首页 > 解决方案 > 如何从 char 数组中清除单个字符?

问题描述

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

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

使用空字符的示例代码

#include <stdio.h>

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

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

#include <stdio.h>

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

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

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

标签: carraysstring

解决方案


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

当你读取一个空格时使用一个简单int的作为标志变量(例如int in;)并设置in = 1;(true),然后当你读取一些不是空格的东西时设置in = 0;(false)来指示你在字符串中读取的当前“状态”(例如在空格中或不在空格中)然后,tab当您在阅读一系列空格后遇到第一个非空格字符时(例如,当您从 更改为 时in = 1;) ,您只需编写 a in = 0;

当您遍历字符串中的每个字符时,只需保留两个指针,一个指向您当前的读取位置(例如p),一个指向您当前的写入位置(例如wp)。所以你有一个读指针和写指针。将两者都初始化到字符串的开头,然后在每次迭代时推进读取指针,如果不是空格,则写入每个字符不变,或者禁止写入所有空格字符并写入 a '\t'whenin1to更改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 */
}

注意:上面会将所有前导空格转换为 atab以及所有尾随空格转换为 a tab。如果要去除前导空格和尾随空格,您可以根据需要进行修改以更改该行为——这留给您)

花时间研究逻辑并了解它是如何工作的。最好的方法是将要转换的字符串写在一张纸上,然后在每次迭代时跟踪p和指向。wp(没有捷径,不要在屏幕上做,拿出一张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 程序运行您的输出,例如hexdumpor od(每个操作系统都有类似的东西)

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

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


推荐阅读