I am really new to C and I am facing a problem with fgets(). I need to make multiple calls to fgets in order to retrieve 4 pieces of data, a name, age, num1 and num2. I cannot use scanf for this I have to use fgets. However, I am facing problems when I make multiple calls to fgets. And just to clarify I want to read num1 and num2 as strings. Here is my code:
int main(int argc, char const *argv[])
{
/* code */
char name[50];
char ageString[3];
char num1[6];
char num2[6];
printf("Enter your name: ");
fgets(name, 50, stdin);
printf("Enter an age: ");
fgets(ageString, 3, stdin);
printf("Enter num 1: ");
fgets(num1, 6, stdin);
printf("Enter num 2: ");
fgets(num2, 6, stdin);
// replace the trailing '\n' with '\0'
name[strcspn(name, "\n")] = '\0';
ageString[strcspn(ageString, "\n")] = '\0';
num1[strcspn(num1, "\n")] = '\0';
num2[strcspn(num2, "\n")] = '\0';
printf("Your name is: %s, you are %s years old, num1: %s, num2: %s\n", name, ageString, num1, num2);
return 0;
}
Here is what I get outputted in the terminal:
Enter your name: Random
Enter an age: 21
Enter num 1: Enter num 2: 1
Your name is: Random, you are 21 years old, num1: , num2: 1
The program reads name and age fine but the num1 is not being read and the formatting is really off.
If anyone has a fix for this that would be greatly appreciated. Again, I am very new to C so I am still learning.
Thank you!
The problem is that your array sizes are too small. When you type in "21\n" and fgets is called with 3 as the size, it reads 2 characters (not 3) The \n remains, so fgets next reads only the newline. The solution would be to to increase your array size by one (for that specific input) or "Don't skimp on Buffer Size...." (#David C. Rankin)
Related
This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
Closed 2 years ago.
MY CODE:
#include<stdio.h>
char main()
{
char g1,g2,g3;
printf("Enter the grade of student 1: ");
scanf("%c",&g1);
printf("\nEnter the grade of student 2: ");
scanf("%c",&g2);
printf("\nEnter the grade of student 3: ");
scanf("%c",&g3);
printf("%c%c%c",g1,g2,g3);
return 0;
}
OUTPUT:
Enter the grade of student 1: A
Enter the grade of student 2:
Enter the grade of student 3:
//I am getting a line break and couldn't enter the value of student 2 and the cursor moves to student 3!!
Try doing:
#include<stdio.h>
char main()
{
char g1,g2,g3;
printf("Enter the grade of student 1: ");
scanf(" %c",&g1);
printf("\nEnter the grade of student 2: ");
scanf(" %c",&g2);
printf("\nEnter the grade of student 3: ");
scanf(" %c",&g3);
printf("%c%c%c",g1,g2,g3);
return 0;
}
Sorry, I'm new to this.
Just give a space before %c in scanf to get desired input. The below is your own code where I've added space in the second and third scanf statements.
#include<stdio.h>
char main()
{
char g1,g2,g3;
printf("Enter the grade of student 1: ");
scanf("%c",&g1);
printf("\nEnter the grade of student 2: ");
scanf(" %c",&g2);
printf("\nEnter the grade of student 3: ");
scanf(" %c",&g3);
printf("%c%c%c",g1,g2,g3);
return 0;
}
And well, the reason? If you don't, then the next scanf statement assumes the new line you create by pressing "Enter" as a new character, which is \n. So we add a space in scanf to let the statement know that space is not considered an input.
It is often easier to always read an entire line, like this:
#include <stdio.h>
void ReadLine(char result[], int resultLen)
{
int ch, i;
i = 0;
ch = getchar();
while ((ch != '\n') && (ch != EOF)) {
if (i < resultLen - 1) {
result[i] = ch;
i++;
}
ch = getchar();
}
result[i] = '\0';
}
int main(void)
{
char g1[2], g2[2] ,g3[2];
printf("Enter the grade of student 1: ");
ReadLine(g1, sizeof g1);
printf("Enter the grade of student 2: ");
ReadLine(g2, sizeof g2);
printf("Enter the grade of student 3: ");
ReadLine(g3, sizeof g3);
printf("%s%s%s\n", g1, g2, g3);
return 0;
}
first Scanf will not read/flush the "\n" after reading the single char.
this character on input buffer will make the 2nd and 3rd scanf to get execute and fail without actually prompting the user.
There are multiple ways to handle this.
read complete line
use gets/fgets to rad complete inputline
then use scanf to read from buffer
eg:
fgets(buff, 255, stdin);
sscanf(buff, "%c", &value);
execute a char read after every scanf statement.
getch()
Put a preceeding " " in front of every "%c" used in scanf.
this will skip the special char.
"scanf(" %c", &value);"
I know others have asked similar questions but they are often old posts with outdated code and solutions.
Regardless of whether I use scanf_s or fgets, it always seems to get skipped despite the fact that I have done this the exact same way on other PCs with the same version of VS and they work fine.
int main() {
char name[20];
name[0] = 0;
printf("Enter your name: ");
scanf_s("%[^\n]%*c", &name[0], 20);
printf("\n");
printf("Your name is %s", name);
}
What am I doing wrong that makes this an issue now but not when this is done elsewhere?
EDIT:
After recreating it and only it in another file and seeing a post (and commenting off certain sections and testing it) I now realize that another part of the code is messing with it. Specifically the scanf_s("%d", &age); of the following code:
int main() {
int age;
int ageDifference;
printf("Enter your age: ");
scanf_s("%d", &age);
if (age == 18) {
printf("You are 18 years old.");
}
else if (age > 18) {
ageDifference = age - 18;
printf("It has been %d years since you were 18.", ageDifference);
}
else {
ageDifference = 18 - age;
printf("It will be %d years before you are 18.", ageDifference);
}
printf("\n");
char name[20];
name[0] = 0;
printf("Enter your name: ");
scanf_s("%[^\n]%*c", name, 20);
printf("\n");
printf("Your name is %s", name);
return 0;
}
Screenshot of output: https://prnt.sc/qdo38t
Why is it causing it to skip it though?
Sorry for being such a noob at C too.
FIXED: Adding a space so that scanf_s("%[^\n]%*c", name, 20) is now scanf_s(" %[^\n]", name, 20) fixed it. Also %*c is not needed. Thanks #Weather Vane.
Let us walk through
printf("Enter your age: ");
User input 6 6 Enter
scanf_s("%d", &age);
scanf() reads "66", leaving the '\n' in stdin.
....
printf("Enter your name: ");
scanf_s() attmepts to read the '\n', which does not meet the criteria of "%[^\n]", so scanf_s() stops right away and does not return a 1 - still leaving the '\n' in stdin.
scanf_s("%[^\n]%*c", name, 20)
Code did not check scanf_s() results, Tsk, tsk, and so does not know that name[] remains unchanged.
Using a space as in " %[^\n]%*c" helps, to first consume the left-over '\n', but the best advice is to not use scanf(), scanf_s() at all. Use fgets() to read a line into a string and then parse the string with sscanf(), strtol(), etc.
In all cases, check the return value of input functions.
This question already has an answer here:
How to read / parse input in C? The FAQ
(1 answer)
Closed 6 years ago.
Hi consider the simple program below:
int main(void)
{
//exercise 1
float num2;
printf("please enter a number \n");
scanf_s("%f", &num2);
printf("the number multiple by 3 is %3.3f\n", num2 * 3);
//exercise 2
char ch1, ch2, ch3, ch4;
printf("enter a word with four char\n");
ch1 = getchar();
ch2 = getchar();
ch3 = getchar();
ch4 = getchar();
printf("the chars in reverse order are\n");
putchar(ch4);
putchar(ch3);
putchar(ch2);
putchar(ch1);
putchar('\n');
}
the output is:
please enter a number
2
the number multiple by 3 is 6.000
enter a word with four char
ffff
the chars in reverse order are
fff
3 chars printed to the console, if i move the code block of exercise 2 above 1:
int main(void)
{
//exercise 2
char ch1, ch2, ch3, ch4;
printf("enter a word with four char\n");
ch1 = getchar();
ch2 = getchar();
ch3 = getchar();
ch4 = getchar();
printf("the chars in reverse order are\n");
putchar(ch4);
putchar(ch3);
putchar(ch2);
putchar(ch1);
putchar('\n');
//exercise 1
float num2;
printf("please enter a number \n");
scanf_s("%f", &num2);
printf("the number multiple by 3 is %3.3f\n", num2 * 3);
}
the result as expected:
enter a word with four char
ffff
the chars in reverse order are
ffff
please enter a number
2
the number multiple by 3 is 6.000
i want to know why it's working when i change the order the code block and how can i solve it, thank you.
want to know why it's working when i change the order the code block and how can i solve it,
That's because scanf_s("%f", &num2); leaves newline character in the input buffer. So your first getchar(); will interpret that newline as ch1.
For this case, a silent preceding getchar would do:
getchar(); // will consume the remaining newline from stdin
ch1 = getchar();
ch2 = getchar();
ch3 = getchar();
ch4 = getchar();
There is a newline character when you input the first floating number, and it is input as a char by the call to getchar. Another way to fix this is to get entire line as a string using fgets, then parse it with whatever format you want:
char line[512];
printf("please enter a number \n");
fgets(line, sizeof line, stdin); // the newline is consumed here
sscanf(line, "%f", &num2);
ch1 = getchar(); // working as expected
This code works well for words with less than five letters: (but not for higher)
#include <stdio.h>
int main(void)
{
const int size = 5;
char str1[size], str2[size], str3[size];
printf("Type word1: ");
scanf("%s", str1);
printf("Type word2: ");
scanf(" %s", str2);
printf("Type word3: ");
scanf(" %s", str3);
printf("First chars: '%c', '%c' e '%c'.\n", str1[0], str2[0], str3[0]);
return 0;
}
The only way to run correctly would increase the 'size' variable? I wonder if it is possible to work properly with larger words without necessarily increasing the 'size' variable.
This will get you close
Just save 1st char
#include <stdio.h>
int main(void)
{
char str[3];
printf("Type word1: ");
scanf(" %c%*s", &str[0]);
printf("Type word2: ");
scanf(" %c%*s", &str[1]);
printf("Type word3: ");
scanf(" %c%*s", &str[2]);
printf("First chars: '%c', '%c' e '%c'.\n", str[0], str[1], str[2]);
return 0;
}
regarding this kind of line: 'scanf("%s", str1);'
1) the scanf format string needs to limit the number of characters input,
otherwise (in this case)
inputting a word longer than 4 char will result in a buffer overrun
2) always check the returned value from scanf
to assure the input/conversion operation was successful.
3) I would strongly suggest using fgets() and sscanf()
then
--the max number of characters is limited by a fgets() parameter,
--the string is null terminated,
--the newline is part of the string,
so will need to be overlayed with '\0'
4) in the user prompts,
I would use:
printf( "\nUsing %d or less characters, enter a string:", argv[1] );
where argv[1] is a command line parameter that indicates the max string length.
(be sure to allow for the nul terminator byte)
I am not too familiar with C syntax. I need to process some data based on user input. Although I processed the data successfully but I am stuck at user input section. I removed the unnecessary data processing section and made a simple example of how I am taking the user input. Can anyone tell me what's the problem with below code :
int i, number;
char *str;
str=(char*)malloc(1000*sizeof(char));
printf("Enter count : ");
scanf("%d", &number);
for(i=0; i<number; i++)
{
printf("\nEnter string: ");
scanf ("%[^\n]%*c", str);
printf("%s", str);
}
Output:
"Enter count : " appears fine, but whenever I provide some value and hit enter it's showing me only 'count' number of Enter string: without enabling user to enter the string.
For example -
Enter count : 2
Enter string:
Enter string:
But if I discard the count input section and provide any fixed value, like
for(i=0; i<5; i++)
it works fine
Thanks in advance
FYI, there is no issue in for(i=0; i<number; i++), problem is in scanning logic.
Actually, scanf ("%[^\n]%*c", str); is not right. you should use %s to read strings, not %c, which reads a single character, including the ENTER (newline).
Rather, i would suggest, use fgets() for inputs. It's a whole lot better in every way. Check the man page here.
Maybe you can use something like
//Dummy code
int i, number;
char *str;
printf("Enter count : ");
scanf("%d", &number);
str=malloc(number*sizeof(char)); //yes, casting not required
fgets(str, (number-1), stdin ); //"number" is used in different context
fputs(str, stdout);
EDIT:
Working code
#include <stdio.h>
#include <stdlib.h>
#define SIZ 1024
int main()
{
int i, number;
char * str = malloc(SIZ * sizeof (char));
printf("Enter the number :\n");
scanf("%d", &number);
getc(stdin); //to eat up the `\n` stored in stdin buffer
for (i = 0; i < number; i++)
{
printf("Enter the string %d :", (i+1));
fgets(str, SIZ-1, stdin);
printf("You have entered :");
fputs(str, stdout);
}
return 0;
}
scanf("%s",str); Use this instead of the code you are using to take string inputs in a character array.
There is a newline character \n after entering count value which is picked up by %c in your scanf()
Just use %s to scan strings as shown below.
scanf("%s",str);
If there are spaces in your input.
Then do
char c[50];
fgets(c,sizeof(c),stdin);
Check the below code:
#include <stdio.h>
#include<stdlib.h>
int main(){
int i, number;
char *str;
str=malloc(1000*sizeof(char));
printf("Enter count : ");
scanf("%d%*c", &number);
for(i=0; i<number; i++)
{
printf("\nEnter string: ");
fgets(str,1000,stdin);
printf("%s", str);
}
}