There are multiple issues and misunderstandings in your question:
there is no %[^\n]s
conversion specification, the trailing s
is not part of the conversion, it acts as a character s
that must matched an input character, which will not happen since %[^\n]
only stops before a newline or at end of file.
fflush(stdin)
has undefined behavior. It does not flush the input stream. You can read and discard the remaining characters in the input line including the newline with a loop:
int c;
while ((c = getchar()) != EOF && c !+ '\n')
continue;
the difference between %s
and %[^\n]
is the behavior on whitespace characters: %s
ignores leading white space, including newlines, then reads and stores characters into the destination array until white space is read and pushed back into the input stream. Conversely %[^\n]
reads and stores any character except a newline, which is pushed back.
the consequence of the above behavior is scanf("%s", student)
ignores the pending newline left by scanf("%d", &roll_no)
and any other leading whitespace, then reads further input until the next whitespace character is found, which is left pending in the input stream. scanf("%[^\n]", student)
stops immediately and returns 0
because the pending newline is not ignored and does not match the specification. To skip this leading whitespace, you should use a space in the scanf
format string: scanf(" %[^\n]", student)
both %s
and %[^\n]
can store an arbitrary number of characters into the destination array if the input contains a long sequence of matching characters. This is a classic security flaw that can be exploited by attackers using carefully constructed input lines. You should pass the maximum number of characters to store as scanf("%999s", student)
or scanf(" %999[^\n]", student);
you should always test the return value of scanf()
to detect invalid or missing input and avoid undefined behavior when using the still uninitialized destination variables.
the prototype for main
without arguments is int main(void)
.
Here is a modified version:
#include <stdio.h>
int main(void) {
int roll_no;
char student[1000];
float physics, maths, chemistry;
printf("Enter your roll no.: ");
if (scanf("%d", &roll_no) != 1) {
fprintf(stderr, "invalid input\n");
return 1;
}
printf("\nEnter your name: ");
if (scanf(" %999[^\n]", student) != 1) {
fprintf(stderr, "invalid input\n");
return 1;
}
printf("\nEnter your physics: ");
if (scanf("%f", &physics) != 1) {
fprintf(stderr, "invalid input\n");
return 1;
}
printf("\nEnter your maths: ");
if (scanf("%f", &maths) != 1) {
fprintf(stderr, "invalid input\n");
return 1;
}
printf("\nEnter your chemistry: ");
if (scanf("%f", &chemistry) != 1) {
fprintf(stderr, "invalid input\n");
return 1;
}
printf("Student Name: %s\n"
"Physics Marks: %.2f Chemistry Marks: %.2f Maths Marks: %.2f",
student, physics, chemistry, maths);
return 0;
}
You can try and avoid code duplication and reprompt the user in case of error by using custom input functions such as in the modified version below:
#include <stdio.h>
int get_integer(const char *prompt, int *dest, int min, int max) {
for (;;) {
int val, c, res;
printf("%s: ", prompt);
res = scanf("%d", &val);
while ((c = getchar()) != EOF && c != '\n')
continue;
if (res == 1) {
if (val >= min || val <= max) {
*dest = val;
return 1;
}
printf("value %d out of range [%d..%d]\n", val, min, max);
} else
if (res == EOF || c == EOF) {
printf("unexpected end of file\n");
return 0;
} else {
printf("invalid input\n");
}
}
}
int get_float(const char *prompt, float *dest) {
for (;;) {
float val;
int c, res;
printf("%s: ", prompt);
res = scanf("%f", &val);
while ((c = getchar()) != EOF && c != '\n')
continue;
if (res == 1) {
*dest = val;
return 1;
} else
if (res == EOF || c == EOF) {
printf("unexpected end of file\n");
*dest = 0;
return 0;
} else {
printf("invalid input\n");
}
}
}
int get_string(const char *prompt, char *dest, size_t size) {
for (;;) {
int c;
size_t n = 0, i = 0;
printf("\n%s: ", prompt);
while ((c = getchar()) != EOF && c != '\n') {
if (i + 1 < size)
dest[i++] = (char)c;
n++;
}
if (i < size) {
dest[i] = '\0';
}
if (n == 0) {
if (c == EOF) {
printf("unexpected end of file\n");
return 0;
}
printf("string cannot be empty\n");
} else {
return 1;
}
}
}
int main(void) {
int roll_no;
char student[1000];
float physics, maths, chemistry;
if (!get_integer("Enter your roll no.", &roll_no, 0, 10000)
|| !get_string("Enter your name", student, sizeof student)
|| !get_float("Enter your physics marks", &physics)
|| !get_float("Enter your maths marks", &maths)
|| !get_float("Enter your chemistry marks", &chemistry)) {
return 1;
}
printf("Student Name: %s\n"
"Physics Marks: %.2f Chemistry Marks: %.2f Maths Marks: %.2f\n",
student, physics, chemistry, maths);
return 0;
}