Scanf skips functions - c

I am working on my assignment and this is the issue that I bumped into. In the assignment, it says that the input value for the middle initals should be this - "L. A.". However, once I run my program it prints some printf functions on the same line, skipping the scanf function. I have went through a lot of topics about that " %c" issue, but I still can not make my program run properly. Some of the variables are from .h file. The actual assignment is bigger, however it is pretty much repetative so I thought if I figure out how to fix this certain issue I will be able to finally finish my assignment.
int main(void){
// Declare variables here:
char ch;
struct Name FullName = { {'\0'} };
struct Address AddressInfo = { 0, '\0', 0, '\0', '\0' };
struct Numbers PhoneInfo = { {'\0'} };
// Display the title
printf("Contact Management System\n");
printf("-------------------------\n");
// Contact Name Input:
printf("Please enter the contact’s first name: ");
scanf("%s", &FullName.firstName);
printf("Do you want to enter a middle initial(s)? (y or n): ");
scanf(" %c", &ch);
if (ch == 'y') {
printf("Please enter the contact’s middle initial(s): ");
scanf(" %s", FullName.middleInitial);
}
printf("Please enter the contact’s last name: ");
scanf(" %s", &FullName.lastName);
// Contact Address Input:
printf("Please enter the contact’s street number: ");
scanf("%d", &AddressInfo.streetNumber);
OUTPUT (I have highlighted input values):
Contact Management System
-------------------------
Please enter the contactÆs first name: *Artem*
Do you want to enter a middle initial(s)? (y or n): *y*
Please enter the contactÆs middle initial(s): *L. A.*
Please enter the contactÆs last name: Please enter the contactÆs street number:

The %s format specifier reads a sequence of characters terminated by whitespace. When you enter L. A., only L. gets read into middleInitial because it stops reading at the space and A. is left in the input buffer. On the next scanf, it immediately reads those buffered characters so it doesn't stop to prompt for anything.
The simplest way to handle this is to leave out the space when inputting, i.e. L.A.. If you want to support whitespace, you'll want to get rid of scanf entirely and read everything a full line at a time using fgets. Note that fgets also reads in the trailing newline, so you'll need to strip that out.

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.

C : when asking for 2 inputs from a user the 2nd question will not prompt an input to be stored in a variable

If I try grade or fullname one at a time I will get the expected result
"Enter your Grade: "
"Your grade is x"
"Enter your full name:"
"Your full name is xxxx xxxx"
If I run below the print out is
Enter your Grade:2
Your grade is 2
Enter your full name: Your full name is
I can't figure out why I am not been prompted for a second input especially as I know it works when tried on its own */
int main()
{
char grade;
printf("Enter your Grade: ");
scanf("%c", &grade);
printf("Your grade is %c \n", grade);
char fullName[20];
printf("Enter your full name: ");
fgets(fullName, 20, stdin); /*2nd argument specify limits of inputs*, 3rd means standard input ie command console */
printf("Your full name is %s \n", fullName);
return 0;
}
scanf("%c"); buffer problem, %c will only eat one character, so or \n will stay in the buffer for the next one to read.
Try this
#include <stdio.h>
#include <stdlib.h>
int main()
{
char grade;
printf("Enter your Grade: ");
scanf("%c", &grade);
getchar(); // here
printf("Your grade is %c \n", grade);
char fullName[20];
printf("Enter your full name: ");
fgets(fullName, 20, stdin); /*2nd argument specify limits of inputs*, 3rd means standard input ie command console */
printf("Your full name is %s \n", fullName);
return 0;
}
use getchar(); to eat the extra character in the buffer.
Don't mix scanf() with fgets() - in this case, the newline present in the buffer, left untouched by scanf() will be fed to fget() and it won't "ask" for any new input.
Better to use fgets() in all the user-inputs.
The problem lies in this line scanf("%c", &grade); Whenever you use scanf() always keep in mind that the enter key will be stored in your buffer. Since enter key was in your buffer, it went right into fullName when fgets(fullName, 20, stdin); is executed. That's way you got your output:
Enter your Grade:2
Your grade is 2
Enter your full name: Your full name is
You can solve the problem by using getchar(); or getch(); right after scanf(); to capture the Enter key and ensures that fullName get the correct input. Another way to solve it is to use fflush(stdin);. They basically do the same thing, but fflush(stdin); clear Enter key from the buffer. Therefore, fflush(stdin); should be used after scanf(); to clear the unwanted Enter key left by scanf();
This is a long one and have a lot to take in, but I hope this information helps :)))

fgets printing two lines before input

