如何使用scanf限制输入长度

How to limit input length with scanf

在这个程序中,我采用了一个大小为[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(); 
}

How should I chk for null character in 2 dimensional ... [something has eaten the rest part, I guess]

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

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

char name[3][4];

如果输入超过三个 char,您将覆盖已分配内存的边界 [考虑到 [=14=] 的 space。您必须使用

来限制您的 scanf()
scanf("%3s",name[i]);

注:

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

编辑:

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

检查下面的代码 [在 Linux 下,因此删除了 conio.hgetch()]

# 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;
}

正如@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 */
}

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

首先把问题说清楚。你想从 stdin 中读取一行,并提取三个由空格分隔的短字符串。存储的字符串以 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;
}

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

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

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