1

Today I wrote a code at the university on VS 2013 and it worked. I sent it to myself through email to try at home. Its not working on VS 2017. Fortunately I have VS 2013 and it does work on it. Why is this happening? Here is the part of the code that fails on VS 2017:

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

typedef struct{
    char name[50];
    char pos[50];
    double sel[12];
    double annpay;
}sluj;

typedef struct{
    int num;
    sluj per[100];
}firma;

firma f;

int main(){

    int i, j;

    do{
        printf("Enter number of employees\n");
        scanf("%d", &f.num);
    } while (f.num < 1 || f.num > 100);

    for (i = 0; i < f.num; i++){
        printf("Enter the name of employee:\n");
        fflush(stdin);
        fgets(f.per[i].name, 50, stdin); //it acts like this row doesnt exist 
                                 //and prints the text below
        printf("Enter the position of employee:\n");
        fgets(f.per[i].pos, 50, stdin);  //basiclly the same thing as above, but on different
                                 //structure member (both are defined char) 
                                 //and it works here!

        for (j = 0; j < 12; j++){
            printf("Enter salary for %d month\n", j+1);
            scanf("%lf", &f.per[i].sel[j]);
        }
    }

    for (i = 0; i < f.num; i++){
        f.per[i].annpay = 0;

        for (j = 0; j < 12; j++){
            f.per[i].annpay += f.per[i].sel[j];
        }
    }

    for (i = 0; i < f.num; i++){
        if (f.per[i].annpay > 6000){
            printf("\n%s %lf", f.per[i].name, f.per[i].annpay);
        }
    }

    return 0;
}

I don't think the problem is with fflush, because it doesn't work even without it.

sg7
  • 6,108
  • 2
  • 32
  • 40
pollux552
  • 107
  • 1
  • 10

2 Answers2

0

scanf() and fgets() do not work well together. scanf() reads number of employes and the submitting \n is still buffered and will be given to fgets(). The fflush() does not work on pipes.

E.g. with linux and glibc you get the same behavior

$ ltrace ./a.out  > /dev/null 
puts("Enter number of employees")                             = 26
__isoc99_scanf(2
"%d", 6295680)                                 = 1
fflush(0x7f7c6811c9e0)                                        = 0
puts("Enter the name of employee:")                           = 28
fgets("\n", 50, 0x7f7c6811c9e0)                               = 0x601088
puts("Enter the position of employee:")                       = 32

There is no good way to combine both functions; Use e.g. fgets() to read the number of employees into a string and convert this later.

ensc
  • 6,704
  • 14
  • 22
0

The problem with the code is that scanf() leaves the '\n' as the artifact in the stdin. Mixing scanf() and fgets() is unwise. Your program with scanf() has no protection for entering wrong input. It would hang if letters are entered as number of employees.

The use of fflush() will not help.

fflush() is typically used for output stream only. Its purpose is to clear (or flush) the output buffer and move the buffered data to console (in case of stdout) or disk (in case of file output stream).

As per C standard, it is undefined behavior to use fflush(stdin).

However, on some compilers like VS2013 it "works". That has been changed in VS2017.

The quick fix for leftover '\n' is as follows:

do{
    printf("Enter number of employees\n");
    scanf("%d", &(f.num));
} while (f.num < 1 || f.num > 100);

int c;
c = getchar();
if(c == EOF)
    return -1; // END OF PROGRAM

if (c!='\n')
    ungetc(c, stdin);
sg7
  • 6,108
  • 2
  • 32
  • 40
  • @JustSteve It would "work" on VS2013, but as per C standard, it is undefined behavior to use `fflush(stdin).` The VS2017 behaviour is in line with the current `gcc`. – sg7 Mar 11 '18 at 18:54