1

I have a scanf that doesn't accept input. The value is automatically zero, even if the variable wasn't initialized. The scanf is skipped:

printf("\nEnter the number of the student to be dropped: ");
fflush(stdin);
scanf(" %d ",&choice);
printf("choice is %d", choice);

When the program is run, it immediately displays "choice is 0".

The snippet above is taken from the drop() function in this code:

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

struct student{
       char name[50];
       char* course;
};

main()
{
      char repeat;
      do{
      system("cls");
      int mainchoice;
      printf("Student Enrollment System");
      printf("\n");
      printf("\n");
      printf("1. View\n");
      printf("2. Enroll\n");
      printf("3. Drop enrollment\n");
      printf("Select choice: ");
      fflush(stdin);
      scanf("%d",&mainchoice);
      system("cls");
      switch(mainchoice){
             case 1:
                  view();
                  break;
             case 2:
                  enroll();
                  break;
             case 3:
                  drop();
                   break;
             default:
                     printf("Please enter a valid number.");
                     getch();
                     fflush(stdin);
                     break;
             }

      printf("\nWould you like to make another transaction? [Y/N]: ");
      fflush(stdin);
      scanf("%c",&repeat);
      }while(repeat=='Y'||repeat=='y');     
}

view(){
       int ctr = count();
       printf("Enrolled Students:\n\n");
       system("type records.txt");
       printf("\n\nNumber of students enrolled: %d", ctr);
       getch();
       fflush(stdin);

}

enroll(){
         int choice;
         char validate;
         printf("1. Information Technology\n");
         printf("2. Computer Science\n");
         printf("3. Computer Engineering\n");
         printf("4. Information Systems\n");
         struct student news;
         printf("Name: ");
         fflush(stdin);
         gets(news.name);
         printf("Course Number: ");
         fflush(stdin);
         scanf("%d", &choice);
         switch(choice){
                        case 1:
                             news.course = "BSIT";
                             break;
                        case 2:
                             news.course= "BSCS";
                             break;
                        case 3:
                             news.course = "BSCpE";
                             break;
                        case 4:
                             news.course = "BSIS";
                             break;
                        default:
                                printf("Please enter a valid number\n");
                                break;
                        }
         printf("Enroll %s to %s? [Y/N]:",news.name,news.course);
         fflush(stdin);
         scanf("%c", &choice);
         if(choice=='Y' || choice=='y')
         {
          FILE * records;
          records = fopen("records.txt", "a+");
          fprintf(records, "%s, %s\n",news.name,news.course);
          fclose(records);
          printf("%s has been enrolled to %s\n",news.name, news.course);

         }
         else
         {
             printf("You have chosen to cancel your transaction");
         }
}

drop(){
       printf("Drop Student:\n\n");
       int ctr = 0;
       int choice; //which student to delete
       char c;
       FILE * record; // original records.txt
       FILE* repo;    //temporary data storage


       record = freopen("records.txt", "r", stdin);
       while((c = fgetchar())!=EOF){
                if(c == '\n'){

                }
                else{
                     ctr=ctr+1;
                     printf("%d.  ", ctr);
                     while(1){       
                                     printf("%c",c);
                                     c= fgetchar();
                                     if(c=='\n'){
                                                 printf("%c",c);
                                                 break;
                                                 }

                     }  

                }              
       }
       fclose(record);
       fflush(stdin);
       fflush(stdin);
       printf("\nEnter the number of the student to be dropped: ");
       fflush(stdin);
       scanf(" %d ",&choice);
       getch();
       getch();
       fflush(stdin);
       ctr = 1;
       fflush(stdin);

       repo = fopen("temp.txt","w");
       record = freopen("records.txt","r",stdin);
       while((c = getchar()) != EOF){
                if(c == '\n'){

                }
                else{

                     while(ctr!=choice){       
                                     fprintf(repo,"%c",c);
                                     c= fgetchar();
                                     if(c=='\n'){
                                                 fprintf(repo,"%c",c);
                                                 ctr = ctr + 1;
                                                 break;
                                                 }
                                     }
                     }
                }
       fclose(record);      
       fclose(repo);

       getch();
}

//counts the number of rows in the record
int count(){
       int ctr=0;
       char c;
       FILE * records;
       records = freopen("records.txt","r", stdin);
       if(records!=NULL){
            while((c=fgetchar()) !=EOF){
                if(c=='\n'){
                    ctr = ctr+1;
                    }
                }                      
       }
       fclose(records);   
       return ctr; 
}

Doing fflush doesn't seem to help. Any ideas?

1 Answers1

6

The behavior of fflush is not defined for input streams; fflush(stdin) is a coding error, and you should remove those calls from your code.

When scanning for individual characters, add a blank space before the %c conversion specifier; this will tell scanf to skip any leading whitespace and read the next non-whitespace character:

scanf(" %c", &choice);

The %d and %s conversion specifiers will skip over any leading whitespace.

Edit

Implicit typing is no longer supported as of C99, and it's a bad habit to get into. Explicitly type your functions, and use void as the parameter list to specify that they take no arguments:

main() => int main(void)
view() => void view(void) // void since it isn't returning a value
drop() => void drop(void)

etc.

Similarly, gets was deprecated in C99 and is gone completely as of the 2011 standard. Using it will introduce a point of failure / major security hole in your program. Use fgets instead.

John Bode
  • 119,563
  • 19
  • 122
  • 198
  • thanks, i did what you told me. changed the data type of choice to char, and explicitly typed my functions., but now ive gotten errors like "conflicting types for view", "previous implicit declaration of view was here" etc... – Carl Nathan Mier Feb 21 '13 at 04:23
  • 1
    @CarlNathanMier: Ah. In C89 and earlier, if the compiler sees a function call without a preceding declaration for that function, it will assume the function returns `int`. So it sees the call to `view` in `main`, assumes it returns an `int`, then it sees the definition for `view`, except now the definition says it returns `void`, hence the heartburn. Functions need to be declared before use; the easiest thing to do is define the function before it's called. In this case, move the definition of `main` below the other function definitions. – John Bode Feb 21 '13 at 04:31
  • thanks @John Bode, but I'm still getting the same problem with the `scanf` in the `drop` function... – Carl Nathan Mier Feb 21 '13 at 05:05
  • @CarlNathanMier: Hmm. Just for giggles, try removing the whitespace around the `%d` conversion specifier: `scanf("%d", &choice);`. I don't expect that to make a difference, but you never know. – John Bode Feb 21 '13 at 05:13
  • The note about the whitespace before the char specifier is killer. Extremely useful information there, +1 – julealgon May 23 '14 at 02:02