So I am trying to write a program that will let me read a user input for data on an MP3 file using a doubly linked list data structure. I got most of the methods and functions to work, but when I am prompting the user to put in input it prints out two lines before the user can input for the first line. So for example
int main()
{
int user_input = 0;
while(!(user_input >= 4))
{
struct MP3_data_node* MP3_data;
MP3_data = (struct MP3_data_node*)malloc(sizeof(struct MP3_data_node));
printf("\nPlease select a number for one of the following instructions:\n");
printf("0: add to list\n1: delete from list\n2: print the list from beginning to end\n3: print the list from end to beginning\n4: exit\n");
scanf("%d", &user_input);
if(user_input == 0)
{
printf("Please provide the artist:");
fgets(MP3_data->artist,50,stdin);
printf("Please provide the album:");
fgets(MP3_data->artist,50,stdin);
printf("Please provide the song title:");
fgets(MP3_data->artist,50,stdin);
printf("Please provide the year the song was released: ");
scanf("%d", &MP3_data->yearReleased);
printf("Please provide the length of the song in seconds: ");
scanf("%d", &MP3_data->runTime);
addToList(MP3_data);
}
...
So it prints out "Please provide the artist:Please provide the album:" and then let's me put the input in, so my question is how do I make it so that it prints:
Please provide the artist: (user input)
Please provide the album: (user input)
etc.
You're doing the right thing (fgets) int the first few prompts, then you switch to scanf which is the source of your problem. Use fgets (and strtol) instead of scanf and you will be fine. (And, the first scanf which causes the problem described in your question.)
The problem is that scanf only reads the digit part of whatever you enter. That means if you type 12Enter, then the scanf reads the 1 and 2 but leaves the Enter in the input buffer for the next call to fgets or scanf. On the other hand, fgets reads everything you type including the Enter, avoiding this problem.

Stack around variable corrupted? C

I have 2 issues, but this is the more pressing one...
printf("Enter the term: "); scanf("%d", &input);
fprintf(inputf, "%d,", input);
printf("Enter the id: "); scanf("%d", &input);
fprintf(inputf, "%d,", input);
printf("Enter last name: "); scanf("%s", name);
fprintf(inputf, "%s,", name);
printf("Enter first name: "); fgets(name, 15, stdin);
fprintf(inputf, "%s,", name);
printf("Enter the subject: "); scanf("%s", subsec);
fprintf(inputf, "%s,", subsec);
printf("Enter the catalog number: "); scanf("%d", &input);
fprintf(inputf, "%d,", input);
//ISSUE HERE!
printf("Enter the section: "); scanf("%s", subsec);
fprintf(inputf, "%s\n", subsec);
Whenever I input all of this information and press enter on the last variable entry I get a window that says this "Run-Time Check Failure #2 - Stack around the variable 'subsec' was corrupted." I can continue and the program pretty much does what I want it to and works, but why is this happening?
My second part is when I get to entering the last name, and then want to enter the first name, it takes in the "\n" character when I press enter for the firstname string variable, obviously dont want that happening, but the both first and last name need to be capable of holding strings with whitespaces. How do I kill both birds with a single stone? I used fget to allow me to hold whitespace, but it cases my "\n" capture issue, but if I change it back to scanf, I cant hold whitespaces!
EDIT: This is subsec
char subsec[MAX_SUBSEC];
MAX_SUBSEC is set to three, I use it previously as you can see, but I figured the second scanf (the one for section, not subject) would write over the original use of inputting subsec, Im going to say I am wrong? And I am not allowed to do this, thus the issue...
Input for subject will be "CSE" and the input for section will be "R01" And yes this is all going to be put into a file.
If MAX_SUBSEC is 3 and you enter more than 2 characters for the subject or subsection, you'll overrun the subsec array on the stack and corrupt the stack frame (which may or may not cause problems. You should use
scanf("%2s", subsec); /* read up to two non-whitespace characters for subsec */
to ensure it doesn't try to read and store more than 2 characters (plus the trailing NUL) into subsec
You might also want to add a
scanf("%*[^\n]"); /* discard the rest of the input line */
after each scanf you have currently to discard the rest of the input line (in case some enters more than the single data item you want. You can combine the two with
scanf("%2s%*[^\n]", subsec); /* read 2 chars and discard the rest of the line */
if you want.
To enter strings of at most 15 chars (including NUL) with whitespace for first/last name, use:
scanf(" %14[^\n]", name); /* read up to 14 chars from the line */
That will discard any leading whitespace (including the newline from the previous line) and then read into name, but won't discard trailing spaces from the name if someone enters them (you might want to clean them up).
Check if inputf, that I presume that is a pointer to an opened file, do a correctly reading of the variable. In other words, check if the file is open correctly and this file contain all data that you want to read.

Question about input with scanf

When I execute the following program it get the user input for account details and then prints it correctly, but it cannot read the opt value (y/n). It automatically calls again. How can I get the program to exit when the user inputs "n"?
char opt;
do
{
//Getting user input
printf("\n Enter the Account Number:\n ");
scanf("%d",&gAccNo_i);
printf("\n Enter the Account Holder's Name:\n ");
scanf("%s",gCustName_c);
printf("\n Enter the Balance Amount:\n ");
scanf("%f",&gBlncAmt_f);
//Printing the input data.
printf("\n Account Number : %d",gAccNo_i);
printf("\n Customer Name : %s",gCustName_c);
printf("\n Balance Amount : %f",gBlncAmt_f);
printf("\n Do u want to wish to continue?(y/n)");
scanf("%c",&opt);
}while(opt!='n');
use opt=getch(); inplace of scanf("%c",&opt);
OR
scanf reads the whitespace that is left in the buffer by previous line. To skip whitespace, add a space to the "%c":
scanf(" %c", &opt);
scanf("%c",&opt);
Will actually read in a space/newline character. Which obviously will not be equal to 'n'.
You may like to take the input as a string and then verify if the first character is a 'n'.
char opts[5];
scanf("%s",opts);
while(opts[0] !='n');

Resources