I am trying to get a name in an array " char name[100][100]". I tried doing many thing like these, but none work.Can you help me?
The code: Its a simple student's grade system i think, but only prints "" when trying to save a name.
#include <stdio.h>
#include <string.h>
void insert();
char name[100][100];float f[20];int z;
int main()
{
int x=0;
do{
printf("<1> Insert student\n");
printf("=> ");
scanf("%d",&x);
printf("\n*************************************************************\n");
switch(x){
case 1:
insert();
break;
default: printf("NO");
break;
}
}while(insert >=0 );
return 0;
}
void insert()
{
int x;
int y=0;
float n1,n2,p;
printf("How many students?: ");
scanf("%d",&y);
for(x=0;x<y;x++){
printf("Insert name: ");
fgets(name[x], 100, stdin);
int len = strlen(name[x]);
if (name[x][len-1] == '\n') {
name[x][len-1] = '\0';
}
printf("name[%d] = \"%s\"\n", x, name[x]);
printf("Insert first grade: ");
scanf("%f",&n1);
printf("Insert second grade: ");
scanf("%f",&n2);
printf("Insert final grade: ");
scanf("%f",&p);
f[x] = (n1 * 0.3)+(n2 * 0.3)+(p * 0.4);
z++;
}
for(x=0;x<z;x++){
if(f[x] < 6){
printf("the final grade of %s is: %.2f \n",name[x], f[x]);}
else{printf("the final grade de %s es: %.2f \n",name[x], f[x]);}
}
}
You should bear in mind that fgets() returns the new-line as well, if there's enough space in the buffer. You might want to take it out:
#include <stdio.h>
#include <string.h>
int main()
{
char name[100][100];
int y = 5;
int x = 0;
for (x = 0; x < y; x++) {
printf("Insert name: ");
fgets(name[x], 100, stdin);
int len = strlen(name[x]);
if (name[x][len-1] == '\n') {
name[x][len-1] = '\0';
}
printf("name[%d] = \"%s\"\n", x, name[x]);
}
}
Why are you using that %[^\t\n] string format? You should just go with a %s string format if you want to read a string (or, better, a %100s to limit the number of characters read).
scanf("%100s",name[x]) works just fine, but will mess things up when you try to use spaces (i.e. the scanf() will read one word at a time).
To avoid that, you can use the second option, that is fgets(). But, in this case, you need to pay attention to the final \n character that is appended to the string. To prevent the newline character from ending your string, you can simply do the following:
name[x][strlen(name[x])-1] = 0;
The previous code simply replaces the \n character with a null byte, thus ending the string and "ignoring" the newline.
EDIT:
The thing you need to understand is that the standard input (i.e. the keyboard input usually) is handled as if it were a file (in fact, you can use functions like fgets(), as if you were reading a normal file). So, as it happens with normal files, each line ends with a special character, \n. Every time you enter an input, and you press "Enter", a newline character is appended to your input.
There's a couple of things you need to know to understand what it is that you're doing wrong:
Some functions (like fgets()) read a line until a newline character is found. The newline character is also read, and returned in the string that was just read.
Other functions (like scanf()) also read lines until some special characters (such as or \n) are found. But, in this case, the final character is not read.
And, last: every time you open a file, the process keeps count of the number of characters you have read from the beginning of the file (or, to put it in an easier (and more correct) way, it "stores" a "pointer" to the next character that should be read).
With this being said, let's have a look at what happens with your program: first, the number of students is read (using scanf()), and, then, a name is read (using fgets()).
So, your input "file", looks like:
4\n
^
John Smith\n
...
The ^ is a pointer to the next character that should be read (and isn't, obviously, part of the input).
After the scanf() (which, as I mentioned, won't read the \n), the situation will be the following:
4\n
^
John Smith\n
...
Now, when you read the next line using fgets(), the "pointer" is already pointing to a newline character, and will therefore assume (correctly!) that the line has ended. The string you are reading is therefore "\n", instead of "John Smith\n".
The easiest way to fix this problem is to read, after every scanf(), single characters from standard input until a newline character is encountered.
scanf ( ... );
while (getc(stdin)!='\n');
Usually reading a single character should be enough, but in some cases (e.g. 4 \n) a single getc() isn't effective.
Basically, whenever a character is read from the file, the "pointer" is updated.
I really hope this cleared things up a bit. It isn't that easy to understand these details at first but, as you get more experience, things will definitely become clearer!
Related
I want the output to print the data that we print. but it is not working as expected and the output is not displaying and it is exiting
#include <stdio.h>
int main() {
char name[20], department[3], section[1];
printf("enter the name of the student:");
scanf("%s", name);
printf("enter your department:");
scanf("%s", department);
printf("enter the section");
scanf("%s", section);
printf("Name:%s \n Department:%s \n Section: %s ", name, department, section);
return 0;
}
Your program has undefined behavior because the arrays are too short and scanf() stores the user input beyond the end of the arrays, especially the last one, section that can only contain an empty string which scanf() cannot read anyway.
Make the arrays larger and tell scanf() the maximum number of characters to store before the null terminator, ie: the size of the array minus 1.
Here is a modified version:
#include <stdio.h>
int main() {
char name[50], department[50], section[50];
printf("enter the name of the student:");
if (scanf("%49s", name) != 1)
return 1;
printf("enter your department:");
if (scanf("%49s", department) != 1)
return 1;
printf("enter the section");
if (scanf("%49s", section) != 1)
return 1;
printf("Name:%s\n Department:%s\n Section: %s\n", name, department, section);
return 0;
}
Note that using scanf with a %s conversion requires that each data item be a single word without embedded spaces. If you want name, department and section to accommodate spaces, which is more realistic for anyone besides Superman Krypton A, you would use %[\n] with an initial space to skip pending whitespace and newlines (or fgets() but in another chapter):
#include <stdio.h>
int main() {
char name[50], department[50], section[50];
printf("enter the name of the student:");
if (scanf(" %49[^\n]", name) != 1)
return 1;
printf("enter your department:");
if (scanf(" %49[^\n]", department) != 1)
return 1;
printf("enter the section");
if (scanf(" %49[^\n]", section) != 1)
return 1;
printf("Name:%s\n Department:%s\n Section: %s\n", name, department, section);
return 0;
}
scanf(" %49[^\n]", name) means skip any initial whitespace, including pending newlines from previous input, read and store and bytes read different from newline, up to a maximum of 49 bytes, append a null byte and return 1 for success, 0 for conversion failure or EOF is end of file is reached without storing any byte. For this particular call, conversion failure can happen if there is an encoding error in the currently selected locale.
The problem is that you have not accounted for the null character. It should work with the following.
char name[20] , department[4] , section[2];
The reason this happens is that C requires an extra character for the null character \0 which tells the program when the string ends.
first of all you should respect the size of string ,so you should either convert section to char or increase the size of that string because you have here the problem of '\0' character...so the rule is : the size of string is the size what you need + 1 for '\0' NULL character
and her is two program i tried to Modification you program for two scenarios :
#include <stdio.h>
int main(){
/// any size you like just respect the NULL character
char name[20],department[4],section[23];
printf("enter the name of the student:");
scanf("%s",name);
printf("enter your department:");
scanf("%s",department);
printf("enter the section");
scanf ("%s",section);
printf("Name:%s \n Department:%s \n Section:%s ", name,department,section);
return 0;
}
and case of char :
#include <stdio.h>
int main(){
char name[20],department[4];
char section;
printf("enter the name of the student:");
scanf("%s",name);
printf("enter your department:");
scanf("%s",department);
printf("enter the section");
///don't forget this space before %c it is important
scanf (" %c",§ion);
printf("Name:%s \n Department:%s \n Section:%c ", name,department,section);
return 0;
}
I watched for a long time and finally found the problem.
This is problem: char section[1];.
You declared the size is too short.
It looks like this after you declared it: section[0] = '\0';.
If you scanf a, the array data like section[0] = 'a';, and then it automatically add '\0' somewhere, so you got a memory leaking.
So replace char section[1]; to char section[2];.
I will not insist in the reasons of the other answers (that state other problems in your code than the one you are asking for) but I'll limit my answer to the reasons you don't get any output before the first prompt (there's no undefined behaviour before the third call of printf if you have input short enough strings to not overflow the arrays --- the last is impossible as long as you input one char, because to input one char you heed at least space for two)
I want the output to print the data that we print. but it is not working as expected and the output is not displaying and it is exiting
stdio works in linebuffer mode when output is directed to a terminal, which means that output is written to the terminal in the following cases:
The buffer is filled completely. This is not going to happen with a sort set of strings.
There is a \n in the output string (which there isn't, as you want the cursor to remain in the same line for input as the prompt string)
As there is no \n in your prompts, you need to make printf flush the buffer at each call (just before calling the input routines) You have two ways of doing this.
Calling explicitly the function fflush(3), as in the example below:
printf("enter the name of the student:");
fflush(stdout); /* <-- this forces flushing the buffer */
if (scanf(" %49[^\n]", name) != 1)
return 1;
configuring stdout so it doesn't use buffers at all, so every call to printf forces a write to the standard output.
setbuf(stdout, NULL); /* this disables buffering completely on stdout */
/* ... later, when you need to print something */
printf("enter the name of the student:"); /* data will be printed */
if (scanf(" %49[^\n]", name) != 1)
return 1;
But use this facilities only when it is necessary, as the throughput of the program is degraded if you disable the normal buffering of stdio.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(){
int n=1,i,cont;
char string[50];
scanf("%d",&n);
while(n!=0){
gets(string);
cont=0;
for(i=0;i<strlen(string);i++){
if(string[i]=='.'){
cont++;
}
}
if(cont%2==0){
printf("S\n");
}else{
printf("N\n");
}
scanf("%d",&n);
}
return 0;
}
My problem is quite simple but troublesome, I want to read an integer value n, and then read a string, after that read n again, but whenever I run the program, it only reads the string value... but if I digit 0 the program ends... it's like my scanf is within the gets function.
Mixing scanf with gets or fgets is troublesome because they each handle newlines differently.
Get rid of the gets call (which is unsafe anyway) and replace it with the following scanf call:
scanf("%49s", string);
This will read at most 49 characters into string (i.e. one less that its size).
From OP's comments, it sounds like the goal is to be able to read strings containing spaces. While there are ways to accomplish this using scanf(), it would be better to use fgets(), which is at the least less error-prone.
The fgets() function can be used to read input for the number into a buffer, and this buffer can then be processed by sscanf() to extract the number. Since fgets() keeps the newline character, it is not left behind to interfere with the next I/O operation.
But, when fgets() is used to get the string, since the newline is retained, it may be desirable to remove it. This can be accomplished in a number of ways, but here strcspn() is used to provide the index of the first \r or \n character encountered; a \0 character is then written to this location, removing the terminating newline from the string.
The code below illustrates these suggestions. Note that both buffer[] and string[] are generously allocated to accommodate reasonably large inputs. If a user enters a large number of characters (more than 999 in this case), the extra characters are left behind in the input stream for the next I/O function call. Also note that the main loop has been streamlined a bit; now there is a for(;;) loop that never terminates, broken out of when the user enters 0 for the number. And, there is a nested loop within the main loop that prompts the user to enter a number until a valid number is entered. Since the #include <stdlib.h> was unnecessary, it was removed. Better code would check the values returned from the calls to fgets() for possible errors.
#include<stdio.h>
#include<string.h>
int main(void)
{
int n = 1, cont;
char buffer[1000];
char string[1000];
for (;;) {
/* Loop until user enters a number */
do {
printf("Please enter a number: ");
fgets(buffer, sizeof buffer, stdin);
} while (sscanf(buffer, "%d", &n) != 1);
/* Break on 0 */
if (n == 0) break;
/* Get a string, and remove trailing newline */
printf("Please enter a string\n");
fgets(string, sizeof string, stdin);
string[strcspn(string, "\r\n")] = '\0';
cont = 0;
for (size_t i = 0; i < strlen(string); i++) {
if (string[i] == '.') {
cont++;
}
}
if (cont % 2 == 0){
printf("S\n");
} else {
printf("N\n");
}
}
return 0;
}
When you enter 5 for an example, you hit a new line character afterwards.
So you are entering 2 characters: 5 and a new line character.
That new line character is causing your headache.
The new line character is also considered an input.
In order to ignore this new line char, simply add a new line that acts as a garbage collection:
char garbage[50];
scanf( "%d", &n);
fgets(garbage, sizeof(garbage), stdin);
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(){
int n=1,i,cont;
char string[50];
scanf("%d",&n);
while(n!=0){
gets(string);
cont=0;
for(i=0;i<strlen(string);i++){
if(string[i]=='.'){
cont++;
}
}
if(cont%2==0){
printf("S\n");
}else{
printf("N\n");
}
scanf("%d",&n);
}
return 0;
}
My problem is quite simple but troublesome, I want to read an integer value n, and then read a string, after that read n again, but whenever I run the program, it only reads the string value... but if I digit 0 the program ends... it's like my scanf is within the gets function.
Mixing scanf with gets or fgets is troublesome because they each handle newlines differently.
Get rid of the gets call (which is unsafe anyway) and replace it with the following scanf call:
scanf("%49s", string);
This will read at most 49 characters into string (i.e. one less that its size).
From OP's comments, it sounds like the goal is to be able to read strings containing spaces. While there are ways to accomplish this using scanf(), it would be better to use fgets(), which is at the least less error-prone.
The fgets() function can be used to read input for the number into a buffer, and this buffer can then be processed by sscanf() to extract the number. Since fgets() keeps the newline character, it is not left behind to interfere with the next I/O operation.
But, when fgets() is used to get the string, since the newline is retained, it may be desirable to remove it. This can be accomplished in a number of ways, but here strcspn() is used to provide the index of the first \r or \n character encountered; a \0 character is then written to this location, removing the terminating newline from the string.
The code below illustrates these suggestions. Note that both buffer[] and string[] are generously allocated to accommodate reasonably large inputs. If a user enters a large number of characters (more than 999 in this case), the extra characters are left behind in the input stream for the next I/O function call. Also note that the main loop has been streamlined a bit; now there is a for(;;) loop that never terminates, broken out of when the user enters 0 for the number. And, there is a nested loop within the main loop that prompts the user to enter a number until a valid number is entered. Since the #include <stdlib.h> was unnecessary, it was removed. Better code would check the values returned from the calls to fgets() for possible errors.
#include<stdio.h>
#include<string.h>
int main(void)
{
int n = 1, cont;
char buffer[1000];
char string[1000];
for (;;) {
/* Loop until user enters a number */
do {
printf("Please enter a number: ");
fgets(buffer, sizeof buffer, stdin);
} while (sscanf(buffer, "%d", &n) != 1);
/* Break on 0 */
if (n == 0) break;
/* Get a string, and remove trailing newline */
printf("Please enter a string\n");
fgets(string, sizeof string, stdin);
string[strcspn(string, "\r\n")] = '\0';
cont = 0;
for (size_t i = 0; i < strlen(string); i++) {
if (string[i] == '.') {
cont++;
}
}
if (cont % 2 == 0){
printf("S\n");
} else {
printf("N\n");
}
}
return 0;
}
When you enter 5 for an example, you hit a new line character afterwards.
So you are entering 2 characters: 5 and a new line character.
That new line character is causing your headache.
The new line character is also considered an input.
In order to ignore this new line char, simply add a new line that acts as a garbage collection:
char garbage[50];
scanf( "%d", &n);
fgets(garbage, sizeof(garbage), stdin);
#include < stdio.h >
#include < process.h >
rec();
main() {
int a, fact;
char question, n, y;
do {
printf("\nEnter any number ");
scanf("%d", & a);
fact = rec(a);
printf("Factorial value = %d\n", fact);
printf("do you want to exit.....(y/n):");
scanf("%s", & question);
}
while (question == n);
exit(0);
}
rec(int x) {
int f;
if (x == 1) return 1;
else f = x * rec(x - 1);
return f;
}
In this program I want to get factorial of the entered number, which I get. But I also want the user to say whether to exit or get the factorial of another number, which I can't do. It asks user but when I enter "n" it exits.
Where is the error?
You want
while (question == 'n');
Or
char question, n = 'n', y = 'y';
Though I find the 2nd version a little redundant.
Either way you need to change
scanf("%s"
to
scanf("%c"
To correctly read in a single char and not a string. Thanks RageD
One problem is the combination of:
char question, n, y;
scanf("%s", &question);
You are using %s to read a null-terminated string into a single character. Even if you hit 'y' and return, you'll be overwriting beyond the end of the variable. This is not good. (The good news is that "%s" skips over white space, including the newline after the number).
You either need to use "%c" in the format:
char question;
scanf(" %c", &question); // NB: The leading space is important!
or you need to use a string format and a string variable (and no &):
char question[10];
scanf("%9s", question);
If you use an array, you need to consider whether to use strcmp(), or whether to compare the first character from the input:
while (strcmp(question, "n") == 0);
while (question[0] == 'n');
You probably got told by the compiler that you'd not declared variable n so you added it. You probably need the loop to end with while (question == 'n');and then get rid of the (now) unused variablen(and the currently unused variabley`).
Note that if you use omit the space in the " %c" format string:
scanf("%c", &question);
then it will normally get the newline after the number, which won't be 'n', so your loop will exit every time, apparently without waiting for you to enter anything. You can finesse that with scanf(" %c", &question); which skips white space before reading a character.
You should test that scanf() received the input you expected each time you use it. The correct test for single item inputs is:
if (scanf(" %c", &question) != 1)
...input failed...
If you need to distinguish between EOF and conversion failure, you can capture the return from scanf():
int rc;
if ((rc = scanf(" %c", &question)) != 1)
...rc == EOF on EOF; rc == 0 on 'conversion failure'...
...a single character input can't easily fail...
...but if someone types 'a' instead of '9' when you're looking for a number...
Getting I/O right using scanf() is distressingly hard. Many experienced programmers simply don't use it; it is too hard to get right. Instead, we use fgets() or POSIX getline() to read a line of data, and then use sscanf() to parse it. There are many advantages to this, but a primary one is that the newline has been eaten so you don't run into problems with the variable question not containing the answer you expect.
I am writing a super simple command line based program in C. It's just a small test and the code is very simple. So what it is meant to do is to ask the user for their name, maths grade, english grade, computing grade. Then it figures out their average grade and also tells them the name they entered. Yes I know this is an extremely simple program, but I'm still doing something wrong.
The problem is, one part of my code will run first telling the user to enter their name and then once they do this and press enter the rest of my code will run all at once and then stop working. It's weird I just don't understand what is wrong.
#include <stdio.h>
int main(int argc, const char * argv[])
{
char chr;
char firstname;
int mathsmark, englishmark, computingmark, averagemark;
printf("What is your name?\n");
scanf("%c", &firstname);
printf("\n");
printf("What is your maths mark?\n");
scanf("%d", &mathsmark);
printf("\n");
printf("What is your english mark?\n");
scanf("%d", &englishmark);
printf("\n");
printf("What is your computing mark?\n");
scanf("%d", &computingmark);
printf("\n");
printf("Your name is: %c", firstname);
printf("\n");
averagemark = (mathsmark + englishmark + computingmark) / 3;
printf("%d", averagemark);
printf("\n");
chr = '\0';
while (chr != '\n') {
chr = getchar ();
}
return 0;
}
One major problem is that you've declared firstname to be a single character long, and when you try to read the name from the console, you're using the %c conversion specifier, which reads the next single character from the input stream and stores it to firstname. The remainder of the name is left in the input stream to foul up the remaining scanf calls.
For example, if you type "Jacob" as a first name, then the first scanf call assigns J to firstname, leaving "acob\n" in the input stream.
The next scanf call attempts to convert "acob\n" to an integer value and save it to mathsmark, which fails ("acob\n" is not a valid integer string). Same thing happens for the next two scanf calls.
The last loop
while (chr != '\n')
{
chr = getchar();
}
finally consumes the rest of "acob\n", which contains the newline character (because you hit Enter after typing the name), causing the loop and program to exit.
How do you fix this?
First, you need to declare firstname as an array of char:
char firstname[SOME_SIZE] = {0};
where SOME_SIZE is large enough to handle all your cases. The you need to change scanf call to
scanf("%s", firstname);
This tells scanf to read characters from the input stream up to the next whitespace character and store the results to the firstname array. Note that you don't need to use the & operator here; under most circumstances, an expression of array type will be converted ("decay") to an expression of pointer type, and the value of the expression will be the address of the first element in the array.
Note that scanf is not very safe, and it's not very robust. If you enter more characters than your buffer is sized to hold, scanf will happily store those extra characters to memory following the array, potentially clobbering something important. You can guard against this by using an explicit field width in the conversion specifier, like
scanf(*%29s", firstname);
but in general it's a pain.
scanf is also not very good at detecting bad input. If you enter "12er" as one of your marks, scanf will convert and assign the "12", leaving the "er" in the stream to foul up the next read.
scanf returns the number of successful assignments, so one way to guard against bad input is to check the return value, like so:
if (scanf("%d", &mathmarks) != 1)
{
printf("Bad input detected for math marks\n");
}
Unfortunately, scanf won't remove bad characters from the stream; you'll have to do that yourself using getchar or similar.
This is a common mistake amongst newer C/C++ developers. The scanf function detects you hitting the ENTER/RETURN key to signal the end of input, but it also catches the \n character as well at the end of the input string, so you essentially get two RETURNS being detected.
Please read up on an example of using fgets and sscanf here:
http://www.linuxforums.org/forum/programming-scripting/67560-problem-scanf.html
It will resolve this issue very quickly for you. In the meantime, I strongly urge you to check out this book:
http://www.amazon.com/Primer-Plus-5th-Stephen-Prata/dp/0672326965
It is the most commonly used C programming book in high school and colleges in North America, and has TONS of examples for you to work through, including this specific program you demonstrated above. The print version has more examples than the e-book, so I would just cough up the $30.00 for the printed version.
Good luck!
You might want to look at a few tutorials. Maybe one on Format specifiers and one on strings in C
scanf() reads data from stdin and stores them as specified by the format specifiers. In this case:
char firstname;
scanf("%c", &firstname);
Read 1 character from stdin and store it to firstname:
>> What is your first name?
Mike
Now firstname == 'M' because scanf() read 1 character as we requested.
What you wanted to do was read a string (a bunch of characters):
char firstname[5]; // an array of characters
scanf("%s", firstname); // store as a string
firstname[4] = '\0'; // Truncate the result with a NULL to insure no overflow
>> What is your first name?
Mike
Now firstname is [M][i][k][e][\0] because scanf() read 1 string, as we requested.
Note the same holds true for printf(), a printf with a %c will give you one character where as a printf() with a %s will give you all the characters until the NULL terminator.
You have (at least) two choices.
char firstname[number_big_enough_to_hold_long_name];
/*or */
char *firstname = malloc(sizeof(char) * number_big_enough_to_hold_long_name);
/* ... code ... */
free(firstname);
Further it would be best to limit width of read. scanf() does not know the size (available space) of firstname.
scanf("%number_big_enough_to_hold_long_names", ...
/* i.e. */
char firstname[32];
if(scanf("%31s", firstname) == EOF) {
perror("bad");
return 1;
}
Further you should check if there is anything left before trying next read. I.e. If someone enters "My Name" then only "My" will end up in firstname and "Name" will be left in input stream.
And getchar() returns an int not a char.
getchar
scanf
And search "ansi c char arrays tutorial" or similar.