Beginner with C here. I am trying to run a loop where strings and ints
are entered into various fields of a struct
. When prompted for a 'last name', the user can press enter with no other input and the loop should end.
The problem is that with this code, the loop doesnt end (last name and first name entry requests run together on the same line) and the value for salary always comes out wrong (0 or some large number)
while (employee_num <= 2)
{
printf("Enter last name ");
fgets(employee[employee_num].last_name, sizeof(employee[employee_num].last_name), stdin);
if(strlen(employee[employee_num].last_name) == 0)
break;
printf("Enter first name ");
fgets(employee[employee_num].first_name, sizeof(employee[employee_num].first_name), stdin);
printf("Enter title ");
fgets(employee[employee_num].title, sizeof(employee[employee_num].title), stdin);
printf("Enter salary ");
fgets(strng_buffer, 1, stdin);
sscanf(strng_buffer, "%d", &employee[employee_num].salary);
++employee_num;
getchar();
}
If I try this code instead, I am able to exit the loop properly after the first run through it, but cannot exit after that (by pressing enter at the last name portion - perhaps a \n I cant seem to clear?):
char strng_buffer[16];
while (employee_num <= 5)
{
printf("Enter last name ");
fgets(strng_buffer, sizeof(strng_buffer), stdin);
sscanf(strng_buffer, "%s", employee[employee_num].last_name);
if(strlen(employee[employee_num].last_name) == 0)
break;
printf("Enter first name ");
fgets(strng_buffer, sizeof(strng_buffer), stdin);
sscanf(strng_buffer, "%s", employee[employee_num].first_name);
printf("Enter title ");
fgets(strng_buffer, sizeof(strng_buffer), stdin);
sscanf(strng_buffer, "%s", employee[employee_num].title);
printf("Enter salary ");
scanf("%d", &employee[employee_num].salary);
++employee_num;
getchar();
}
I am curious as to how to make this work as intended and what best practice would be for entries like this (ie use of sscanf, fgets, etc)
Thanks in advance!
Assuming the fix mentioned by Abhijit, why transform the first into the second? Are you aware that the second behaves differently to the first, because of the addition of
sscanf
? If your intention was to shorten the first, the second seems quite bulky. Rather than addingsscanf
to the situation, why not shorten the first by declaring astruct employee *e = employee + employee_num;
and using that repetitively, instead ofemployee[employee_num]
?One "best practise" regarding
fgets
is to check it's return value. What do you supposefgets
might return, if it encountersEOF
? What do you supposefgets
would return if it's successful?One "best practise" regarding
scanf
is to check it's return value. In regards to the return value ofscanf
, I suggest reading thisscanf
manual carefully and answering the following questions:int x = scanf("%d", &employee[employee_num].salary);
What do you supposex
will be if I enter"fubar\n"
as input?'f'
from"fubar\n"
will go?ungetc
'd back ontostdin
, what would your next employee's last name be?int x = scanf("%d", &employee[employee_num].salary);
What do you supposex
will be if I run this code on Windows and press CTRL+Z to sendEOF
tostdin
?int x = scanf("%d %d", &y, &z);
What would you expectx
to be, presumingscanf
successfully puts values into the two variablesy
andz
?P.S.
EOF
can be sent throughstdin
in Windows by CTRL+Z, and in Linux and friends by CTRL+D, in addition to using pipes and redirection to redirect input from other programs and files.The Loop breaks prematurely when it encounters the break statement
The uninitialized character buffer
strng_buffer
, coincidently has null as the first character causingstrlen
to return0
I believe you may have intended
as the loop terminatorm, and it was a typo in your part causing premature loop exit.
The problem is that
fgets
returns the string with the line break (\n
) included. So, even the user presses return without entering info, the string won't be empty. Also, your buffer size forsalary
is too small.So, either you strip out the
\n
on everyfgets
or you change your check to:Also, when you're getting the buffer, change 1 to something bigger, like
However, if you do want to strip out the
\n
from each fgets, you can do something like:You can do this for every string or, better yet, create a function that does it.
EDIT: if you can guarantee that the user will press enter after each input then you can safely assume this. However if it's not always the case it's possible that the last character is not
\n
and just stripping this way might cause problems.