从字符串中删除空格和特殊字符

4

如何从字符串中删除空格特殊字符?

我在谷歌上搜索时没有找到一个可行的答案,大多数与其他语言有关,但并不是C语言。其中大部分提到了使用正则表达式,但这并非C标准。

删除简单的空格很容易:

 char str[50] = "Remove The Spaces!!";

接下来是一个带有if语句的简单循环:

if (str[i] != ' ');

输出将会是:
RemoveTheSpaces!!

我应该在if语句中添加什么内容,以便它能够识别特殊字符并将其删除?

我的特殊字符定义:

Characters not included in this list: 
A-Z a-z 0-9

在C语言中,字符串处理并不总是有趣的。将字符串视为一个char数组。您可以用b替换a,但没有简单的方法从数组中删除字符索引,因此仍然会留下空洞。虽然,如果只是为了打印,您可以遍历数组,如果它不在ascii值范围内的a-zA-Z0-9,则跳过执行任何操作并转到下一个字符。在我看来,这通常是可能时最容易做的事情。否则,您需要复制到新缓冲区。 - Jite
7个回答

8

这可能不是最高效的方法,但它可以相对快速地完成工作。

注意:此代码需要包含<string.h><ctype.h>

char str[50] = "Remove The Spaces!!";
char strStripped[50];

int i = 0, c = 0; /*I'm assuming you're not using C99+*/
for(; i < strlen(str); i++)
{
    if (isalnum(str[i]))
    {
        strStripped[c] = str[i];
        c++;
    }
}
strStripped[c] = '\0';

2
你忘记了对strStripped进行NUL终止:在循环之后加上strStripped[c]='\0'; - Heath Hunnicutt
如果您假定使用 C99 之前的版本,则 // 风格的注释也不被支持。 - user405725
不要用双引号,真的,用单引号 :) - Jite
2
请注意,在循环条件中使用 strlen() 会导致糟糕的(二次)性能,而不是线性性能。请使用 int len = strlen(str);,然后在循环条件中测试 len - Jonathan Leffler
@JonathanLeffler 嗯,就像我说的不是最高效的方法,但它能完成任务。 - user1120369
显示剩余2条评论

1

使用if语句:

if (str[i] != ' ');

通过一些逻辑(字符必须在a-z或A-Z或0-9范围内):

If ( !('a' <= str[i] && 'z' >= str[i]) &&
     !('A' <= str[i] && 'Z' >= str[i]) &&
     !('0' <= str[i] && '9' >= str[i])) then ignore character.

1
你知道你可以通过删除“!”并将“&&”替换为“||”来简化逻辑。你已经否定了表达式 :) - Jite
1
这是真的哈哈...我只是按照我自己理解自然的方式编写它。因为某种原因,我更喜欢使用and而不是or...我可能很奇怪。 - George Mitchell

1

这只是一个愚蠢的建议。

char ordinary[CHAR_MAX] = {
    ['A']=1,['B']=1,['C']=1,['D']=1,['E']=1,['F']=1,['G']=1,['H']=1,['I']=1,
    ['J']=1,['K']=1,['L']=1,['M']=1,['N']=1,['O']=1,['P']=1,['Q']=1,['R']=1,
    ['S']=1,['T']=1,['U']=1,['V']=1,['W']=1,['X']=1,['Y']=1,['Z']=1,

    ['a']=1,['b']=1,['c']=1,['d']=1,['e']=1,['f']=1,['g']=1,['h']=1,['i']=1,
    ['j']=1,['k']=1,['l']=1,['m']=1,['n']=1,['o']=1,['p']=1,['q']=1,['r']=1,
    ['s']=1,['t']=1,['u']=1,['v']=1,['w']=1,['x']=1,['y']=1,['z']=1,

    ['0']=1,['1']=1,['2']=1,['3']=1,['4']=1,['5']=1,['6']=1,['7']=1,['8']=1,
    ['9']=1,
};

int is_special (int c) {
    if (c < 0) return 1;
    if (c >= CHAR_MAX) return 1;
    return !ordinary[c];
}

void remove_spaces_and_specials_in_place (char *str) {
    if (str) {
        char *p = str;
        for (; *str; ++str) {
            if (!is_special(*str)) *p++ = *str;
        }
        *p = '\0';
    }
}

C99指定初始化器的良好使用。 - Jonathan Leffler

1

有数百万种不同的方法可以完成这个任务。这里只是一个示例,它不使用任何额外的存储,并且“原地”执行了不需要的字符删除:

#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>

