Regarding structures in C - c

If I try to run this code then it doesn't ask me the value of s2.name. Why is it so?
#include<stdio.h>
int main()
{
struct student
{
char name;
int roll;
int age;
};
struct student s1;
struct student s2;
printf("Enter name of the student: ");
scanf("%c", &s1.name);
printf("%c", s1.name);
printf("\n");
printf("Enter name of the student: ");
scanf("%c", &s2.name);
printf("%c", s2.name);
return 0;
}

When you input a single character and press the Enter key, you are actually inputting two characters: The character in your input and a newline from the Enter key.
The second scanf reads this newline.
Or if you give multiple characters as input to the first name, then the second character will be read by the second scanf.
The way to solve the first problem is easy: Tell scanf to read and discard leading white-space (which newline is) by adding a single space in front of the format, like
scanf(" %c", &s2.name);
// ^
// Note space here
The way to solve the second problem is to read strings instead, which means you have to turn your name members into arrays and then use the "%s" format (preferably with a specified width so you don't read to many characters).

You are basically inputting two characters:
- the one that you type
- the newline character `\n` because you hit `enter`
A solution to this problem is clearing stdin after reading in the first "name":
#include<stdio.h>
int main()
{
struct student
{
char name;
int roll;
int age;
};
struct student s1;
struct student s2;
printf("Enter name of the student: ");
scanf("%c", &s1.name);
printf("%c", s1.name);
printf("\n");
fflush(stdin); //only works on windows, clears the input buffer
printf("Enter name of the student: ");
scanf("%c", &s2.name);
printf("%c", s2.name);
return 0;
}
Another way to clear the input buffer is:
while (getchar() != '\n');
This reads in all characters from the input buffer, because as soon as input is read by functions like getchar() or scanf(), the input is removed from stdin.
EDIT:
When you input values using getchar(), scanf(), etc., then the symbols that you type into stdin (most of the times via a keyboard) are stored in the input buffer at first (stdin). getchar() or any similar function then takes the values that it should read in, out of the input buffer. For example:
scanf("%d", &var);
scanf("%d", &var2);
If I input 5x, the characters in the input buffer are '5', 'x' and \n (because you hit the enter key). The first scanf() then takes out the '5', as it fits the format string %d. After that, the characters in the input buffer are 'x' and \n. In this case scanf returns 1, because it read in one value correctly.
When it then continues to the second one, scanf() won't even let you type anything, as there is already something in the input buffer stdin. It won't store any data however, because the first "item" in stdin ist 'x'. That doesn't fit the format string %d. The compiler then doesn't continue to read. In this case scanf would return 0, as no value was read in correctly.

Related

Why is the scanf() skipped?

#include <stdio.h>
int main() {
char opt;
scanf(" %c", &opt);
switch (opt) {
case 'A':
printf("Please Enter a New Name:");
char name[200];
scanf("%[^\n]s", name);
printf("Please Enter a New Code:");
char code[200];
scanf("%s", code);
printf("Please Enter the Number:");
int number;
scanf("%d", number);
printf("%s\n%s\n%d", name, code, number);
printf("\nPlease press Enter to confirm Creation");
}
}
Why is the scanf of the name skipped? the output looks like
A
Please Enter a New Name:Please Enter a New Code:
Also when switch() is removed, it works normally. Is the problem on the switch()? It does not have other cases because it is an unfinished code.
As commented by melonduofromage, your first scanf leaves the newline (\n) typed by the user after the A in the input stream. Next scanf("%[^\n]s", name) fails because the first byte from the input stream is a newline, so scanf returns immediately with a return value of 0, which you should not ignore. The program then prompts for the code and scanf skips initial white space, including the pending newline and waits for user input.
To fix this problem, add a space before the conversion specifier to skip initial white space. You should also limit the number of characters stored into the destination array: specify this number between the % and the [. Note also that the trailing s in "%[^\n]s" is useless: it is not part of the conversion specifier and scanf() will try and match it against the input stream. The correct format is scanf(" %199[^\n]", name) and the return value must be 1 for a successful conversion.
Also note that there is a missing & in scanf("%d", number): you must pass the address of the destination variable: scanf("%d", &number);
Here is a modified version:
#include <stdio.h>
int invalid_input(void) {
fprintf(stderr, "invalid or missing input\n");
return 1;
}
int main() {
char opt;
if (scanf(" %c", &opt) != 1)
return invalid_input();
switch (opt) {
case 'A':
printf("Please Enter a New Name:");
char name[200];
if (scanf(" %199[^\n]", name) != 1)
return invalid_input();
printf("Please Enter a New Code:");
char code[200];
if (scanf("%199s", code) != 1)
return invalid_input();
printf("Please Enter the Number:");
int number;
if (scanf("%d", &number) != 1)
return invalid_input();
printf("%s\n%s\n%d", name, code, number);
printf("\nPlease press Enter to confirm Creation");
//...
}
return 0;
}
When you prompt user with the first scanf here
char opt;
scanf(" %c", &opt);
When the user enters a character, say A, "A\n" is placed in the buffer, \n coming from the user hitting the return key. The scanf takes one character as requested with the " %c" format string, and leaves the \n on the buffer.
When the second scanf is executed as
printf("Please Enter a New Name:");
char name[200];
scanf("%[^\n]s", name);
the format string "%[^\n]s" requests it to read until a \n is encountered, mind you, your buffer already contains a \n as the first character, hence scanf returns without reading anything, still leaving the \n in the buffer.
When the third scanf is executed as:
printf("Please Enter a New Code:");
char code[200];
scanf("%s", code);
(Corrected after the comments of chqrlie)
The format string "%s" ignores the leading whitespaces, hence now the \n is ignored, and scanf happily waits for your input.
Notice the leading space in the format string " %c", the space is there to get scanf ignore the leading whitespace, you can implement the same logic with your second scanf. You can either ensure that all consecutive scanf ignore the \n left in the buffer, which turns out most format specifiers do, or you can ensure that no scanf leaves it to begin with with using something like "<...>%*c" to get rid of it. Though none of which are reliable and consistent methods, and as said countless times, scanf is not designed to perform such tasks like taking user input, and you should seek alternative methods.
Also, the s in "%[^\n]s" certainly doesn't do what you expect. man page of the scanf states that
An ordinary character (i.e., one other than white space or '%'). This character must exactly match the next character of input.
If it matches, scanf discards it and continues parsing according to the remaining format specifiers. If it doesn't, scanf stops there and returns. Since it is at the end of your format string, it returns either way, hiding a potential bug from you.

Is there any problem when reading a char that is inside a struc?

So I have this code and for some reason when I am trying to enter all the "requested" information, my program always skips scanning the char
Currently I solved it by creating a char type variable with an array on 1 position and treating it as a string, but it doesn't make sense why it wont read a char
struct person
{
char name[30];
int age;
char sex;
};
int main()
{
struct person data[3];
for (i = 0 ; i < 3 ; i++)
{
printf("\nType in the data of the person number: %d",i+1);
printf("\nName: ");
scanf("%s",data[i].name);
printf("\nAge: ");
scanf("%d",&data[i].age);
printf("\nSex (M/F): ");
scanf("%c",data[i].sex);
}
}
It perfectly scans name and age, it even prints them, but for some reason, it refuses to scan the sex
The char gets read but it is the newline character '\n' left from the previous scanf(). To skip leading whitespace use
scanf(" %c", &data[i].sex);
// |
// +---- skips leading whitespace
And you also missed the address-of operator in your code.
The leading space is not necessary for most format specifiers like %d because they skip leading whitespace per default.
There is a newline character in your input stream, which is read as the character (%c) you're trying to read as gender.
You can read this character and ignore it in this way:
printf("\nSex (M/F): ");
getchar(); //ignore the remained character in input stream
scanf("%c", &data[i].sex);
As mentioned in other answers, you also have forgotten the reference symbol (&) in scanning the gender.

why %s does not print the string after it encounters a space character? [duplicate]

This question already has answers here:
How do you allow spaces to be entered using scanf?
(11 answers)
Closed 6 years ago.
#include <stdio.h>
int main()
{
char name[20];
printf("Enter name: ");
scanf("%s", name);
printf("Your name is %s.", name);
return 0;
}
Output:
Enter name: Dennis Ritchie
Your name is Dennis.
So far I haven't found any specific valid reason for this question. Can anyone help me out?
scanf only read till it gets to space that is why it is not storing after the first space , so your printf function is not faulty , it is the scanf that is not storing the complete string , stopping on encountering first space.
One should never use gets() , unless they completely know what they are doing , because it does not have buffer overflow protection , it continue to read after the buffer ends until it finds a new line or encounter a EOF. You can read more about that here.Please Check This Why is the gets function so dangerous that it should not be used?
You should instead use fgets().
#include <stdio.h>
int main(){
char name[20];
printf("Enter name: ");
fgets(name,20,stdin);
printf("Your name is %s.", name);
return 0;
}
Remember fgets() also reads newline character(the one you get when you press enter) so you should manually remove that.
Also I highly Recommend this answer for using fgets() to its full potential and avoiding common pitfalls.
This answer tells about using scanf to read string.What it says is the following:
int main(){
char string[100], c;
int i;
printf("Enter the string: ");
scanf("%s", string);
i = strlen(string); // length of user input till first space
do{
scanf("%c", &c);
string[i++] = c; // reading characters after first space (including it)
}while (c != '\n'); // until user hits Enter
string[i - 1] = 0; // string terminating
return 0;
}
How this works? When user inputs characters from standard input, they will be stored in string variable until first blank space. After that, rest of entry will remain in input stream, and wait for next scanf. Next, we have a for loop that takes char by char from input stream (till \n) and appends them to end of string variable, thus forming a complete string same as user input from keyboard.

char Input in C by scanf

Help me Please.
I want to know why it happen.
This code is not give right answer:
#include < stdio.h>
int main()
{
char c,ch;
int i;
printf("Welcome buddy!\n\nPlease input first character of your name: ");
scanf("%c",&c);
printf("\nPlease input first character of your lovers name: ");
scanf("%c",&ch);
printf("\nHow many children do you want? ");
scanf("%d",&i);
printf("\n\n%c loves %c and %c want %d children",c,ch,c,i);
return 0;
}
but this code give right answer.
#include < stdio.h>
int main()
{
char c,ch;
int i;
printf("Welcome buddy!\n\nPlease input first character of your name: ");
scanf(" %c",&c);
printf("\nPlease input first character of your lovers name: ");
scanf(" %c",&ch);
printf("\nHow many children do you want? ");
scanf("%d",&i);
printf("\n\n%c loves %c and %c want %d children",c,ch,c,i);
return 0;
}
Why?
and How?
Please help me anyone who know this why it happend.
While you are giving like this, It will not ignore the white spaces.
scanf("%c",&ch);
When you are giving the input to the first scanf then you will give the enter('\n'). It is one character so it will take that as input to the second scanf. So second input will not get input from the user.
scanf(" %c",&ch);
If you give like this, then it will ignore that white space character, then it will ask for the input from the user.
The first program doesn't work properly, because the scanf function when checking for input doesn't remove automatically whitespaces when trying to parse characters.
So in the first program the value of c will be a char and the value of ch will be the '\n' (newline) char.
Using scanf("\n%c", &varname); or scanf(" %c", &varname); will parse the newline inserted while pressing enter.
The scanf function reads data from standard input stream stdin.
int scanf(const char *format, …);
The white-space characters in format, such as blanks and new-line characters, causes scanf to read, but not store, all consecutive white-space characters in the input up to the next character that is not a white-space character.
Now, when you press, by example, "a" and "return", you have two chars in the stdin stream: a and the \n char.
That is why the second call to scanf assign the \n char to ch var.
your scanf() function takes input from stdin. Now when you hit any character from keyboard and hit enter, character entered by you is scanned by scanf() but still enter is present in stdin which will be scanned by scanf() below it. To ignore white spaces you have to use scanf() with " %c".

Trouble using char in scanf in a structure

I'm a student studying C, and seem to be stuck when using Structures and Arrays to read in characters as part of the array.
When I run the code, it skips over the char scanf and will not read in any characters. There is no problem reading in integers etc.
For example (This is an example, my code is much longer but I know there's a problem here). Is the scanf part that reads in the name correct?
struct stud s[5];
int i = 0;
for (int i = 0; i < 5; i++)
{
fflush(stdout);
s[i].no = i + 1;
printf("\nStud number %d\n", s[i].no);
printf("Enter name:");
scanf_s("%c", &s[i].name);
printf("Enter grade: ");
scanf_s("%d", &s[i].grade);
printf("Successfully added to grade book\n");
}
I declared them below:
struct stud {
int no;
char name;
int grade;
};
It would be great if someone could point me in the correct direction?
You have to declare name as a char array
struct room {
int no;
char name[32]; /* pick a reasonable size */
int grade;
};
And then this
scanf_s("%c",&s[i].name);
would change to
scanf_s("%s",s[i].name, _countof(s[i].name));
and since there is no guarantee that the name would be 31 characters length, you have to specify a field length like this
scanf_s("%31s",s[i].name, _countof(s[i].name));
the length should be the sizeOfArray - 1 since c strings need to mark the end of the string with a null byte '\0', and scanf_s will append that byte to the read string.
If you don't specify the field length and it turns out that there are more than characters than requested by _countof(s[i].name) then nothing is read, for more information read here.
Note that you should create a char array of a reasonable size and use %s as mentioned by #iharob in his answer if you want to enter more than 1 character for a student. If you want name to be a char,then change
scanf_s("%c", &s[i].name);
To
scanf_s(" %c", &s[i].name, 1);
The space before %c skips all kinds of blanks(like newlines and spaces) present in the stdin and %c will then scan a non-whitespace character.
The %c will not the characters because the characters will be present in stdin, and you have to skip the characters.
scanf_s("%c", &s[i].name);
if the last character in the previous is \n the %c will take the \n as input.
You have to change the code, just give a space before the %c.
scanf_s(" %c", &s[i].name);
This will flush the white space characters in the stdin and it will get the input.

Resources