简体   繁体   English

如何清除char数组中的单个字符?

[英]How can I clear a single character from a char array?

I'm trying to remove a single character from an array, without using the standard library functions like strcpy. 我正在尝试从数组中删除单个字符,而不使用诸如strcpy之类的标准库函数。 how could I go about this? 我该怎么办?

I want to replace a consecutive set of spaces with a tab, and while I can replace one of the space with a tab, I don't know how to get rid of the rest of the spaces in the array. 我想用一个制表符替换连续的一组空格,虽然我可以用一个制表符替换一个空间,但是我不知道如何摆脱数组中其余的空格。 I can typecast "" into a character, and that'll remove them, but gcc throws up a warning about "cast from pointer to integer of different size". 我可以将“”转换成一个字符,然后将其删除,但是gcc会发出一条警告:“从指针转换为不同大小的整数”。 it runs fine, but the warning makes me think there's a better way of doing this. 它运行正常,但是警告使我认为有更好的方法可以做到这一点。 using '' doesn't work, because gcc throws the "empty character constant" error. 使用”不起作用,因为gcc会引发“空字符常量”错误。

example code using empty character 使用空字符的示例代码

#include <stdio.h>

int main() {
    char str[10] = "gay\n\0";
    str[1] = '';
    printf("%s", str);
}

example code using empty string, casted into char 使用空字符串的示例代码,转换为char

#include <stdio.h>

int main() {
    char str[10] = "gay\n\0";
    str[1] = (char) "";
    printf("%s", str);
}

the first example throws out the error "empty character constant" 第一个示例抛出错误“空字符常量”

the second example works, but throws the warning "cast from pointer to integer of different size" 第二个示例可行,但是抛出警告“从指针到不同大小的整数的转换”

Since you are determined to do this without the benefit of standard library functions, the easiest way to accomplish replacing all series of spaces (including a series of 1) with a tab character ( '\\t' ) is to loop over your string using a variable to keep track of whether you are currently in or out of a series of spaces. 由于您决心不使用标准库功能来执行此操作,因此用tab符( '\\t' )替换所有系列空格(包括一系列1)的最简单方法是使用变量,以跟踪您当前是一系列空格还是不在一系列空格中。

Use a simple int as a flag variable (eg int in; ) and set in = 1; 使用简单的int作为标记变量(例如int in; )并设置in = 1; (true) when you read a space, and then whenever you read something not a space set in = 0; (true)当您读取一个空格,然后每当您读取某些内容而不是in = 0;设置的空格时in = 0; (false) to indicate the current "state" of your read within the string (eg either in spaces or not in spaces) You then simply write a tab when you encounter the first non-space character after reading a series of spaces (eg when you change from in = 1; to in = 0; ). (false)表示字符串中读取的当前“状态”(例如,在空格中还是不在空格中),然后在读取一系列空格后遇到第一个非空格字符时,只需编写一个tab符(例如您从in = 1;更改为in = 0; )。

As you loop over each character in the string, just keep two pointers, one to your current read-position (say p ) and one to your current write-position (say wp ). 当您遍历字符串中的每个字符时,只需保留两个指针,一个指针指向您当前的读取位置(例如p ),另一个指向您当前的写入位置(例如wp )。 So you have a read-pointer and write-pointer. 因此,您有一个读指针和写指针。 Initialize both to the beginning of your string and then advance your read-pointer every iteration either writing every character unchanged if not a space, or suppressing the write of all space character and writing a '\\t' when in changes from 1 to 0 . 初始化既您的字符串的开头,然后每次迭代推动你读指针或者写的每一个字符不变,如果没有空间,或抑制所有空格字符的写,写一个'\\t'in变化,从10 Seeing it helps. 看到它会有所帮助。

You can do something like: 您可以执行以下操作:

/** spaces2tab will convert all series of spaces in s to a '\t'.
 *  s must be mutable (writeable) and not const or a string-literal.
 */
void spaces2tab (char *s)
{
    char *p = s,    /* pointer to s -- for reading */
        *wp = s;    /* pointer to s -- for writing */
    int in = 0;     /* flag -- in/out series of spaces */

    while (*p) {                /* loop over each char in s */
        if (*p == ' ') {        /* if char is ' ' set in to 'true' */
            in = 1;
        }
        else {                  /* if other than space */
            if (in) {           /* if was series of spaces */
                *wp++ = '\t';   /* write a tab */
                in = 0;         /* set in 'false' */
            }
            *wp++ = *p;         /* write current char */
        }
        p++;                    /* advance to next char */
    }
    if (in)                     /* if was in series of spaces at end */
        *wp++ = '\t';           /* add tab at end */

    *wp = *p;                   /* nul-terminate at current char */
}

