【问题标题】:how can i let while loop printf only come once in c?我怎样才能让while循环printf在c中只出现一次?
【发布时间】:2022-09-27 23:40:51
【问题描述】:
#include<stdio.h>
    int main(void)
    {
        int num;
        int days;
        int week;
        printf(\"enter a day\\n\");
        scanf_s(\"%d\\n\", &num);
        
    
        while (num)
        {
            week = num / 7;
            days = num - week * 7;
            printf(\"%ddays are %dweeks, %days\\n\", num, week, days);
        
        }
    
        if (num <= 0)
    
            printf(\"your input is wrong\\n\");
        else
            printf(\"enter your day again\\n\");
            
        
            return 0;
    }

   

如何让 printf(\"%ddays are %dweeks, %days\\n\", num, week, days) 只出现一次然后显示 printf(\"enter your day again\\n\");如果我的输入 >0

  • 如果您希望它只打印一次,请将其移出循环。你到底想做什么?
  • 如果num != 0,你有一个无限循环。您似乎打算在循环中更新num,但忘记了这样做。
  • 我试图让用户重复输入日值;当用户输入像 <=0 这样的非正值时终止循环
  • @asterdis:如果您希望用户能够重复输入,那么您应该将 scanf_s 函数调用移动到循环中。
  • @AndreasWenzel 喜欢那样 while (scanf_s(\"%d\\n\", &num))?

标签: c


【解决方案1】:

首先,如果您希望您的代码可以移植到其他平台,一般不建议使用函数scanf_s。通常最好使用scanf。如果您使用 scanf_s 的唯一原因是因为 Microsoft 编译器告诉您必须这样做,那么我建议您添加该行

#define _CRT_SECURE_NO_WARNINGS

到源代码文件的最顶部,Microsoft 编译器将接受您改用scanf

另外,线

scanf_s("%d\n", &num);

是错的。您应该从格式字符串中删除\n。有关更多信息,请参阅此问题:

What is the effect of trailing white space in a scanf() format string?

如果您希望您的程序继续重新提示用户,直到输入有效,那么您可以使用以下代码:

#include <stdio.h>

int main( void )
{
    for (;;) //infinite loop, equivalent to while(1)
    {
        int num;
        int days;
        int week;

        //get input from user and verify it
        printf( "Enter number of days: " );
        if (
            scanf( "%d", &num ) != 1
            ||
            num <= 0
        )
        {
            printf( "Invalid input! Please try again.\n" );
            continue;
        }

        //calculate number of weeks and days
        week = num / 7;
        days = num % 7;

        //print result
        printf( "%d days are %d weeks, %d days.\n", num, week, days );

        //break out of infinite loop
        break;
    }
}

该程序具有以下行为:

Enter number of days: 8
8 days are 1 weeks, 1 days.
Enter number of days: -3
Invalid input! Please try again.
Enter number of days: 0
Invalid input! Please try again.
Enter number of days: 14
14 days are 2 weeks, 0 days.

但是,值得注意的是,如果用户输入除数字以外的任何其他内容,该程序将陷入无限循环:

Enter number of days: abc
Invalid input! Please try again.
Enter number of days: Invalid input! Please try again.
Enter number of days: Invalid input! Please try again.
Enter number of days: Invalid input! Please try again.
Enter number of days: Invalid input! Please try again.
Enter number of days: Invalid input! Please try again.
Enter number of days: Invalid input! Please try again.
Enter number of days: Invalid input! Please try again.
Enter number of days: Invalid input! Please try again.
Enter number of days: Invalid input! Please try again.
Enter number of days: Invalid input! Please try again.
Enter number of days: Invalid input! Please try again.
Enter number of days: Invalid input! Please try again.
Enter number of days: Invalid input! Please try again.
Enter number of days: Invalid input! Please try again.
Enter number of days: Invalid input! Please try again.
Enter number of days: Invalid input! Please try again.
Enter number of days: Invalid input! Please try again.
[...]

这是因为scanf 将立即失败而不会消耗无效输入,因此对scanf 的下一次调用将由于完全相同的原因而失败。

函数scanf 的行为是这样的,因为它不是为基于用户的行输入而设计的。因此,最好不要使用此功能。最好使用函数fgets 始终将整行​​输入读取为字符串,然后使用函数strtol 尝试将此输入转换为整数。

this answer of mine to another question 中,我创建了一个函数get_int_from_user,它使用fgetsstrtol 而不是scanf,这样就不会出现上述问题。如果输入不是有效整数或由于其他原因无法转换为int,此函数将执行广泛的输入验证并自动重新提示用户。

如果我重写您的程序以使用此功能,它将如下所示:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <errno.h>

//declare function prototype
int get_int_from_user( const char *prompt );

int main( void )
{
    for (;;) //infinite loop, equivalent to while(1)
    {
        int num;
        int days;
        int week;

        //read integer from user
        num = get_int_from_user( "Enter number of days: " );

        //verify that number is positive
        if ( num <= 0 )
        {
            printf( "Invalid input! Please try again.\n" );
            continue;
        }

        //calculate number of weeks and days
        week = num / 7;
        days = num % 7;

        //print result
        printf( "%d days are %d weeks, %d days.\n", num, week, days );

        //break out of infinite loop
        break;
    }
}

int get_int_from_user( const char *prompt )
{
    //loop forever until user enters a valid number
    for (;;)
    {
        char buffer[1024], *p;
        long l;

        //prompt user for input
        fputs( prompt, stdout );

        //get one line of input from input stream
        if ( fgets( buffer, sizeof buffer, stdin ) == NULL )
        {
            fprintf( stderr, "Unrecoverable input error!\n" );
            exit( EXIT_FAILURE );
        }

        //make sure that entire line was read in (i.e. that
        //the buffer was not too small)
        if ( strchr( buffer, '\n' ) == NULL && !feof( stdin ) )
        {
            int c;

            printf( "Line input was too long!\n" );

            //discard remainder of line
            do
            {
                c = getchar();

                if ( c == EOF )
                {
                    fprintf( stderr, "Unrecoverable error reading from input!\n" );
                    exit( EXIT_FAILURE );
                }

            } while ( c != '\n' );

            continue;
        }

        //attempt to convert string to number
        errno = 0;
        l = strtol( buffer, &p, 10 );
        if ( p == buffer )
        {
            printf( "Error converting string to number!\n" );
            continue;
        }

        //make sure that number is representable as an "int"
        if ( errno == ERANGE || l < INT_MIN || l > INT_MAX )
        {
            printf( "Number out of range error!\n" );
            continue;
        }

        //make sure that remainder of line contains only whitespace,
        //so that input such as "6sdfj23jlj" gets rejected
        for ( ; *p != '\0'; p++ )
        {
            if ( !isspace( (unsigned char)*p ) )
            {
                printf( "Unexpected input encountered!\n" );

                //cannot use `continue` here, because that would go to
                //the next iteration of the innermost loop, but we
                //want to go to the next iteration of the outer loop
                goto continue_outer_loop;
            }
        }

        return l;

    continue_outer_loop:
        continue;
    }
}

如您所见,如果我输入数字以外的其他内容,程序将不再陷入无限循环:

Enter number of days: abc
Error converting string to number!
Enter number of days: 8abc
Unexpected input encountered!
Enter number of days: 8
8 days are 1 weeks, 1 days.

【讨论】:

  • @chux:我的函数get_int_from_user 以与换行符相同的方式处理文件结束事件。请参阅以下行:if ( strchr( buffer, '\n' ) == NULL &amp;&amp; !feof( stdin ) )。因此,它应该在您描述的情况下工作。
  • 输入一天 0 0days 是 0weeks, 0ays 你的输入是错误的 C:\Users\86377\source\repos\assignment2\x64\Debug\item3.exe (process 10244) exited with code 0. 调试停止时自动关闭控制台,启用工具->选项->调试->调试停止时自动关闭控制台。按任意键关闭此窗口。 . .
  • 我运行的程序是第一个
  • @asterdis:请指定所需的输出以及实际输出。目前尚不清楚您指定的输出是期望输出还是实际输出。
  • scanf_s 是 C11,但它是可选的.这方面的好读物是:“scanf_s is not included in C11”和“Why didn't gcc (or glibc) implement _s functions?”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-18
  • 2018-05-14
  • 2020-11-28
  • 2014-11-09
相关资源
最近更新 更多