【问题标题】:Loop back after wrong input, problem with fgetc(stdin) and loop输入错误后循环返回,fgetc(stdin) 和循环出现问题
【发布时间】:2019-08-14 09:13:47
【问题描述】:

所以我有这个简单的代码,我找到了here。我想让它循环工作。我用不同的方法尝试了几次,但输出很糟糕。在 Ubuntu Visual Studio 中工作

编辑我添加了if(y>=2015 && y<=3000),它工作正常吗?

EDIT 2 我已经修改了我的代码并遵循了@Sergey 的建议...它仍然无法正常工作... 我尝试添加“检查 scanf 的返回值”,但它也不起作用。

        if ((scanf("%u", &d) == 1) && (scanf("%u", &m) == 1) && (scanf("%u", &y) == 1))
            while (fdateCheck());
        else
    //...EOF or conversion failure...
            while (fdateCheck());

while ((rc = scanf("%u.%u.%u", &d, &m, &y)) != EOF)
{
    if (rc != 3)
        //...oops data problems...
    else
        //...all OK...
}

需要有关检查 scanfs 返回的建议

int fdateCheck();

unsigned int d,m,y;
unsigned int daysinmonth[12]={31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int rc;
int legit = 0;

int main()
    {
        printf("Enter the date\n");
        scanf("%u.%u.%u",&d,&m,&y);
        while (fdateCheck());
    }
int fdateCheck()
    {   
        if (y % 400 == 0 || (y % 100 != 0 && y % 4 == 0))
            {
                daysinmonth[1]=29;
            }
            else if (y >= 2015 && y <= 3000)
                {
                    if (m < 13)
                        {
                            if (d <= daysinmonth[m-1])
                            legit = 1;
                        }

                    if (legit == 1)
                        {
                            system("clear");  
                            printf("It is a legitimate date!\n");
                            return 0;
                        }
                }
            else
                system("clear");     
                int ch = fgetc(stdin);
                if (ch == '\n')
                    {
                        system("clear");
                        printf("It's not a legitimate date!\n");
                        printf("\nRetry: ");
                        return 1;
                    }
                fflush(stdin);
    }

【问题讨论】:

  • 不要像0x0A一样使用magic numbers。如果您的意思是换行符'\n',请明确说明。
  • 另外,递归调用main 是一个非常糟糕的习惯。改用真正的循环。
  • 您需要学习如何检查函数返回值是否存在错误情况。绝对你需要检查scanf 返回的内容。为了解决这个崩溃问题,请考虑将fgetssscanf 结合使用。
  • 检查scanf的返回值。处理错误。然后事情可能会开始变得有意义。
  • 另一件事,你应该在你的闰年检查上有一个 else,否则如果它曾经设置为 29,它将在所有年份保持这种状态。

标签: c loops date fgetc


【解决方案1】:

如果您在函数void main() 中有适当的代码,并且需要按照您的描述循环重复,您可以执行以下操作:

  1. 将原来的void main()重命名为int one_step()
  2. return 0;放在printf("It is a legitimate date!\n");之后
  3. return 1;放在printf("It's not a legitimate date!\n");之后
  4. 创建新的void main() 函数为:
void main() {
    while(one_step());
}

您不需要break;return main();。您可能需要一些增强功能,如上面的 cmets 中所述。祝你编码顺利!

更新 #1

我的意思是对您的代码进行了这样的改进:

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

int fdateCheck();

int main()
{
    while (fdateCheck());
}

int fdateCheck()
{
int res;
int legit = 0;
unsigned int d,m,y;
unsigned int daysinmonth[12]={31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    // get input block
    printf("Enter the date\n");         // prompt for data
    res = scanf("%u.%u.%u",&d,&m,&y);   // get input data
    if (res == EOF) {                   // check if no more input
            printf("Input error\n");
            exit(1);
    }
    // check if input data is valid
    if (res != 3) {                     // check if 3 numbers scanned
            system("clear");
            printf("It is not a date\n");
            fflush(stdin);
            return 1;
    }
    // make leap year correction
    if (y % 400 == 0 || (y % 100 != 0 && y % 4 == 0)) {
        daysinmonth[1]=29;              // leap year correction
    }
    // check if year, month and day is valid
    if (y >= 2015 && y <= 3000) {       // check if year in this range
        if (0 < m && m < 13) {          // check if month in this range
            if (0 < d && d <= daysinmonth[m-1]) // check if day in this range
                legit = 1;
        }
    }
    // print a message and finish the iteration
    if (legit == 1) {
        printf("It is a legitimate date!\n");
        return 0;
    }
    else {
        system("clear");
        printf("It's not a legitimate date!\n");
        printf("Please retry.\n");
        fflush(stdin);
        return 1;
    }
}

我还移动了函数内的所有变量。这将在每次迭代之前恢复 legitdaysinmonth[1] 的值。

更新 #2

我的下一个建议:

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

int fdateCheck();

int main()
{
    while (fdateCheck());
}

int fdateCheck()
{
int res;
int legit = 0;
unsigned int d,m,y;
unsigned int daysinmonth[12]={31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    // get input block
    printf("Enter the date\n");         // prompt for data
    res = scanf("%u.%u.%u",&d,&m,&y);   // get input data
    if (res == EOF) {                   // check if no more input
            printf("Input error\n");
            exit(1);
    }
    // check if input data is valid
    if (res != 3) {                     // check if 3 numbers scanned
            fgetc(stdin);               // remove a barrier
            system("clear");
            printf("It is not a date\n");
            fflush(stdin);
            return 1;
    }
    // make leap year correction
    if (y % 400 == 0 || (y % 100 != 0 && y % 4 == 0)) {
        daysinmonth[1]=29;              // leap year correction
    }
    // check if year, month and day is valid
    if (y >= 2015 && y <= 3000) {       // check if year in this range
        if (0 < m && m < 13) {          // check if month in this range
            if (0 < d && d <= daysinmonth[m-1]) // check if day in this range
                legit = 1;
        }
    }
    // print a message and finish the iteration
    if (legit == 1) {
        printf("It is a legitimate date!\n");
        return 0;
    }
    else {
        system("clear");
        printf("It's not a legitimate date!\n");
        printf("Please retry.\n");
        fflush(stdin);
        return 1;
    }
}

【讨论】:

  • 感谢您的回答,以后会有所帮助
  • 代码运行正常,但出现错误。当输入例如a.b.c.时,程序处于无限循环中
  • 我在if (res!=3)中添加了这个system("clear"); int ch = fgetc(stdin);if (ch == '\n'){system("clear");printf("It's not a legitimate date!\n");fflush(stdin);return 1;}
  • 完美!你抓住了我。但是我还是觉得没必要去查ch的值。请参阅更新 #2。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-20
  • 1970-01-01
相关资源
最近更新 更多