c - 如果用户输入的长度超过 16 个字符,为什么我的 C 程序会打印两次消息?

标签 c loops

我正在尝试制作一个小型帐户注册程序。它提示用户输入 userIDpassword 。我正在研究 userID部分,但似乎不对。如果我输入 < 8 ,效果很好。字符userID ,但是当我输入 userID超过16字符,询问用户不同的消息 userID打印两次。这是为什么?

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

int main(void)
{
    // Setting up variables
    char userID[18];
    char passcode[51];

    // Firstly promt the user for user ID
    do // This loop is for asking the user to type another userID if his chosen one isn't approprite
    {
        printf("Please choose your user ID! (it must be between 6 - 16 charaters long)\n");
        for (int i = 0; i < 17; i++) // This loop store the userID into the character array
        {
            userID[i] = getchar(); // Store userID into array character by         character
            if (userID[i] == '\n')
            {
                userID[i+1] = '\0';
                break;
            }

        }
    }
    while (strlen(userID) < 7  ||  (strlen(userID) > 16  &&  userID[16] != '\n'));

    // Printing info on the screen.
    printf("Your acount info are:\n\tuserID  : %s\tpasscode: ", userID);

最佳答案

It works fine if I type in a < 5 characters userID, but when I type in a userID with more than 16 characters, the messages asking the user for a different userID are printed twice. Why's that?

  • 当您输入超过 16 字符时,17 字符会被扫描到字符串 userID 中,因为您没有输入 '\n' ,不会在字符串 userID 末尾放置空字符。

    <
  • 然后,当您使用 strlen(userID) 时,这会调用未定义的行为,因为末尾没有放置终止 \0 字符。尝试这样做:

  • 当您重新开始迭代时,剩余的额外整数将被吸收。

<小时/>

解决方案:

为了避免上述问题:

  1. 在每次迭代中在 index + 1 位置放置一个空字符。
  2. flush 每次迭代结束时的 stdin

    do
    {
        printf("Please choose your user ID! (it must be between 6 - 16 charaters long)\n");
    
        for (int i = 0; i < 17; i++)
        {
            userID[i] = getchar();
            userID[i+1] = '\0'; //placing null character at the position index+1
    
            if(userID[i] == '\n')
            {
                userID[i] = '\0';
                break;
            }    
    
        }
    
        fflush(stdin); //flushing the extra input at the end of each iteration
    
    } while (strlen(userID) < 7  ||  (strlen(userID) > 16  &&  userID[16] != '\n'));
    

示例输入:

more than 16 123456789
1123
123456789

示例输出:

Please choose your user ID! (it must be between 6 - 16 charaters long)
more than 16 123456789
Please choose your user ID! (it must be between 6 - 16 charaters long)
1123
Please choose your user ID! (it must be between 6 - 16 charaters long)
123456789

Your acount info are:
    userID  : 123456789
    passcode: 
<小时/>

注意:

避免使用 fflussh(stdin),因为它存在可移植性问题,如 @JonathanLeffler 中的 comments 建议。另外,这里还有一篇解释性文章为什么不使用 fflush(stdin) :click

这是避免使用 fflush(stdin) 的代码实现

do
{
    int i;

    printf("Please choose your user ID! (it must be between 6 - 16 charaters long)\n");

    for (i = 0; (userID[i] = getchar()); i++)
    {

        userID[i+1] = '\0'; //placing null character at the position index+1

        if(userID[i] == '\n')
        {
            userID[i] = '\0';
            break;
        }

        //if user enters more than 16 characters then,
        //scan in 17th character for `strlen(userID)` purpose and
        //consume all other characters using an integer `c`
        if( i > 17)
        {
            int c;

            while( ((c = getchar())!= '\n') && (c!=EOF) );
            break;
        }
    }

} while ( (strlen(userID) < 7)  ||  (strlen(userID) > 16 ) );

关于c - 如果用户输入的长度超过 16 个字符,为什么我的 C 程序会打印两次消息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38278125/

相关文章:

c - 在堆内存数组中分配指向结构的指针

c - 调用 execv 后出现奇怪的行为

c++ - 如何创建接受参数的dll

python - 如何检查两级循环中的键?

带 HREF 的 PHP While 循环

javascript - forEach 循环中的 NodeJs 函数需要在转到下一项之前完成

c - 一个更完整的递归下降c解释器

c - 如何扫描字符串直到在C中输入特定字符串

jquery - 使用 jQuery 循环遍历 JSON 结果

c - 在c中使用带循环的字符串