从字符串中删除错误字符的C代码

从字符串中删除错误字符的C代码,c,linux,pointers,C,Linux,Pointers,这段代码应该删除给定字符串中的任何前导空格,并且它工作正常。然后,似乎没有任何理由,它开始删除单词中间的字符。在本例中,给出了单词“CHEDDAR”,它没有前导空格,因此应该像输入一样传回,但是它返回“CHEDDR”,我不知道为什么。有人知道这是怎么可能的吗?我想这与指针和内存有关,但我对C语言不太流利,我需要一些帮助。在莱尔河上奔跑。谢谢 #include <stdio.h> #include <stdlib.h> #include <string.h>

这段代码应该删除给定字符串中的任何前导空格,并且它工作正常。然后,似乎没有任何理由,它开始删除单词中间的字符。在本例中,给出了单词“CHEDDAR”,它没有前导空格,因此应该像输入一样传回,但是它返回“CHEDDR”,我不知道为什么。有人知道这是怎么可能的吗?我想这与指针和内存有关,但我对C语言不太流利,我需要一些帮助。在莱尔河上奔跑。谢谢

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

#define REMOVE_LEADING_SPACES(input)                       \
           {                                            \
           stripFrontChar( input, ' ' );                         \
           }


char *stripFrontChar(char *startingString, char removeChar) {
    while (*startingString == removeChar)
        strcpy(startingString, startingString + 1);
    return (startingString);
}

void main(argc, argv)
    char **argv;int argc; {
    char *result = "CHEDDAR";
    REMOVE_LEADING_SPACES(result);
    printf("%s\n", result);
}
#包括
#包括
#包括
#定义删除前导空格(输入)\
{                                            \
stripFrontChar(输入“”)\
}
char*stripFrontChar(char*startingString,char removeChar){
while(*startingString==removeChar)
strcpy(启动字符串,启动字符串+1);
返回(起始字符串);
}
空干管(argc、argv)
字符**argv;int-argc;{
char*result=“切达”;
删除前导空格(结果);
printf(“%s\n”,结果);
}
编辑:现在有点晚了,但根据我的评论,我应该表明这个词(我用切达作为例子)是从一个文件中读取的,而不是我代码中显示的文字。我试图简化这个问题,现在我意识到这是一个完全不同的场景,所以我不应该这样做。谢谢,看来我需要用memmov


EDIT2:实际上有一个类似“CHEDDAR”的空格,所以我只需要将它改为memmov,再次感谢大家。

您使用重叠的内存区域复制字符串:

strcpy(startingString, startingString + 1);
根据C标准:

7.24.2.3 strcpy功能

如果复制发生在重叠的对象之间,则行为未定义

您需要使用
memmov
(并提供适当的长度),或者需要自己移动字符。如果从计算需要删除的字符开始,然后一次性复制所有字符,还可以提高性能

Joop Eggen在评论中指出的另一个问题是:

char *result = "CHEDDAR";
不允许您修改字符串文字。 如果试图删除前导字符,则会调用未定义的行为

你应该把这个改成

char result[] = "CHEDDAR";
由于示例字符串不包含前导空格,因此还不会引起问题。但是您应该修复它,尽管如此

这段代码

strcpy(startingString, startingString + 1);
复制重叠的字符串

Per:

strcpy
函数将
s2
指向的字符串(包括终止的空字符)复制到
s1
指向的数组中如果复制发生在重叠的对象之间,则行为未定义。


您正在调用未定义的行为。

虽然标识您正在复制重叠字符串的答案标识未定义的行为,但另一个原因是您使用了文本字符串,并且在大多数平台上,这些字符串是不可变的,将导致程序中止

而不是:

char *result = "CHEDDAR";
使用:


(注意:查看大多数strcpy函数的实现方式,即当看到源字符串的空字符时终止的循环,然后使用的重叠仍将看到源字符串的空字符并将其放置在目标中(向下复制)。反过来复制(向上复制)将不再看到空终止符,因为它将被覆盖,并且可能会继续复制到目标字符串之外。)

在您的情况下,如果不需要修改也不进行alloc,您只需要找到开始,而不复制任何内容

char *stripFrontChar(char *startingString, char removeChar) {
    for( ; *startingString == removeChar; startingString++)
        ;
    return (startingString);
}
但是您必须使用stripFrontChar()的返回


我不确定这是怎么发生的,但“目标…不应该在内存中与源重叠”您应该能够删除单个副本中的所有前导空格,而不是重复复制:计算出所需的偏移量,然后执行单个复制/移动。memmove可以工作,因为它允许源和目标之间的重叠,或者您可以自己循环复制字符。另外,您指向的是常量切达。@Rup,它当然不是官方的“文档”旁注:您真的应该放弃在
main
中使用的那些古老的K&R样式的参数列表。而且
main
通常应该有返回类型
int
谢谢,但是在没有前导空格的情况下它是如何进入while循环的呢?这就是我在你的问题下的最新评论的意思。你真的确定你没有从文件中读取空格吗?啊,是的,我错过了,很抱歉,比strcpy或memmov更好的解决方案。
char *stripFrontChar(char *startingString, char removeChar) {
    for( ; *startingString == removeChar; startingString++)
        ;
    return (startingString);
}
printf("%s\n", stripFrontChar(result));