【问题标题】:How to limit input length with scanf如何使用 scanf 限制输入长度
【发布时间】:2015-04-02 13:17:48
【问题描述】:

在这个程序中,我采用了一个大小为 [3][4] 的维度字符数组, 只要我为每行输入 3 个字符,它就可以正常工作。

例如:如果我输入 abc abd abd 我会得到相同的输出,但如果我在第一行或第二行或第三行输入更多字母,则会出现错误。

我应该如何检查二维中的空字符?

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

void main()
{
   int i=0; 
   char name[3][4];
   printf("\n enter the names \n");
   for(i=0;i<3;i++)
   {
      scanf( "%s",name[i]); 
   } 

   printf( "you entered these names\n");
   for(i=0;i<3;i++)
   {
      printf( "%s\n",name[i]);
   }
   getch(); 
}

【问题讨论】:

    标签: c arrays scanf


    【解决方案1】:

    正如@SouravGhosh 所指出的,您可以将scanf 限制为"%3s",但如果您不在每次迭代中刷新stdin,问题仍然存在。

    你可以这样做:

    printf("\n enter the names \n"); 
    for(i = 0; i < 3; i++) {
        int c;
        scanf("%3s", name[i]);
        while ((c = fgetc(stdin)) != '\n' && c != EOF); /* Flush stdin */
    }
    

    【讨论】:

    • 好的先生,但是如果我的输入是在一行中提供的呢?sourav ghosh abcde ?
    • 然后,(根据 OP 的要求)程序还需要 2 个输入
    【解决方案2】:

    我应该如何检查二维中的空字符... [我猜有些东西吃掉了其余部分]

    您不需要,至少在当前情况下不需要。

    问题在于您分配内存并将输入放入其中的方法。你的代码有

    char name[3][4];
    

    如果您输入超过三个chars,您将覆盖已分配内存的边界[考虑到\0 的空间]。你必须限制你的scanf() 使用

    scanf("%3s",name[i]);
    

    注意:

    • 将void main() 更改为int main()。在末尾添加return 0。
    • 始终检查scanf() 的返回值以确保正确输入。

    编辑:

    至于逻辑部分,需要吃掉输入单词的剩余部分,从下一个单词的开头开始扫描。

    检查下面的代码[Linux下,所以去掉conio.h和getch()]

    # include <stdio.h>
    # include <ctype.h>
    int main()
    {
            int i=0; char name[3][4];
            int c = 0;
            printf("\n enter the names \n");
            for(i=0;i < 3;i++)
            {
                    scanf( "%3s",name[i]);
                    while(1)   // loop to eat up the rest of unwanted input
                    {          // upto a ' ' or `\n` or `EOF`, whichever is earlier
                        c = getchar();
                        if (c == ' ' || c == '\n' || c == EOF) break;
                    }
            }
            printf( "you entered these names\n");
    
            for(i=0;i<3;i++)
            {
                    printf( "%s\n",name[i]);
            }
        return 0;
    }
    

    【讨论】:

    • 我试过你的代码..但我又遇到了一个问题。如果我在第一行输入 abcd 并在第二行输入 abcd 然后按回车键,我会在第一行得到输出为 abc 并且d 在第二行,abc 在最后一行。我没有输入第三个名字的选项
    • @venkat 我知道,前面那个词的剩余部分正在被提供给下一个scanf(),对吧?
    • 是的。但我不希望这样,如果我在第一行输入 ABCD,则在第二行输入 HIJKL,在第三行输入 XYZRE,我想在第二行的第一个 HIJ 输入 ABC,然后在最后
    • @venkat 请不要大喊大叫。
    • @venkat 检查我更新的答案,逻辑就在那里。
    【解决方案3】:

    (在阅读迄今为止的答案后感到畏缩。)

    首先,清楚地说明问题。您想从标准输入读取一行,并提取三个短的空格分隔字符串。存储的字符串以 NUL 结尾,最多三个字符(不包括 NUL)。

    #include <stdio.h>         
    
    void main(int, char**) {
        char name[3][4];
        printf("\n enter the names \n");
        {
            // Read tbe line of input text.
            char line[80];
            if (0 == fgets(line, sizeof(line), stdin)) {
                printf("Nothing read!\n");
                return 1;           
            } 
            int n_line = strlen(line);
            if ('\n' != line[n_line - 1]) {
                printf("Input too long!\n");
                return 2;
            }
            // Parse out the three values.
            int v = sscanf(line, "%3s %3s %3s", name[0], name[1], name[2]);
            if (3 != v) {
                printf("Too few values!\n");
                return 3;
            }
        }
        // We now have the three values, with errors checked.
        printf("you entered these names\n%s\n%s\n%s\n",
            name[0], name[1], name[2]
        );
        return 0;
    }
    

    【讨论】:

      【解决方案4】:

      你可能会考虑 scanf("%3s%*s",name[i]); 如果我没记错的话,应该将前三个字符(最多一个空格)放入名称中,然后忽略其他任何内容,直到下一个空格。这将涵盖您的长条目,它不关心空白是什么。

      这不是一个完美的答案,因为如果单字符或双字符条目是模式,它可能会吃掉 A B C 的中间条目。 strtok,会将一行分成有用的位,然后您可以将位的子字符串放入您的 name[] 字段。

      也许在编写代码之前弄清楚整个需求是这个过程的第一步。

      【讨论】:

        猜你喜欢
        • 2021-12-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-04
        • 1970-01-01
        • 2019-06-23
        • 2017-03-10
        • 1970-01-01
        相关资源
        最近更新 更多