1

I am trying to save weather data in a structure. In the below, when I use scanf, it works fine for the 1st loop, but from the second loop, scanf is skipped and just the printf statement gets executed. How can I get scanf to get input throughout the loops. Here is my code:

#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;
}
Kiran C K
  • 61
  • 7
  • Have a look here : http://stackoverflow.com/questions/26345914/c-scanf-in-loop-continues-automaticly-without-input?rq=1 – saruftw Sep 06 '15 at 17:21
  • 1
    Always check the result of functions! What does `scanf` return? – too honest for this site Sep 06 '15 at 17:23
  • It is not that scanf is not executing. It may reading some existing input from the stdin which was entered by you in the first iteration of the loop. Try printing the values after each iteration. That may help you. – Jay Sep 06 '15 at 17:31
  • 1
    `\n` in a `scanf` pattern does exactly the same thing as a space would do: cause *any amount* of whitespace to be skipped. But `%d` and `%s` do that anyway. So there is no difference between `scanf("\n%d", &val)` and `scanf("%d", &val)`. It's better practice to use the second one. Also, your `notes` field only has room for 79 characters and a NUL terminator, so you should fill it in with `scanf(" %79[^\n]", pinfo[loop].notes);`. (The `s` in `%[^\n]s` will only match a literal `s`, which is unlikely since the next character in the input, if any, must be `\n` unless the limit was exceeded.) – rici Sep 06 '15 at 17:45
  • the system function `scanf()` stops inputting when it encounters any white space That white space is still in the input stream. the scanf for 'yes'/'no' leaves a newline in the input stream. the scanf() for 'notes' will see a newline as the first character in the input stream and stop inputting. The 'yes_no' and 'notes' fields are a limited size therefore, the %s input/formats must have a length modifier added so the user cannot overrun the input input buffer. When calling scanf() always check the returned value to assure the operation was successful – user3629249 Sep 06 '15 at 17:53
  • @rici That should probably be an answer. – melpomene Sep 06 '15 at 17:54
  • @rici, %s does NOT automatically skip over leading white space. see: or read the man page. "s String of characters. This will read subsequent characters until a whitespace is found (whitespace characters are considered to be blank, newline and tab)." – user3629249 Sep 06 '15 at 17:56
  • @melpomene: It is not an answer to the question; just some suggestions on how to use scanf. I'm not really sure what the exact symptom is, and I didn't try to track down the possibilities. – rici Sep 06 '15 at 17:57
  • @user3629249 According to your tutorial, none of the conversions skip over white space. This seems wrong. (My man page says: "Before conversion begins, most conversions skip white space; this white space is not counted against the field width.") – melpomene Sep 06 '15 at 18:00
  • @user3629249: The only format conversions which don't skip whitespace are `%c` and `%[`. (Even `%%` skips whitespace.) Try it and see. – rici Sep 06 '15 at 18:06
  • @user3629249: sorry, forgot the `%n` conversion, which doesn't read any input at all. – rici Sep 06 '15 at 18:12
  • 1
    @user3629249 "the system function scanf() stops inputting when it encounters any white space" is incorrect. It depends on the format. – chux - Reinstate Monica Sep 06 '15 at 18:30
  • Post the exact input used. – chux - Reinstate Monica Sep 06 '15 at 18:41
  • 100, 75, 40, 30,"y". – Kiran C K Sep 06 '15 at 20:56
  • 1
    100, 75, 40, 30, "y", "today is the highest temprature recorded". These are the inputs for the first loop – Kiran C K Sep 06 '15 at 20:59
  • Note that `info[0].data` is never set. Attempting to print it (in unposted code) is bad. – chux - Reinstate Monica Sep 06 '15 at 21:54

1 Answers1

1

Wrong format. scanf("\n%[\n]s"...


scanf() first discards for 0 or more white space due to "\n"

Then scans for a line feed due to "%[\n]". Since input by this time is 't' from "today". The scan fails and stops.

Later scanf("\n%d",&(pinfo+loop)->h_temp); tries to read in the 't' as a number and that fails too. Things then just get worse.

As @rici comments, OP likely wanted "\n%[^\n]".

The major fault really is that the code does not check the result of scanf() to verify valid input occurred.

Suggest:

1) Use " " instead of "\n" to skip optional white-space. Both work the same. " " is idiomatic.

2) Use width limited formats like " %79[^\n]" for char notes [80];

3) Always check scanf() results like if (1 !- scanf("\n%d",&(pinfo+loop)->h_temp) { puts("temp fail"); return -1; }

4) Look into dumping all usage of scanf() and use fgets() instead.


Also:

ctime() re-uses the same buffer.

The return value points to a statically allocated string which might be overwritten by subsequent calls to any of the date and time functions.

// (pinfo+loop)->date = ctime(&curtime);
// Make duplicate and remember to free when done.
(pinfo+loop)->date = strdup(ctime(&curtime));
Community
  • 1
  • 1
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256