( note: the above will convert all leading spaces to a tab as well as all trailing spaces to a tab . You can modify as needed to change that behavior if you want to strip the leading and trailing spaces -- that is left to you) 注意:上面的代码会将所有前导空格都转换为tab ,并将所有尾随空格都转换为tab 。如果要删除前导空格和尾随空格,可以根据需要进行更改以更改此行为-留给您)

Take the time to work though the logic and understand how it is working. 花一些时间来研究逻辑,并了解其工作原理。 The best way to do that is write your string to be converted out on a sheet of paper and then track were p and wp point on each iteration. 最好的方法是将要转换的字符串写在纸上,然后在每次迭代中跟踪pwp点。 (no shortcuts, don't do it on the screen, take out an 8.5x11 sheet of paper and pencil and write it out) (没有快捷方式,不要在屏幕上执行此操作,取出一张8.5x11的纸和铅笔并写下来)

A full example that takes the string to convert as your first argument to your program (or uses a simple default string of " this is a test " if no argument is given) could be similar to the following (note a manual strcpy was written ( scopy ) to comport with your no library function requirement to copy characters to the string to be converted): 一个将字符串转换为程序的第一个参数的完整示例(或者,如果未提供任何参数,则使用简单的默认字符串" this is a test " ),可能类似于以下示例(请注意,已编写了手动strcpyscopy )以符合您对库函数的要求,即将字符复制到要转换的字符串):

#include <stdio.h>

#define MAXC 128

/** spaces2tab will convert all series of spaces in s to a '\t'.
 *  s must be mutable (writeable) and not const or a string-literal.
 */
void spaces2tab (char *s)
{
    char *p = s,    /* pointer to s -- for reading */
        *wp = s;    /* pointer to s -- for writing */
    int in = 0;     /* flag -- in/out series of spaces */

    while (*p) {                /* loop over each char in s */
        if (*p == ' ') {        /* if char is ' ' set in to 'true' */
            in = 1;
        }
        else {                  /* if other than space */
            if (in) {           /* if was series of spaces */
                *wp++ = '\t';   /* write a tab */
                in = 0;         /* set in 'false' */
            }
            *wp++ = *p;         /* write current char */
        }
        p++;                    /* advance to next char */
    }
    if (in)                     /* if was in series of spaces at end */
        *wp++ = '\t';           /* add tab at end */

    *wp = *p;                   /* nul-terminate at current char */
}

char *scopy (char *dest, const char *src)
{
    char *p = dest;             /* pointer to dest */
    *dest = 0;                  /* set dest to empty-string */

    if (!src)                   /* valdiate src not NULL or return NULL */
        return NULL;

    do {                        /* loop copying chars from src to p */
        *p++ = *src;            /* (it will copy the nul-termining char) */
    } while (*src++);

    return dest;                /* return pointer to indicate success */
}

int main (int argc, char **argv) {

    char str[MAXC] = "",
        *p = argc > 1 ? argv[1] : "  this   is a      test    ";

    if (!scopy (str, p))
        return 1;

    spaces2tab (str);

    printf ("original  : '%s'\nconverted : '%s'\n", p, str);
}

Example Use/Output 使用/输出示例

$ ./bin/spaces2tab
original  : '  this   is a      test    '
converted : '   this    is      a       test    '

Verification of '\\t' Conversion 验证'\\t'转换

To verify the proper conversion, run your output through a hex-dump program like hexdump or od (each OS will have something similar) 要验证正确的转换,请通过hexdumpod这样的hex-dump程序运行输出(每个OS都有类似的东西)

$ ./bin/spaces2tab | hexdump -Cv
00000000  6f 72 69 67 69 6e 61 6c  20 20 3a 20 27 20 20 74  |original  : '  t|
00000010  68 69 73 20 20 20 69 73  20 61 20 20 20 20 20 20  |his   is a      |
00000020  74 65 73 74 20 20 20 20  27 0a 63 6f 6e 76 65 72  |test    '.conver|
00000030  74 65 64 20 3a 20 27 09  74 68 69 73 09 69 73 09  |ted : '.this.is.|
00000040  61 09 74 65 73 74 09 27  0a                       |a.test.'.|
00000049

Above you can confirm all series of spaces (hex 20 ) have been converted to a single tab character (hex 09 ). 在上方,您可以确认所有系列空格(十六进制20 )都已转换为单个tab符(十六进制09 )。

Let me know if you have further questions. 如果您还有其他问题,请告诉我。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM