This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
Closed 4 years ago.
I wrote this C program to enter names and ages of 3 people. But the output wasn't my expectation. It was able to enter name and age for the first person, but it wasn't able for second and third persons. Please help.
#include <stdio.h>
#include <string.h>
int main()
{
int i, age;
char name[20];
for(i=0; i<3; i++)
{
printf("\nEnter name: ");
gets(name);
printf("Enter age: ");
scanf(" %d", &age);
puts(name);
printf(" %d", age);
}
return 0;
}
In short: Your 2nd puts is processing the '\n' from your scanf.
Fix by adding getchar(); after scanf
Explanation:
1st iteration:
printf("\nEnter name: ");
gets(name); // line is read from input
printf("Enter age: ");
scanf(" %d", &age); // a number is read from input, and the newline char ('\n') remains in buffer
puts(name);
printf(" %d", age);
2nd iteration:
printf("\nEnter name: ");
gets(name); // previously buffered newline char is read, thus "skipping" user input
printf("Enter age: ");
scanf(" %d", &age);
puts(name);
printf(" %d", age);
Same goes for 3rd iteration, and this is why you lose user input
The best way to store information of more than one person is to use struct, like
struct person {
int age;
char name[20];
};
and make array of struct, like
struct person people[3];
than use loop with accessing people[i].age and people[i].name, e.g.:
#include <stdio.h>
#include <string.h>
struct person {
int age;
char name[20];
};
#define ARR_SIZE 3
int main(int argc, char* argv[])
{
struct person people[ARR_SIZE];
int i;
char *lastpos;
for(i = 0; i < ARR_SIZE; i++)
{
printf("\nEnter name: ");
scanf(" %s", people[i].name);
if ((lastpos=strchr(people[i].name, '\n')) != NULL) *lastpos = '\0'; // remove newline from the end
printf("Enter age: ");
scanf(" %d", &people[i].age);
}
printf("This is the people you entered:\n");
for(i = 0; i < ARR_SIZE; i++)
{
printf("%d : %s : %d\n", i+1, people[i].name, people[i].age);
}
return 0;
}
UPDATE:
As you see I use scanf(" %s", people[i].name); instead of gets(people[i].name); to read name from stdin. Try both option for the following cases:
enter short name (e.g. John) and correct age (e.g. 15)
enter two word name (e.g. John Smith) and correct age (e.g. 17)
enter short name and uncorrect age (e.g. five)
Then read articles about value returned by scanf and cleaning input buffer
Related
I'm new to C, and currently trying to practice on some simple codes, and I'm currently stuck with that next one.
After entering the first customer data, and repeat the code... View_customer function fails to show the saved data, and when I try to go to enter a second account data, it fails at the second entry.
#include<stdio.h>
#include<stdlib.h>
typedef struct cust{
char name[60];
int acc_no,age;
char address[60];
char citizenship[15];
double phone;
char acc_type[10];
} cust;
void new_account(int num);
void view_account(int num);
int main()
{
cust customers[10];
char answer;
int n;
int cutomer_number=1;
int cutomer_num2;
printf("Welcome To The program X: \n");
do{
printf("\n How can we serve you today? \n 1.Create a new account \n 2.Print an existing Account info \n ");
scanf("%d",&n);
if (n==1)
{
new_account(cutomer_number);
cutomer_number++;
}else {
printf("Please enter your Cust number: ");
scanf(" %d",&cutomer_num2);
view_account(cutomer_num2);
};
printf("\n Press Y to continue. Press any Key To Exit: ");
scanf(" %c",&answer);
}while (answer == 'Y' || answer == 'y');
return 0;
}
void view_account(int n)
{
cust customers[n];
printf("Your name is %s \n ", customers[n].name);
printf("Your age is %d \n", customers[n].age);
printf("Your address is %s \n", customers[n].address);
printf("Your citizenship is %s \n", customers[n].citizenship);
printf("Your phone number is %f \n", customers[n].phone);
printf("Your account type is %s \n", customers[n].acc_type);
};
void new_account(int n)
{
cust customers[n];
customers[n].acc_no = n;
printf("You are the customer number %d \n", customers[n].acc_no);
printf("Please, Enter your name: ");
scanf("%s", &customers[n].name);
printf("Please, Enter your age:");
scanf(" %d", &customers[n].age);
printf("Please, Enter your address: ");
scanf(" %s", &customers[n].address);
printf("Please, Enter your citizenship: ");
scanf(" %s", &customers[n].citizenship);
printf("Please, Enter your phone number: ");
scanf(" %f", &customers[n].phone);
printf("Please, Enter your account type: ");
scanf(" %s", &customers[n].acc_type);
}
>
Each of your three functions declares its own customers array variable, so each of them has their own memory for the customer data. Moreover, the array of new_account goes out of scope at the end of the function, so you can no longer safely access the data. Because of how C compilers typically work, the customer data is not immediately erased from memory, so your view_account function might still be able to read it, but that is what is called "undefined behavior". Which means it might work, or it might not.
Try to pass down the array from the main function to the other two functions in parameters. Or, to make things simpler at first, you could also turn the local customers variable of main into a global variable.
cust customers[10];
int main(int argc, char *argv[])
{
char answer;
int n;
int cutomer_number=1;
int cutomer_num2;
printf("Welcome To The program X: \n");
...
}
void view_account(int n) {
printf("Your name is %s \n ", customers[n].name);
...
}
void new_acccount(int n)
{
customers[n].acc_no = n;
...
}
Note that there are further issues in your code, like not checking the return value of scanf or overflowing the char arrays of the struct if you enter too many characters (missing bounds and length checking), or being able to enter more than 10 customers and accessing out of bounds of the customers array, or not using customers[0] (because your customer_number starts at 1, but array indices are 0-based). But I will not go into further details here to keep the answer focused.
This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
Closed 3 years ago.
I am programming a simulation, and when the user chooses to create a new tag, the user is supposed to enter a tag ID, the tag's owner, and the object the tag represents. What the program is doing is just skipping over command that scans for the owner, and I'm not quite sure why. My codes are below (the functions are in iotlib.cpp):
iotlib.cpp
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define MAX 20
struct tagInfo
{
char owner[MAX];
char object[MAX];
int id;
};
struct tre //TRE = Tag Read Event
{
int id;
char node[MAX];
int dx;
};
void initTag(struct tagInfo tag[], int numTags)
{
for(int i=0; i<numTags; i++)
{
printf("Enter the tag ID number: ");
scanf("%i", &tag[i].id);
printf("Enter owner of tag: ");
scanf("%c", &tag[i].owner);
printf("Enter the object the tag is attached to: ");
scanf("%c", &tag[i].object);
}
}
void generateTRE(struct tre event[], int numEvents)
{
for(int i=0; i<numEvents; i++)
{
printf("Enter tag ID: ");
scanf("%i", &event[i].id);
printf("Enter node: ");
scanf("%c", &event[i].node);
printf("Enter distance from node as an integer number of feet: ");
scanf("%c", &event[i].dx);
}
}
void triangulationSimulate(struct tre event1, struct tre event2, int numEvents)
{
if(numEvents>1 && event1.id==event2.id)
{
printf("Node %c", event1.node);
for(int i=0; i<event1.dx; i++)
{
printf(" ");
}
printf("Tag %i", event1.id);
for(int i=0; i<event2.dx; i++)
{
printf(" ");
}
printf("Node %c", event2.node);
}
}
void getTagInfo(struct tagInfo tag)
{
printf("The tag with ID %i represents a/an %c belonging to %c", tag.id, tag.object, tag.owner);
}
main.cpp
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "iotlib.cpp"
void execute();
int main(void)
{
execute();
return 0;
}
void execute()
{
struct tagInfo tags[5];
struct tre events[5];
int choice, numTags, numEvents;
printf("!Simulation supports a maximum of 5 tags and 5 nodes!\n\n");
printf("Choose a function by entering it's number:\n1. Create tags\n2. Generate Tag Read Events\n3. Triangulate tag\n4. Recall tag metadata\n\n");
scanf("%i", &choice);
if(choice==1)
{
printf("Enter the number of tags to initialize (max of 5): ");
scanf("%i", &numTags);
if(numTags<1 || numTags>5)
{
printf("Invalid datum.\n");
}
else
{
initTag(tags, numTags);
}
}
else if(choice==2)
{
printf("Enter the number of TRE's to be generated (max of 5: ");
scanf("%i", &numEvents);
if(numEvents<1 || numEvents>5)
{
printf("Invalid datum.\n");
}
else
{
generateTRE(events, numEvents);
}
}
else if(choice==3)
{
int eventX, eventY;
printf("Enter two existing TRE numbers to use, separated by a space: ");
scanf("%i %i", &eventX, &eventY);
triangulationSimulate(events[eventX], events[eventY], numEvents);
}
else if(choice==4)
{
int tagNum;
printf("Enter a tag number: ");
scanf("%i", &tagNum);
getTagInfo(tags[tagNum-1]);
}
else
{
printf("Invalid selection.\n");
}
execute();
}
Point 1 [Programmatic error]
The problem here is the usage with %c format specifier. It counts the previously entered \n, stored by pressing the ENTER key after previous input. What you want is
scanf(" %c", &tag[i].owner);
^
|
note the space
to skip any leading whitespace like character (including \n) before the actual input.
Point 2 [Logical Error]
As per your code here, to scan a string input, you need to use %s format specifier.
So, finally, your code should look like
scanf("%s", tag[i].owner); // if tag[i].owner is char array
or
scanf(" %c", &tag[i].owner); // if tag[i].owner is a char, just in case
%c is the specifier for a character, you're trying to input a string, not a character. See scanf documentation. What you want to use is the %s specifier for a string.
I am writing a simple program in C using structs. The user needs to enter some values for the struct - a name and age. After I enter the data for the first time, the second time the program just skips one of the fields and only wants me to enter the second field of the data. I can't figure out what's wrong.
struct Person {
char name[20];
int age;
};
void main(){
struct Person pArray[10];
for (int i = 0; i < 10; i++) {
printf("Please enter a name and age:\n");
printf("Name: ");
fgets(pArray[i].name, 20, stdin);
printf("Age: ");
scanf("%d", &pArray[i].age);
}
}
As you can see, after entering Jonathan and 45 for the first time, the second time it skipped the name and wants only the age. Why is this happening?
I try not to mix formatted and unformatted input (e.g., fgets and scanf). Here is your program using only fgets for input:
#include <stdio.h>
struct Person {
char name[20];
int age;
};
int main(){
struct Person pArray[10];
char numberBuffer[20];
for (int i = 0; i < 10; i++) {
printf("Please enter a name and age:\n");
printf("Name: ");
fgets(pArray[i].name, 20, stdin);
printf("Age: ");
fgets(numberBuffer, 20, stdin);
sscanf(numberBuffer, "%d", &pArray[i].age);
}
}
This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
Closed 3 years ago.
I am programming a simulation, and when the user chooses to create a new tag, the user is supposed to enter a tag ID, the tag's owner, and the object the tag represents. What the program is doing is just skipping over command that scans for the owner, and I'm not quite sure why. My codes are below (the functions are in iotlib.cpp):
iotlib.cpp
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define MAX 20
struct tagInfo
{
char owner[MAX];
char object[MAX];
int id;
};
struct tre //TRE = Tag Read Event
{
int id;
char node[MAX];
int dx;
};
void initTag(struct tagInfo tag[], int numTags)
{
for(int i=0; i<numTags; i++)
{
printf("Enter the tag ID number: ");
scanf("%i", &tag[i].id);
printf("Enter owner of tag: ");
scanf("%c", &tag[i].owner);
printf("Enter the object the tag is attached to: ");
scanf("%c", &tag[i].object);
}
}
void generateTRE(struct tre event[], int numEvents)
{
for(int i=0; i<numEvents; i++)
{
printf("Enter tag ID: ");
scanf("%i", &event[i].id);
printf("Enter node: ");
scanf("%c", &event[i].node);
printf("Enter distance from node as an integer number of feet: ");
scanf("%c", &event[i].dx);
}
}
void triangulationSimulate(struct tre event1, struct tre event2, int numEvents)
{
if(numEvents>1 && event1.id==event2.id)
{
printf("Node %c", event1.node);
for(int i=0; i<event1.dx; i++)
{
printf(" ");
}
printf("Tag %i", event1.id);
for(int i=0; i<event2.dx; i++)
{
printf(" ");
}
printf("Node %c", event2.node);
}
}
void getTagInfo(struct tagInfo tag)
{
printf("The tag with ID %i represents a/an %c belonging to %c", tag.id, tag.object, tag.owner);
}
main.cpp
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "iotlib.cpp"
void execute();
int main(void)
{
execute();
return 0;
}
void execute()
{
struct tagInfo tags[5];
struct tre events[5];
int choice, numTags, numEvents;
printf("!Simulation supports a maximum of 5 tags and 5 nodes!\n\n");
printf("Choose a function by entering it's number:\n1. Create tags\n2. Generate Tag Read Events\n3. Triangulate tag\n4. Recall tag metadata\n\n");
scanf("%i", &choice);
if(choice==1)
{
printf("Enter the number of tags to initialize (max of 5): ");
scanf("%i", &numTags);
if(numTags<1 || numTags>5)
{
printf("Invalid datum.\n");
}
else
{
initTag(tags, numTags);
}
}
else if(choice==2)
{
printf("Enter the number of TRE's to be generated (max of 5: ");
scanf("%i", &numEvents);
if(numEvents<1 || numEvents>5)
{
printf("Invalid datum.\n");
}
else
{
generateTRE(events, numEvents);
}
}
else if(choice==3)
{
int eventX, eventY;
printf("Enter two existing TRE numbers to use, separated by a space: ");
scanf("%i %i", &eventX, &eventY);
triangulationSimulate(events[eventX], events[eventY], numEvents);
}
else if(choice==4)
{
int tagNum;
printf("Enter a tag number: ");
scanf("%i", &tagNum);
getTagInfo(tags[tagNum-1]);
}
else
{
printf("Invalid selection.\n");
}
execute();
}
Point 1 [Programmatic error]
The problem here is the usage with %c format specifier. It counts the previously entered \n, stored by pressing the ENTER key after previous input. What you want is
scanf(" %c", &tag[i].owner);
^
|
note the space
to skip any leading whitespace like character (including \n) before the actual input.
Point 2 [Logical Error]
As per your code here, to scan a string input, you need to use %s format specifier.
So, finally, your code should look like
scanf("%s", tag[i].owner); // if tag[i].owner is char array
or
scanf(" %c", &tag[i].owner); // if tag[i].owner is a char, just in case
%c is the specifier for a character, you're trying to input a string, not a character. See scanf documentation. What you want to use is the %s specifier for a string.
This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
Closed 3 years ago.
I am programming a simulation, and when the user chooses to create a new tag, the user is supposed to enter a tag ID, the tag's owner, and the object the tag represents. What the program is doing is just skipping over command that scans for the owner, and I'm not quite sure why. My codes are below (the functions are in iotlib.cpp):
iotlib.cpp
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define MAX 20
struct tagInfo
{
char owner[MAX];
char object[MAX];
int id;
};
struct tre //TRE = Tag Read Event
{
int id;
char node[MAX];
int dx;
};
void initTag(struct tagInfo tag[], int numTags)
{
for(int i=0; i<numTags; i++)
{
printf("Enter the tag ID number: ");
scanf("%i", &tag[i].id);
printf("Enter owner of tag: ");
scanf("%c", &tag[i].owner);
printf("Enter the object the tag is attached to: ");
scanf("%c", &tag[i].object);
}
}
void generateTRE(struct tre event[], int numEvents)
{
for(int i=0; i<numEvents; i++)
{
printf("Enter tag ID: ");
scanf("%i", &event[i].id);
printf("Enter node: ");
scanf("%c", &event[i].node);
printf("Enter distance from node as an integer number of feet: ");
scanf("%c", &event[i].dx);
}
}
void triangulationSimulate(struct tre event1, struct tre event2, int numEvents)
{
if(numEvents>1 && event1.id==event2.id)
{
printf("Node %c", event1.node);
for(int i=0; i<event1.dx; i++)
{
printf(" ");
}
printf("Tag %i", event1.id);
for(int i=0; i<event2.dx; i++)
{
printf(" ");
}
printf("Node %c", event2.node);
}
}
void getTagInfo(struct tagInfo tag)
{
printf("The tag with ID %i represents a/an %c belonging to %c", tag.id, tag.object, tag.owner);
}
main.cpp
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "iotlib.cpp"
void execute();
int main(void)
{
execute();
return 0;
}
void execute()
{
struct tagInfo tags[5];
struct tre events[5];
int choice, numTags, numEvents;
printf("!Simulation supports a maximum of 5 tags and 5 nodes!\n\n");
printf("Choose a function by entering it's number:\n1. Create tags\n2. Generate Tag Read Events\n3. Triangulate tag\n4. Recall tag metadata\n\n");
scanf("%i", &choice);
if(choice==1)
{
printf("Enter the number of tags to initialize (max of 5): ");
scanf("%i", &numTags);
if(numTags<1 || numTags>5)
{
printf("Invalid datum.\n");
}
else
{
initTag(tags, numTags);
}
}
else if(choice==2)
{
printf("Enter the number of TRE's to be generated (max of 5: ");
scanf("%i", &numEvents);
if(numEvents<1 || numEvents>5)
{
printf("Invalid datum.\n");
}
else
{
generateTRE(events, numEvents);
}
}
else if(choice==3)
{
int eventX, eventY;
printf("Enter two existing TRE numbers to use, separated by a space: ");
scanf("%i %i", &eventX, &eventY);
triangulationSimulate(events[eventX], events[eventY], numEvents);
}
else if(choice==4)
{
int tagNum;
printf("Enter a tag number: ");
scanf("%i", &tagNum);
getTagInfo(tags[tagNum-1]);
}
else
{
printf("Invalid selection.\n");
}
execute();
}
Point 1 [Programmatic error]
The problem here is the usage with %c format specifier. It counts the previously entered \n, stored by pressing the ENTER key after previous input. What you want is
scanf(" %c", &tag[i].owner);
^
|
note the space
to skip any leading whitespace like character (including \n) before the actual input.
Point 2 [Logical Error]
As per your code here, to scan a string input, you need to use %s format specifier.
So, finally, your code should look like
scanf("%s", tag[i].owner); // if tag[i].owner is char array
or
scanf(" %c", &tag[i].owner); // if tag[i].owner is a char, just in case
%c is the specifier for a character, you're trying to input a string, not a character. See scanf documentation. What you want to use is the %s specifier for a string.