【问题标题】:A program that prints even and odd characters from a string从字符串中打印偶数和奇数字符的程序
【发布时间】:2017-11-13 19:48:35
【问题描述】:

这是家庭作业

我必须编写一个程序,要求用户输入一个字符串,然后我的程序会将输入的字符串中的偶数和奇数分开。这是我的程序。

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

int main(void) {
    char *str[41];
    char odd[21];
    char even[21];
    int i = 0; 
    int j = 0;
    int k = 0;

    printf("Enter a string (40 characters maximum): ");
    scanf("%s", &str);

    while (&str[i] < 41) {
        if (i % 2 == 0) {
            odd[j++] = *str[i];
        } else {
            even[k++] = *str[i];
        }
        i++;
    }

    printf("The even string is:%s\n ", even);
    printf("The odd string is:%s\n ", odd);

    return 0;
}

当我尝试编译我的程序时,我收到两个警告:

  1. 对于我的scanf,我得到"format '%s' expects arguments of type char but argument has 'char * (*)[41]"。我不确定这意味着什么,但我认为这是因为数组初始化。

  2. while 循环中,它给了我一个警告,指出指针和整数之间的比较。我也不确定这意味着什么,我认为在 C 中进行这种比较是合法的。

当我编译程序时,我得到了偶数和奇数字符串的随机字符。

任何帮助将不胜感激!

