【问题标题】:Why cannot scanf get input after the first loop? [closed]为什么 scanf 在第一个循环后无法获得输入? [关闭]
【发布时间】:2015-09-06 17:16:12
【问题描述】:

我正在尝试将天气数据保存在一个结构中。在下面,当我使用 scanf 时,它适用于第一个循环,但从第二个循环开始,scanf 被跳过,只执行 printf 语句。如何让 scanf 在整个循环中获取输入。这是我的代码:

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

struct weather
{
     char *date;
     int month;
     int day;
     int year;
     unsigned int h_temp;
     unsigned int l_temp;
     int max_wind_speed;
     int preciption;
     char notes [80];
};

void collect_data (struct weather *pinfo)
{
     int loop;
     char yes_no[2];

     time_t curtime; //declaring time variable

     //storing current system time in the time variable
     time(&curtime);

     //storing current time to time structure
     struct tm * wdate = localtime (&curtime);


     for (loop=0;loop<4;loop++)
     {
            if (loop!=0)
            {
                (pinfo+loop)->date = ctime(&curtime);
                (pinfo+loop)->day = wdate->tm_mday;
                (pinfo+loop)->month = wdate->tm_mon;
                (pinfo+loop)->year = wdate->tm_year;
            }
            /*else
            {
            recent_date(loop,wdate);
            }*/

          printf("\nEnter the high temperature of the day:");
          scanf("\n%d",&(pinfo+loop)->h_temp);
          printf("\nEnter the low temperature of the day:");
          scanf("\n%d",&(pinfo+loop)->l_temp);
          printf("\nEnter the maximum wind speed of the day:");
          scanf("\n%d",&(pinfo+loop)->max_wind_speed);
          printf("\nEnter the perciption of the day:");
          scanf("\n%d",&(pinfo+loop)->preciption);
          printf("\nDo you have any notes about the weather of the day (y/n):");
          scanf("\n%s",yes_no);

          if (strcmp(yes_no,"y")==0)
          {
                printf("\nNotes:\n");
                scanf("\n%[\n]s",(pinfo+loop)->notes);
          }
     }
}

int main ()
{
     struct weather info [4];

     collect_data(info);

     return 0;
}

【问题讨论】:

  • 总是检查函数的结果! scanf 返回什么?
  • \nscanf 模式中的作用与空格完全相同:导致任意数量的空格被跳过。但是%d%s 无论如何都会这样做。所以scanf("\n%d", &amp;val)scanf("%d", &amp;val)没有区别。最好使用第二个。此外,您的notes 字段只能容纳 79 个字符和一个 NUL 终止符,因此您应该使用scanf(" %79[^\n]", pinfo[loop].notes); 填写它。 (%[^\n]s 中的 s 只会匹配文字 s,这不太可能,因为输入中的下一个字符(如果有)必须是 \n,除非超出限制。)
  • @user3629249 “系统函数 scanf() 在遇到任何空白时停止输入”不正确。这取决于格式。
  • 100, 75, 40, 30, "y", "今天是记录的最高温度"。这些是第一个循环的输入

标签: c arrays pointers structure scanf


【解决方案1】:

格式错误。 scanf("\n%[\n]s"...


scanf() 由于"\n" 而首先丢弃 0 个或更多空白空间

然后扫描由于"%[\n]" 引起的换行符。由于此时的输入是“今天”的“t”。扫描失败并停止。

后来scanf("\n%d",&amp;(pinfo+loop)-&gt;h_temp); 尝试将“t”作为数字读入,但也失败了。事情只会变得更糟。

作为@rici cmets,OP 可能想要"\n%[^\n]"

主要错误确实是代码没有检查scanf()的结果来验证是否发生了有效输入。

建议:

1) 使用" " 而不是"\n" 跳过可选的空白。两者的工作方式相同。 " " 是惯用的。

2) 对char notes [80]; 使用宽度受限的格式,例如" %79[^\n]"

3) 始终检查scanf() 结果,例如if (1 !- scanf("\n%d",&amp;(pinfo+loop)-&gt;h_temp) { puts("temp fail"); return -1; }

4) 考虑转储所有 scanf() 的使用,并改用 fgets()


还有:

ctime() 重复使用相同的缓冲区。

返回值指向一个静态分配的字符串,该字符串可能被后续调用任何日期和时间函数覆盖。

// (pinfo+loop)->date = ctime(&curtime);
// Make duplicate and remember to free when done.
(pinfo+loop)->date = strdup(ctime(&curtime));

【讨论】:

    猜你喜欢
    • 2021-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-28
    • 2015-09-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多