从字符串中删除所有字符的代码不起作用 - 但为什么呢?

时间:2017-06-14 18:54:16

标签: c string algorithm

这是我的代码并打印错误。我认为它应该工作正常,但挤压功能有一个错误,我找不到。

#include <stdio.h>

void squeeze(char *s, int c);
int main(void){
    char s[]="kyriacos";
    squeeze(s,'c');
    printf("the new kyriacos is %s",s);
}



void squeeze(char *s, int c){
    int i,j;
    for(i=j=0; s[i]!='0';i++){
        if(s[i]!='c'){
            s[j]=s[i];
            j++;
        }
    }
    s[j]='\0';
}

5 个答案:

答案 0 :(得分:2)

您的功能实现有拼写错误。在本声明的条件下

for(i=j=0; s[i]!='0';i++){

必须使用字符'\0'而不是'0'

for(i=j=0; s[i]!='\0';i++){

此声明还有一个错字

if(s[i]!='c'){

您需要使用参数'c'

,而不是字符c
if(s[i] != c){

考虑到字符串函数通常遵循它们返回指向目标字符串的指针的约定。

因此最好将该函数声明为

char * squeeze(char *s, int c);

同样不使用类型int作为字符串索引的类型,最好使用类型size_t,因为它是标准函数strlen的类型和结果申请运营商sizeof有。

在演示程序中显示了如何实现该功能

#include <stdio.h>

char * squeeze(char *s, int c)
{
    size_t i = 0, j = 0;

    do
    {
        if (s[i] != c)
        {
            if (i != j) s[j] = s[i];
            j++;
        }
    } while (s[i++]);

    return s;
}

int main( void )
{
    char s[] = "kyriacos";
    printf("the new kyriacos is \"%s\"\n", squeeze(s, 'c'));
}

程序输出

the new kyriacos is "kyriaos"

答案 1 :(得分:1)

for不知道何时结束。当它到达你单词的最后一个字母时,它就会继续。解决方案是:i&lt; strlen(s)。要使用strlen,必须在头文件中包含string.h!祝你好运!

for(i=j=0;i < strlen(s);i++)

或者你可以选择

for(i=j=0; s[i]!='\0';i++) // '\0' is the end string character

答案 2 :(得分:1)

你有:

void squeeze(char *s, int c){
    int i,j;
    for(i=j=0; s[i]!='0';i++){
        if(s[i]!='c'){
            s[j]=s[i];
            j++;
        }
    }
    s[j]='\0';
}

'c'是个错误;您想使用变量c。您还需要测试'\0'(而不是'0')来终止循环。

void squeeze(char *s, int c)
{
    int i, j;
    for (i = j = 0; s[i] != '\0'; i++)
    {
        if (s[i] != c)
            s[j++] = s[i];
    }
    s[j] = '\0';
}

空白便宜;使用它们。增量运算符可以在表达式中使用(小心)。

答案 3 :(得分:1)

关注其他好的答案:

@jacoblaw指出了与c类型相关的问题。当char具有负值时,这很重要,但传入的值是int c

void squeeze1(char *s, int c) {
  size_t j = 0;
  for(size_t i=0; s[i]; i++) {
    // This could be comparing a negative `char` against a int value like CHAR_MAX + 10
    if(s[i] != c) {  
      s[j++]=s[i];
    }
  }
  s[j]='\0';
}

void foo() {
  char s[80];
  fgets(s, sizeof s, stdin);
  int ch = fgetchar();  // ch has a value in the `unsigned char` range.
  if (ch != EOF) squeeze1(s, ch);
}
  

C11 7.24字符串处理
  ......对于本子条款中的所有函数,每个字符都应被解释为具有类型unsigned char ...

为了进行比较,标准C库倾向于将char视为unsigned char,因此建议其他方法

void squeeze2(char *s, char c) {

void squeeze3(char *s, int c) {
  ...
    if((unsigned char) s[i] != (unsigned char) c) {  

答案 4 :(得分:-1)

当你通过挤压(s,&#39; c&#39;)时,它只会通过字符串第一个字符的地址。要访问地址处的值,需要取消引用指针(使用*) 要访问下一个值,指针s指向下一个地址使用(s ++),即它指向存储新字符的下一个地址,该字符在1个字节之后。 问题在于循环,你需要访问地址的值 s指向位置的地址,其中&#39; k&#39;存储。
s + 1指向基地址后的1个字节&#39; (因为char存储1个字节。如果它是一个int,它将指向基址+4个字节 。

s + i指向基址+ i字节。

我已更正您的代码。

{{1}}

另请注意,通常当你在一个函数中传递一个char时,它会被相同的数据类型接收。但是因为使用了一个int,所以char&#39; c&#39;在这种情况下99被转换为整数,这是它的ASCII值。所以在循环中,它比较字符是否等于c,机器也将*(s + i)转换为int值并比较它们