【问题讨论】:

  • scanf("%s" , &amp;str); -> scanf("%s" , str);
  • char *str[41]; => char str[41]; 然后删除 str (*str) 的所有取消引用
  • scanf("%s" , &amp;str); -> scanf("%40s" , str);
  • if (i % 2 == 0) { odd[j++] = str[i]; 看起来应该是 if (i % 2 == 0) { even[j++] = str[i];
  • 请编辑您的答案,因为您想打印奇数或偶数的字符,而不是值:)

标签: c arrays string


【解决方案1】:

这个声明是错误的:

char *str[41];

您声明了 41 个未初始化的字符串。你想要:

char str[41];

然后,scanf("%40s" , str);,没有&amp; 并限制输入大小(安全)

然后循环(你的while (str[i]&lt;41) 是错误的,它可能会立即结束,因为字母从 65 开始(“A”的 ascii 代码)。你想测试 i 与 41 但测试 str[i] 与 @ 987654329@ 代替,否则如果字符串不完全是 40 字节长,则在 oddeven 字符串之一中的 nul-termination char 后得到所有垃圾)

while (str[i]) {
    if (i % 2 == 0) {
        odd[j++] = str[i];
    } else {
        even[k++] = str[i];
    }
    i++;
}

如果你想使用指针(赋值要求),只需像以前一样定义str

char str[41];

如上所示扫描其上的输入值,然后指向它:

char *p = str;

现在您在缓冲区上定义了一个指针,如果您需要使用尊重而不是索引访问,您可以这样做:

while (*p) { // test end of string termination
    if (i % 2 == 0) {  // if ((p-str) % 2 == 0) { would allow to get rid of i
        odd[j++] = *p;
    } else {
        even[k++] = *p;
    }
    p++;
    i++;
}

(我们必须增加 i 以进行偶数/奇数测试,否则我们将不得不测试 p-str 偶数)

aaa 和最后一个经典错误(感谢最后一分钟的 cmets),evenodd 不是空终止的,因此在打印它们时有在最后得到垃圾的风险,您需要:

even[k] = odd[j] = '\0';

(如another answer所说,检查偶数和奇数的概念,预期结果可能相反)

【讨论】:

  • 我没有收到while (str[i] &lt; 41)
  • 你是对的,OP 必须测试 nul 终止。我在上次重写时添加了安全检查,但
  • 注意:OP;s printf("The even string is:%s\n ", even); 正在打印一个肯定不是空字符终止的数组。
  • @Jean-FrançoisFabre:好的,但是当您使用相同的标识符 str 作为不同类型的 OP 时,会造成混淆。我会使用p 作为指针,并保持str 作为包含字符串的数组。
  • @chqrlie 我最后的指针解决方案也是错误的,因为 i 不再增加。我把它加回来了,这里用指针算术听起来有点矫枉过正。
【解决方案2】:

您的代码存在多个问题:

  • 您定义了一个指针数组 char *str[41],而不是一个 char 数组。
  • 您应该将数组传递给scanf 而不是其地址:当传递给函数时,数组衰减为指向其第一个元素的指针。
  • 您应该限制scanf 读取的字符数。
  • 您应该迭代直到字符串的结尾,而不是数组的所有元素,尤其是(&amp;str[i] &lt; 41),它将ith 元素的地址与值41 进行比较,这是没有意义的。字符串的结尾是空终止符,可以用(str[i] != '\0') 进行测试。
  • 您应该读取来自strstr[i] 的字符。
  • 您应该空终止 evenodd 数组。

这是修改后的版本:

#include <stdio.h>

int main(void) {
    char str[41];
    char odd[21];
    char even[21];
    int i = 0; 
    int j = 0;
    int k = 0;

    printf("Enter a string (40 characters maximum): ");
    if (scanf("%40s", str) != 1)
        return 1;

    while (str[i] != '\0') {
        if (i % 2 == 0) {
            odd[j++] = str[i];
        } else {
            even[k++] = str[i];
        }
        i++;
    }
    odd[j] = even[k] = '\0';

    printf("The even string is: %s\n", even);
    printf("The odd string is: %s\n", odd);

    return 0;
}

请注意,您对偶数和奇数字符的解释假定偏移量为 1,即:第一个字符是奇数字符。这与 C 方法不一致,在 C 方法中,偶数字符将被解释为与字符串开头有偶数偏移,从 0 开始。

【讨论】:

  • 只是一个问题 - 对于偶数/奇数大,我们谈论的是 ASCII 值还是字符 '0' 到 '9' - 应该忽略 'A' 等...
  • @chqrlie "你应该迭代直到字符串的结尾,而不是所有字符":OP 可能是这个意思,但实际上 OP 测试 str[i] 对 41,所以循环可能会立即结束,除非输入空格或其他较低的 ASCII 字符。起初我也不明白为什么 OP 会这样做......
  • @Jean-FrançoisFabre:确实,这种比较是扭曲且毫无意义的。 OP实际上将str[i]的地址与41进行比较...
【解决方案3】:

许多答案都准备好了,指出原始代码的问题。

以下是一些减少内存使用的想法,因为 2 个数组 odd[], even[] 不是需要

看到“偶数”字符后,将它们打印出来。
当看到“奇数”字符时,将它们移动到数组的第一部分。

替代打印:如果代码使用"%.*s",则数组不需要空字符终止。

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

int main(void) {
  char str[41];

  printf("Enter a string (40 characters maximum): ");
  fflush(stdout);
  if (scanf("%40s", str) == 1) {
    int i;
    printf("The even string is:");
    for (i = 0; str[i]; i++) {
      if (i % 2 == 0) {
        str[i / 2] = str[i];  // copy character to an earlier part of `str[]`
      } else {
        putchar(str[i]);
      }
    }
    printf("\n");
    printf("The odd string is:%.*s\n ", (i + 1) / 2, str);
  }
  return 0;
}

或者干脆

printf("The even string is:");
for (int i = 0; str[i]; i++) {
  if (i % 2 != 0) {
    putchar(str[i]);
  }
}
printf("\n");
printf("The odd string is:");
for (int i = 0; str[i]; i++) {
  if (i % 2 == 0) {
    putchar(str[i]);
  }
}
printf("\n");

【讨论】:

    【解决方案4】:

    这是你的解决方案:)

    #include <stdio.h>
    #include <string.h>
    
    int main(void) 
    {
    
        char str[41]; 
        char odd[21];
        char even[21];
        int i = 0; 
        int j = 0;
        int k = 0;
    
        printf("Enter a string (40 characters maximum): ");
        scanf("%s" , str); 
    
        while (i < strlen(str)) 
        {
            if (i % 2 == 0) {
                    odd[j++] = str[i];
            } else {
                    even[k++] = str[i];
            }
            i++;
        }
        odd[j] = '\0'; 
        even[k] = '\0';
    
        printf("The even string is:%s\n " , even);
    
        printf("The odd string is:%s\n " , odd);
    
        return 0;
    }
    

    解决了声明、扫描字符串值、while循环条件和数组元素赋值的错误。 :)

    【讨论】:

    • @chux:实际上,哪个数组不能以空值结尾取决于输入的长度;-)
    • 哦,谢谢你的建议。在这里..我纠正它
    • 有时很容易快速获得解决方案,而不是过多的解释。那是我的尝试:D ..他一定会解决问题的。
    • 如果输入的字符串不完全是 40 个字符,则此解决方案是错误的。
    猜你喜欢
    • 1970-01-01
    • 2017-06-21
    • 2017-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多