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

Posted

技术标签:

【中文标题】如何从 char 数组中清除单个字符?【英文标题】:How can I clear a single character from a char array? 【发布时间】:2020-01-10 07:17:05 【问题描述】:

我正在尝试从数组中删除单个字符,而不使用 strcpy 等标准库函数。我该怎么办?

我想用制表符替换一组连续的空格,虽然我可以用制表符替换其中一个空格,但我不知道如何摆脱数组中的其余空格。我可以将“”类型转换为一个字符,这将删除它们,但 gcc 会引发一个关于“从指针转换为不同大小的整数”的警告。它运行良好,但警告让我认为有更好的方法来做到这一点。使用 '' 不起作用,因为 gcc 会抛出“空字符常量”错误。

使用空字符的示例代码

#include <stdio.h>

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

使用空字符串的示例代码,转换为字符

#include <stdio.h>

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

第一个例子抛出错误“空字符常量”

第二个例子有效,但抛出警告“从指针转换为不同大小的整数”

【问题讨论】:

您不需要包含\0。字符串文字已经以空值结尾。此外,您可能想要选择不同的测试字符串。 您需要将该字符后面的所有字符移到前面一个字符。你不能“删除”内存。 str[1] = (char) ""; 无效,因为它尝试从 ""(它是空字符串,char*)到 char 的转换。如果您想在索引1nul-terminate,只需使用str[1] = 0;(或者如果您喜欢字符表示,请使用str[1] = '\0';)。记住双引号表示一个字符串,单引号表示一个字符。 【参考方案1】:

由于您决定在不使用标准库函数的情况下执行此操作,因此用 tab 字符 ('\t') 替换所有空格系列(包括一系列 1)的最简单方法是循环您的字符串使用一个变量来跟踪您当前是 in 还是 out 的一系列空格。

使用简单的int 作为标志变量(例如int in;)并在读取空格时设置in = 1;(真),然后每当您读取非空格的内容时设置in = 0;(假)为指示您在字符串中读取的当前“状态”(例如,在空格中或不在空格中)然后当您在读取一系列空格后遇到第一个非空格字符时(例如,当您更改从in = 1;in = 0;)。

当您遍历字符串中的每个字符时,只需保留两个指针,一个指向您当前的读取位置(例如p),一个指向您当前的写入位置(例如wp)。所以你有一个读指针和写指针。将两者都初始化到字符串的开头,然后在每次迭代时推进读取指针,如果不是空格,则写入每个字符不变,或者当in1 更改时,禁止写入所有空格字符并写入'\t'0。看到它会有所帮助。

你可以这样做:

/** 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 */

(注意:以上内容会将所有前导空格转换为tab,并将所有尾随空格转换为tab。如果您愿意,可以根据需要进行修改以更改该行为去掉前导和尾随空格——留给你)

花时间研究逻辑并了解其工作原理。最好的方法是将要转换的字符串写在一张纸上,然后在每次迭代中跟踪 pwp 点。 (没有捷径,不要在屏幕上做,拿出一张8.5x11的纸和铅笔写出来)

将要转换的字符串作为程序的第一个参数(或使用简单的默认字符串 " this is a test ",如果没有给出参数)的完整示例可能类似于以下内容(注意手册 strcpy 是编写(scopy)以符合您将字符复制到要转换的字符串的无库函数要求):

#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);

使用/输出示例

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

验证'\t'转换

要验证正确的转换,请通过 hex-dump 程序运行您的输出,例如 hexdumpod(每个操作系统都有类似的东西)

$ ./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

您可以在上面确认所有系列的空格(十六进制20)已转换为单个tab 字符(十六进制09)。

如果您还有其他问题,请告诉我。

【讨论】:

以上是关于如何从 char 数组中清除单个字符?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 memset 清除 char 数组 [重复]

清除 char 数组的最佳方案 - memset 与否?

如何从点击通知列表中清除单个通知?

在 C++ 上的函数 gets() 后,字符数组被清除

在 C/C++ 中清除 char 数组的最佳方法是啥?

选择 UITableView 中的行时如何清除文本字段?