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.
Answer from Karthikeyan.R.S on Stack OverflowWhile 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 %c conversion specifier won't automatically skip any leading whitespace, so if there's a stray newline in the input stream (from a previous entry, for example) the scanf call will consume it immediately.
One way around the problem is to put a blank space before the conversion specifier in the format string:
scanf(" %c", &c);
The blank in the format string tells scanf to skip leading whitespace, and the first non-whitespace character will be read with the %c conversion specifier.
First of all, avoid scanf(). Using it is not worth the pain.
See: Why does everyone say not to use scanf? What should I use instead?
Using a whitespace character in scanf() would ignore any number of whitespace characters left in the input stream, what if you need to read more inputs? Consider:
#include <stdio.h>
int main(void)
{
char ch1, ch2;
scanf("%c", &ch1); /* Leaves the newline in the input */
scanf(" %c", &ch2); /* The leading whitespace ensures it's the
previous newline is ignored */
printf("ch1: %c, ch2: %c\n", ch1, ch2);
/* All good so far */
char ch3;
scanf("%c", &ch3); /* Doesn't read input due to the same problem */
printf("ch3: %c\n", ch3);
return 0;
}
While the 3rd scanf() can be fixed in the same way using a leading whitespace, it's not always going to that simple as above.
Another major problem is, scanf() will not discard any input in the input stream if it doesn't match the format. For example, if you input abc for an int such as: scanf("%d", &int_var); then abc will have to read and discarded. Consider:
#include <stdio.h>
int main(void)
{
int i;
while(1) {
if (scanf("%d", &i) != 1) { /* Input "abc" */
printf("Invalid input. Try again\n");
} else {
break;
}
}
printf("Int read: %d\n", i);
return 0;
}
Another common problem is mixing scanf() and fgets(). Consider:
#include <stdio.h>
int main(void)
{
int age;
char name[256];
printf("Input your age:");
scanf("%d", &age); /* Input 10 */
printf("Input your full name [firstname lastname]");
fgets(name, sizeof name, stdin); /* Doesn't read! */
return 0;
}
The call to fgets() doesn't wait for input because the newline left by the previous scanf() call is read and fgets() terminates input reading when it encounters a newline.
There are many other similar problems associated with scanf(). That's why it's generally recommended to avoid it.
So, what's the alternative? Use fgets() function instead in the following fashion to read a single character:
#include <stdio.h>
int main(void)
{
char line[256];
char ch;
if (fgets(line, sizeof line, stdin) == NULL) {
printf("Input error.\n");
exit(1);
}
ch = line[0];
printf("Character read: %c\n", ch);
return 0;
}
One detail to be aware of when using fgets() will read in the newline character if there's enough room in the inut buffer. If it's not desirable then you can remove it:
char line[256];
if (fgets(line, sizeof line, stdin) == NULL) {
printf("Input error.\n");
exit(1);
}
line[strcpsn(line, "\n")] = 0; /* removes the trailing newline, if present */
For the %c specifier, scanf needs the address of the location into which the character is to be stored, but printf needs the value of the character, not its address. In C, an array decays into a pointer to the first element of the array when referenced. So, the scanf is being passed the address of the first element of the name array, which is where the character will be stored; however, the printf is also being passed the address, which is wrong. The printf should be like this:
printf("%c", name[0]);
Note that the scanf argument is technically ok, it is a little weird to be passing an array, when a pointer to a single character would suffice. It would be better to declare a single character and pass its address explicitly:
char c;
scanf("%c", &c);
printf("%c", c);
On the other hand, if you were trying to read a string instead of a single character, then you should be using %s instead of %c.
Either Read a single char
char name[2];
scanf("%c",name);
printf("%c",name[0]);
Or read a string
char name[2];
scanf("%1s",name);
printf("%s",name);
Your type for scores (int scores[row];) does not correspond to your attempt to read scores with scanf (scanf("%s", &scores);). The "%s" conversion specifier is for converting whitespace separated strings, not integers. The "%d" conversion specifier is provided for integer conversions.
Before looking at specifics. Any time you have a coding task of coordinating differing types of data as a single unit, (e.g. student each with a name (char*) and a score (int), you should be thinking about using a struct containing the name and score as members. That way there is only a single array of struct needed rather than trying to coordinate multiple arrays of differing types to contain the same information.
Also, don't skimp on buffer size for character arrays. You would rather be 10,000 characters too long than 1-character too short. If you think your maximum name is 10-16 character, use a 64-char (or larger) buffer to insure you can read the entire line of data - eliminating the chance that a few stray characters typed could result in characters remaining unread in stdin.
A simple stuct is all that is needed. You can add a typedef for convenience (to avoid having to type struct name_of_struct for each declaration or parameter), e.g.
#include <stdio.h>
#define ROW 5 /* if you need a constant, #define one (or more) */
#define COL 64
typedef struct { /* delcare a simple struct with name/score */
char name[COL]; /* (add a typedef for convenience) */
int score;
} student_t;
Now you have a structure that contains your student name and score as a single unit rather than two arrays, one char and one int you have to deal with.[1]
All that remains is declaring an array of student_t for use in your code, e.g.
int main (void) {
int n = 0; /* declare counter */
student_t student[ROW] = {{ .name = "" }}; /* array of struct */
puts ("\n[note; press Enter alone to end input]\n");
With the array of struct declared, you can turn to your input handling. A robust way of handling input is to loop continually, validating that you receive the input you expects on each iteration, handling any errors that arise (gracefully so that your code continues), and keeping track of the number of inputs made so that you can protect your array bounds and avoid invoking Undefined Behavior by writing beyond the end of your array.
You could begin your input loop, prompting and reading your line of input with fgets as mentioned in my comment. That has multiple advantages over attempting each input with scanf. Most notably because what remains unread in the input buffer (stdin here) doesn't depend on the conversion specifier used. The entire line (up to and including the trailing '\n') is extracted from the input buffer and place in buffer you give fgets to fill. You can also check if the user simply presses Enter which you can use to conveniently indicate end of input, e.g.
for (;;) { /* loop until all input given or empty line entered */
char buf[COL]; /* declare buffer to hold line */
fputs ("Enter student name: ", stdout); /* prompt */
if (!fgets (buf, sizeof buf, stdin)) /* read/validate line */
break;
if (*buf == '\n') /* check for empty line */
break;
(note you can (and should) additionally check the string length of the buffer filled to (1) check that the last character read is '\n' ensuring the complete line was read; and (2) if the last char isn't '\n' checking whether the length is equal to the maximum length (-1) indicating that characters may be left unread. (that is left to you)
Now that you know you have a line of input and it's not empty, you can call sscanf to parse the line into the name and score for each student while handling any failure in conversion gracefully, e.g.
/* parse line into name and score - validate! */
if (sscanf (buf, "%63s %d", student[n].name, &student[n].score) != 2)
{ /* handle error */
fputs (" error: invalid input, conversion failed.\n", stderr);
continue;
}
n++; /* increment row count - after validating */
if (n == ROW) { /* check if array full (protect array bounds) */
fputs ("\narray full - input complete.\n", stdout);
break;
}
}
If you are paying attention, you can see one of the benefits of using the fgets and sscanf approach from a robustness standpoint. You get independent validations of (1) the read of user input; and (2) the separation (or parsing) of that input into the needed values. A failure in either case can be handled appropriately.
Putting all the pieces together into a short program, you could do the following:
#include <stdio.h>
#define ROW 5 /* if you need a constant, #define one (or more) */
#define COL 64
typedef struct { /* delcare a simple struct with name/score */
char name[COL]; /* (add a typedef for convenience) */
int score;
} student_t;
int main (void) {
int n = 0; /* declare counter */
student_t student[ROW] = {{ .name = "" }}; /* array of struct */
puts ("\n[note; press Enter alone to end input]\n");
for (;;) { /* loop until all input given or empty line entered */
char buf[COL]; /* declare buffer to hold line */
fputs ("Enter student name: ", stdout); /* prompt */
if (!fgets (buf, sizeof buf, stdin)) /* read/validate line */
break;
if (*buf == '\n') /* check for empty line */
break;
/* parse line into name and score - validate! */
if (sscanf (buf, "%63s %d", student[n].name, &student[n].score) != 2)
{ /* handle error */
fputs (" error: invalid input, conversion failed.\n", stderr);
continue;
}
n++; /* increment row count - after validating */
if (n == ROW) { /* check if array full (protect array bounds) */
fputs ("\narray full - input complete.\n", stdout);
break;
}
}
for (int i = 0; i < n; i++) /* output stored names and values */
printf ("%-16s %3d\n", student[i].name, student[i].score);
}
Example Use/Output
When ever you write an input routine -- Go Try and Break It!. Intentionally enter invalid data. If your input routine breaks -- Go Fix It!. In the code as noted the only check left for you to implement and handle is input greater than COL number of characters (e.g. the cat steps on the keyboard). Exercise your input:
$ ./bin/studentnamescore
[note; press Enter alone to end input]
Enter student name: zach 85
Enter student name: the dummy that didn't pass
error: invalid input, conversion failed.
Enter student name: kevin 96
Enter student name: nick 56
Enter student name: martha88
error: invalid input, conversion failed.
Enter student name: martha 88
Enter student name: tim 77
array full - input complete.
zach 85
kevin 96
nick 56
martha 88
tim 77
While you can use two separate arrays, a single array of struct is a much better approach. Look things over and let me know if you have further questions.
footnotes:
- Be aware that POSIX specifies that names ending with suffix
_tare reserved for its use. (size_t, uint64_t, etc...) Also be aware you will see that suffix used in common practice. So check before you make up your own (but we no there is no POSIXstudent_ttype).
You are almost there. However you have to make sure you do things cleanly Let's just do this step by step:
Step 1, get ONE name and ONE score
#include <stdio.h>
#define MAX_NAME_LENGTH 30
int main() {
char name[MAX_NAME_LENGTH+1]; /* an array of characters making up ONE name (+1 for terminating NUL char in case of max-length name) */
unsigned int score; /* a score */
scanf("%30s", name); /* scan a name (assuming NO spaces in the name)*/
/* also notice that name has no & in front of it because it already IS a pointer to the array name[MAX_NAME_LENGTH] */
scanf("%u", &score);
printf("%s scored %u in the test\n", name, score);
return 0;
}
(See it run at http://tpcg.io/jS3woS)
STEP 2 -- Iterate to get multiple scores
Now let's read in 5 pairs and then print out 5 pairs.
#include <stdio.h>
#define MAX_NAME_LENGTH 30
/* i called rows iterations here just to provide contrast */
/* you can call them ROWS if you want but it then creates a confusion about name length */
#define ITERATIONS 5
int main() {
char name[ITERATIONS][MAX_NAME_LENGTH+1]; /* an array of names where each name is MAX_NAME_LENGTH long (notice the order) */
unsigned int score[ITERATIONS]; /* score */
int i;
for(i = 0; i < ITERATIONS; i++ ) {
scanf("%30s", name[i]); /* scan a name (assuming NO spaces in the name)*/
/* notice that name[i] has no & in front of it because name[i] is the pointer to the i-th row */
scanf("%u", &score[i]);
}
for(i = 0; i < ITERATIONS; i++ ) {
printf("%s scored %u in the test\n", name[i], score[i]);
}
return 0;
}
See it in action here (http://tpcg.io/iTj4ag)