static void my_strip(char *data)
{
    unsigned long i = 0; /* Scanning index */
    unsigned long x = 0; /* Write back index */
    char c;

    /*
     * Store every next character in `c` and make sure it is not '\0'
     * because '\0' indicates the end of string, and we don't want
     * to read past the end not to trigger undefined behavior.
     * Then increment "scanning" index so that next time we read the
     * next character.
     */
    while ((c = data[i++]) != '\0') {
        /* Check if character is either alphabetic or numeric. */
        if (isalnum(c)) {
            /*
             * OK, this is what we need. Write it back.
             * Note that `x` will always be either the same as `i`
             * or less. After writing, increment `x` so that next
             * time we do not overwrite the previous result.
             */
            data[x++] = c;
        }
        /* else — this is something we don't need — so we don't increment the
           `x` while `i` is incremented. */
    }
    /* After all is done, ensure we terminate the string with '\0'. */
    data[x] = '\0';
}

int main()
{
    /* This is array we will be operating on. */
    char data[512];

    /* Ask your customer for a string. */
    printf("Please enter a string: ");

    if (fgets(data, sizeof(data), stdin) == NULL) {
        /* Something unexpected happened. */
        return EXIT_FAILURE;
    }

    /* Show the customer what we read (just in case :-)) */
    printf("You have entered: %s", data);

    /*
     * Call the magic function that removes everything and leaves
     * only alphabetic and numberic characters.
     */
    my_strip(data);

    /*
     * Print the end result. Note that newline (\n) is there
     * when we read the string
     */
    printf("Stripped string: %s\n", data);

    /* Our job is done! */
    return EXIT_SUCCESS;
}

我在代码中添加了许多注释,希望它们足够清晰,不需要解释。希望能对你有所帮助。祝好运!


1
#include <stdio.h>
#include <string.h>

main()
{
    int i=0, j=0;
    char c;
    char buff[255] = "Remove The Spaces!!";

    for(; c=buff[i]=buff[j]; j++){
       if(c>='A' && c<='Z' || c>='a' && c<='z' || c>='0' && c<='9'){
           i++;
       }
    }

    printf("char buff[255] = \"%s\"\n", buff);
}

1
只是一个建议...通过向代码添加注释并可能显示输出,可以改进此答案。 - Mahonri Moriancumer
现在我看到,如果一行中有多个特殊字符,代码将把它们留在结果字符串中,始终是该序列中每两个字符对中的第二个。由于指令“buff[i]=buff[++j];”存在错误,因为它没有考虑到可能会有两个或更多连续的特殊字符。而且变量“i”只应在源中“j”索引处的字符有效时才增加,而不是总是增加。 - Kelton Santos
所以要更正代码: 1- 删除else中的指令,只留下“if”; 2- 不要增加“i”,在每次迭代结束时(只增加“j”)。 3- 在“buff [i] = buff [j];”指令之后增加“i”,或者用“buff [i ++] = buff [j];”替换此指令。 结果将是一个非常类似于我编辑Jonathan Leffler编写的代码的代码,只是在那个代码中,我忘记在“if”的条件中包括源字符串终止符,以便将终止符作为有效字符复制到结果字符串中。 - Kelton Santos
我认为这是从字符串中删除特殊字符的代码最有效的版本。 唯一可能提高效率的改进是在“for”循环中将测试指令(“c=buff[i]=buff[j];”)替换为“c=buff[j];”,以便尽量减少从“j”索引到字符串的“i”索引复制特殊字符的不必要副本,并在“for”完成后将空终止符放在最终字符串的“i”处。 但是,由于我喜欢更紧凑的代码,所以我就这样做了。 希望你喜欢它。 - Kelton Santos
忘记我在这条评论上面说的话。那个指令就在那里。因为从“j”到“i”索引的字符副本必须存在,也就是说,它无论如何都会完成。不同之处在于,这种方式使代码保持更紧凑,而如果我在“if”内部进行复制,则代码会更少效率,因为特殊字符的复制总是会发生,即使在这些情况下“i”没有增加。但它也很有用,因为它在进行更改后放置了空终止符,而不是在“for”完成后才这样做。 - Kelton Santos

1
include < stdio.h >

int main()
{
    char a[100];

    int i;
    printf("Enter the character : ");
    gets(a);
    for (i = 0; a[i] != '\0'; i++) {
        if ((a[i] >= 'a' && a[i] <= 'z') || (a[i] >= 'A' && a[i] <= 'Z') 
             || (a[i] - 48 >= 0 && a[i] - 48 <= 9)) {
            printf("%c", a[i]);
        } else {
            continue;
        }
    }
    return 0;
}

0

这是ASCII码范围

字符: 十进制

0:48, 9:57
A:65, Z:90
a:97, z:122

试试这个:

char str[50] = "Remove The Spaces!!";

int i =0;
for(; i<strlen(str); i++)
{
    if(str[i]>=48 && str[i]<=57 || str[i]>=65 && str[i]<=90 || str[i]>=97 && str[i]<=122)
  //This is equivalent to
  //if(str[i]>='0' && str[i]<='9' || str[i]>='A' && str[i]<='Z' || str[i]>='a' && str[i]<='z')
        printf("alphaNumeric:%c\n", str[i]);
    else
    {
        printf("special:%c\n", str[i]);
        //remove that
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接