【问题标题】:Why does scanf("%[^\n]\n", titre); ask me for a third input为什么 scanf("%[^\n]\n", titre);问我第三个输入
【发布时间】:2020-11-29 17:14:20
【问题描述】:

我在 Win10 上,目前正在学习 C,对于一个简单的练习,我很不理解我的输出 (EKEKEKEKE),该练习要求输入并将相同的字符串作为输出而不带元音。

inputBLABLABLA
EKEKEKE
outputB.L.B.L.B.L.
inputBLABLABLA
outputK.K.K.
int main()
{
    for (int i = 0; i < 2; i = i + 1)
    {

        printf("input");
        char titre[101] = {0};
        scanf("%[^\n]\n", titre);


        int j = 0;
        char t = titre[0];

        printf("output");

        while ((t != '\0') && (j < 101))
        {
            if ((t != 'A')
                && (t != 'E')
                && (t != 'I')
                && (t != 'O')
                && (t != 'U')
                && (t != 'Y')
                && (t != ' '))
            {
                printf("%c.", t);
            }
            j = j + 1;
            t = titre[j];
        }
        if (i == 0)
        {
            printf("\n");
        }
    }
}

【问题讨论】:

  • 我从不使用带有尾随空格规范的scanf,所以我无法解释为什么它行为不端,但如果你将其更改为scanf(" %[^\n]", titre);,那应该会更好。注意% 前面的空格,它过滤了输入缓冲区中留下的任何先前的换行符、空格等。
  • 您根本不应该使用scanf(请参阅stackoverflow.com/questions/58403537/…stackoverflow.com/questions/15664664/scanf-regex-c/… 了解原因)。使用fgets(或getline,如果可用)一次读取用户输入一行。

标签: c scanf


【解决方案1】:

嗯,问题出在scanf() 正则表达式上。主要是您正在吃除换行符以外的所有字符,直到您遇到换行符。但是,在匹配所有 scanf() 之后仍然没有返回,因为它仍然“匹配”更多。通过更改该表达式,使其不匹配换行符而是任意字符(应该是换行符),我可以让它按照您的期望响应。我还稍微修改了您的代码以将某些功能移至另一个功能:


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

#define INPUT_COUNT  2
#define BUFFER_SIZE  100

int is_vowel (char c)
{
    const char *vowels = "AEIOUY ";
    for (const char *s = vowels; *s != '\0'; s++) {
        if (toupper(c) == *s) {
            return 1;
        }
    }
    return 0;
}

int main ()
{
    for (int i = 0; i < INPUT_COUNT; i++) {
        char c, titre[BUFFER_SIZE + 1] = {0};

        // Scan in a line.
        printf("Input:\t");
      
        // %100 <- Limit 100 characters. %c <- Trick to get around newline issue
        scanf(" %100[^\n]%c", titre, &c);

        printf("Output:\t");
        for (int j = 0; j < BUFFER_SIZE && titre[j] != '\0'; j++) {

            if (!is_vowel(titre[j])) {
                printf("%c.", titre[j]);
            }
        }
        putchar('\n');
    }
}

【讨论】:

    【解决方案2】:

    你应该使用 get 来读取这样的字符串:

    int main()
    {
        for (int i = 0; i < 2; i = i + 1)
       {
           printf("input :");
           char titre[101] = {0};
           gets(titre);
           int j = 0;
           char t = titre[0];
           printf("output :");
    
           while ((t != '\0') && (j < 101))
           {
              if ((t != 'A')&&(t != 'E')&&(t != 'I')&&(t != 'O')&&(t != 'U')&&(t != 'Y')&&(t != ' '))
              {
                  printf("%c.", t);
              }
               j = j + 1;
               t = titre[j];
           }
           if (i == 0)
           {
               printf("\n");
           }
        }
      }
    

    【讨论】:

    • 永远不要使用或推荐gets,它不再是标准C库的一部分。请阅读Why is the gets function so dangerous that it should not be used?
    • @WeatherVane 如果你要提出这个问题,你还应该指出 scanf("%[...]"),没有字段宽度,如 OP 的代码所示,与 gets 一样危险,并且出于同样的原因。
    • @zwol 是的,在我之前的评论中被忽略了。
    • @WeatherVane 对不起。那么,我如何读取字符串
    • @MEDLDN getline 如果可能,fgets 否则。 (区别在于getline 使用malloced 缓冲区,因此对行的长度没有限制。但是,它不在ISO C 中,而fgets 是。)
    猜你喜欢
    • 2011-08-30
    • 2014-06-22
    • 1970-01-01
    • 1970-01-01
    • 2017-12-29
    • 2017-07-27
    • 1970-01-01
    • 2021-07-30
    相关资源
    最近更新 更多