【问题标题】:'N' character appears in the end of the string'N' 字符出现在字符串的末尾
【发布时间】:2018-09-01 20:04:28
【问题描述】:

我是 C 新手,在尝试输入字符串时遇到了问题。更具体地说,当打印字符串时,字符“N”出现在它的末尾,因此,我无法测量确切的字符数。这是我的代码:

int main()
{
    int j = 0;
    char c[15];
    printf("Give surname: ");
    scanf(" %s", c);
    for (int i = 0; i<sizeof(c) / sizeof(c[1]); i++)
    {
        if (isalpha(c[i]))
        {
            printf("%c ", c[i]);
            j++;
        }
    }
    printf("\nNumber of characters: %d", j);

    return 0;
}

例如:如果输入是“john”,那么我会得到以下输出:

我做错了什么?

【问题讨论】:

  • 您的循环迭代的字符数远远多于从stdin 读取的字符数。
  • 一个可能的原因是scanf 在您输入回复时在字符串末尾添加了一个 0 字节,但您并没有对此进行检查,而是输出了 15 个字符无论。您应该了解 C 中的字符串函数,例如 strlen,而不是手动输出字符,也许只需让 printf 为您完成?
  • 你没有初始化c,所以它在scanf()设置的部分后面包含不确定的数据。如果您通过一个明显打印每个字符的程序发送输出(例如odxxd -g 1),您会在输出中看到很多其他字符——一个空字节和一些其他非打印(控制)字符,还有比你想象的更多的空格。
  • 发布的代码无法编译!。它似乎缺少所需头文件的包含语句。您是否希望我们猜测您的实际代码包含哪些头文件?
  • 运算符sizeof 返回一个size_t,(通常是一个无符号长整数)但是,发布的代码将该值与int 进行比较

标签: c string scanf


【解决方案1】:

那是因为您在比实际字符串长的字符数组上使用了sizeof 运算符。 你可以使用string.h中的strlen,如上所述,或者简单地遍历字符直到\0,就像这样:

char * p = c;
while(*p++)
    if (isalpha(*p))
        printf("%c ", *p);

如果您对字符数感兴趣,您可以减去指针。

【讨论】:

    【解决方案2】:

    你的循环限制是错误的。它导致您评估不确定数据。特别错误的事情:

    • 不检查scanf 是否成功
    • 未指定长度受限的格式字符串以避免c[] 数组溢出。
    • 如前所述,迭代整个数组,而不仅仅是您假设已成功读取的数据。

    所有这些都可以修复,其中一些是微不足道的。

    • 检查scanf 是否返回1
    • 由于您的 c 数组是 15 个字符,并且必须为终止的 nullchar 考虑空格,因此您的格式字符串使用 %14s
    • 要么使用strlen 作为 for 的限制(以某种方式,将其保存到临时或直接在条件子句中)或使用指针。

    关于最后一项,我更喜欢后者,因为您只扫描字符串一次strlen 将扫描字符串以找到终止符,从而计算长度并返回它。然后在迭代期间再次扫描它。您可以通过简单地不使用 strlen 扫描来消除它,而是使用指针,并在发现终止符时停止扫描。

    改写了,结果是这样的:

    #include <stdio.h>
    #include <ctype.h>
    
    int main()
    {
        char c[15];
        int j = 0;
    
        printf("Give surname: ");
        if (scanf("%14s", c) == 1)
        {
            for (const char *p = c; *p; ++p)
            {
                if (isalpha(*p))
                {
                    printf("%c ", *p);
                    ++j;
                }
            }
    
            printf("\nNumber of characters: %d", j);
        }
    
        return 0;
    }
    

    输入

    123john456
    

    输出

    j o h n
    Number of characters: 4
    

    【讨论】:

      【解决方案3】:

      尝试改用strlen() 函数。它会检查实际字符串末尾的空终止字符(与完整数组相反,它可能在空值之后包含垃圾字符-终止字符)。

      int length = strlen(c);
      for (int i = 0; i < length; i++){
      

      记得#include &lt;string.h&gt;

      在这里查看它的实际效果: https://repl.it/repls/SugaryUnfoldedCleaninstall

      如果您想知道为什么需要依赖函数来执行此操作,请查看 the source of strlen()。编写这样一个性能良好且在所有情况下都正确的函数比看起来更难。

      进一步阅读
      How to iterate over a string in C

      【讨论】:

      • 最好不要在条件中使用strlen(c)——它可能会被优化,以便只调用一次,但可能不会。 (不过,一般问题诊断是正确的。)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-20
      • 1970-01-01
      • 2016-03-21
      • 1970-01-01
      • 2023-03-29
      相关资源
      最近更新 更多