Can I use getchar() to clear the buffer between scanf and fgets? - c

I have this function and it works well, but I was wondering if the usage of getchar is correct. Could I do something else instead? Thanks, guys.
void addRecord (struct record ** start, int account, char name[], char address[ ]);
{
printf("Enter your account number:\n");
scanf("%d", &account);
getchar();
printf("Enter your name:\n");
fgets(name, sizeof name, stdin);
printf("Enter your residential address:\n");
getaddress(address, sizeof address);
}

Assuming names cannot be empty and are not allowed to start with spaces (or tabs), you can read the name with another scanf while skipping over all intervening whitespace.
printf("Enter your account number:\n");
int account;
if(scanf("%d", &account) != 1) { /* error getting account */ }
printf("Enter your name:\n");
char name[80];
if(scanf(" %79[^\n]", name) != 1) { /* error getting name */ }
The breakdown of the " %79[^\n]" format specifier being used is:
the leading space skips over one or more whitespace characters (spaces, tabs, newlines), which consumes the newline left behind by the first scanf, any empty lines, and any leading spaces on the next line;
79 is a width specifier which limits scanf to reading at most 79 characters, leaving room for the terminating \0 nul character in the 80-character destination buffer;
[^\n] directs scanf to read a string up to (and not including) the \n newline character, which saves the name that the user entered into the name argument.

getchar() will only fetch a single character from stdin . To clear stdin buffer, you have use getchar() until you get EOF (end of file) or a new line. So, instead of calling getchar() once, call it a loop like this:
int c;
do {
c = getchar();
} while (c != EOF && c != '\n');
Note that the value of EOF is -1, so you must use int to handle it, as char is limited to 0 to 255 range.
Thanks to David Ranieri, the value of EOF can be (and usually) out of the range supported by char , so you should use int (or short ) to handle EOF.
You can put this code inside a function like clear_stdin if you need to reuse this code several times.

Related

Program seems to be ignoring one instance of 'gets()' and show an error message when the user hasn't interacted with the program [duplicate]

#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);

scanf not reading properly because of gets function

#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);

Program to replace a letter with another in C

I wrote a program to replace a letter in a string. Although it has no error, the output is not as expected. Please help me with it.
#define _CRT_SECURE_NO_DEPRECATE
#include<stdio.h>
#include<string.h>
void replace(char s,char d);
char a[100];
int main()
{
char b,r;
printf("enter the string\n:");
gets(a);
printf("enter the the letter to be replaced\n:");
scanf("%c", &b);
printf("enter the letter to be replaced with\n:");
scanf("%c", &r);
replace(b,r);
}
void replace(char s, char d)
{
int i,f=0;
for (i = 0; a[i] != '\0'; i++)
{
if (a[i] == s)
{
a[i] = d;
f = 1;
}
}
if (f == 0)
{
printf("letter not found");
}
}
Output
enter the string
:hello every one
enter the the letter to be replaced
:e
enter the letter to be replaced with
:letter not found
I wanted to replace e with o but I am not able to give the input for word to be replaced
UPDATE
Use this loop to get rid of the input buffer problem when using scanf
but I am not sure how to implement it on my program need help
void
clear(void)
{
while ( getchar() != '\n' )
;
}
The scanf() function skips over initial whitespace characters when you read in strings using the %s specifier, but it does not do this when your read chars with the %c specifier. The gets() function that you use (which you should never ever ever use ever) reads through the newline, and discards it. So your first call to scanf() has a clean input stream. When you call scanf() the first time, a value is read into the variable b, but the trailing newline is left behind in the input stream. Then, when you try to read the next value, scanf() picks up this newline, instead of the value that you want to enter.
One fix for this is to discard any unwanted characters from the input stream like this:
while (getchar() != '\n')
continue; // discard unwanted characters
You can also test for the EOF character in the conditional expression if you really want to be careful. One virtue of this approach is that, no matter how many characters the user enters at your second prompt, only the first is taken, and the remaining characters through the newline are discarded. Since there is nothing left in the input stream, scanf() has to wait for the user to enter something at your third prompt. You should place this code after each call to scanf() to make sure that the input stream is clear.
Now, gets() is a terrible and unsafe function begging for buffer overflows, because it doesn't check to see if there is enough memory allocated for the string it is getting. Instead, use fgets(). This function takes an argument that specifies the maximum number of characters to read, including the null-terminator. fgets() also reads the newline character into the string, so you have to dispose of that yourself if you don't want it. Here are the modifications you need to make:
int i = 0;
...
char b,r;
printf("enter the string\n:");
fgets(a, 100, stdin);
while(a[i] != '\n' && a[i] != '\0') // remove newline
++i;
a[i] = '\0';
printf("enter the the letter to be replaced\n:");
scanf("%c", &b);
while (getchar() != '\n')
continue; // discard unwanted characters
printf("enter the letter to be replaced with\n:");
scanf("%c", &r);
while (getchar() != '\n')
continue; // discard unwanted characters
replace(b,r);
printf("%s\n", a);
...
I added a final printf() to display the changed string.

Why is the first string ignored when reading with fgets from stdin? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Dev-C++ Input skipped
I am trying to read an array of character strings from stdin using fgets, but the first string I want to read is always ignored. What is causing this issue?
#include <stdio.h>
int main()
{
int i;
struct material
{
char name[30];
float price, kg;
};
unsigned m,nr;
printf("Lorry capacity=");
scanf("%u", &m);
printf("Number of materials=");
putchar('\n');
scanf("%u", &nr);
struct material list[nr];
for (i=0; i<nr; i++)
{
printf("Name=");
fgets(list[i].name, 30, stdin);
}
putchar('\n');
for (i=0; i<nr; i++)
{
printf("%s ", list[i].name);
}
return 0;
}
scanf("%u", &nr);
struct material list[nr];
for (i=0; i<nr; i++)
{
printf("Name=");
fgets(list[i].name, 30, stdin);
The scanf("%u", &nr); leaves the newline in the input buffer, so fgets finds an empty line without requiring further input to be entered.
It is generally a bad idea to mix (f)scanf and fgets, for that reason (among others).
As a quick fix, empty the input buffer before the first fgets,
int ch;
while((ch = getchar()) != EOF && ch != '\n');
if (ch == EOF) {
// oops
}
A more principled fix would be to read in the values before using fgets to get an entire line including the newline, and decode the numbers with strtoul or maybe sscanf.
This is a very common error. After reading a number with scanf, the newline you typed by pressing ENTER is left in the input buffer, so the first call to fgets reads the (very short) line that consists of only that newline.
I noticed that I can get rid of the newline left in the input buffer, by reading it with getchar().
Also, I had to use the following code to remove the trailing newline character from fgets() input:
char *pos;
if ((pos=strchr(Name, '\n')) != NULL)
*pos = '\0';
One of the things that's generally misunderstood is that when you ask for input from the user, you get freebies.
When the computer ask for the amount of materials:
Number of materials=
51
And you enter "51" you're really getting three characters: '5', '1', and '\n'. Everything comes with a newline character when you hit the enter key.
Different utilities that get input from the user handle this different. fgets() will read the newline and then it stores the input as "51\n". If you read it as a string using scanf()'s string format specificer "%s" you'll get only the digits "51" and the newline character is left on the stdin buffer.
So in your case you read a number via scanf:
scanf("%u", &nr);
Which leaves the newline, then when you try to do the next read:
fgets(list[i].name, 30, stdin);
fgets picks up that newline and stores it.
So there's a bunch of fixes possible here, one is to just use fgets() only, another is to consume the newlines with getchar() after each scanf, choice is up to you.
BTW: You can insert a newline in your printfs: printf("Number of materials=\n");
You can just do a fgets after each scanf, which will then eat the pending newline:
char dummy[10];
...
scanf (...);
fgets (dummy, 1, stdin);

Getting a line of user input in C help.

I've been all over the web and tried a bunch of different things, but they never seem to work. Every time I run the program it skips over the chance to enter something for the students name and goes straight to the department. Also, we are new to C and were really told to use printf and scanf, but when the user puts in a name like, joe shmo, it does some weird stuff.
fputs("Please enter the students name: ", stdout);
fflush(stdout);
fgets(studentArray[empty].name, sizeof studentArray[empty].name, stdin);
printf("\nPlease enter the students department: ");
scanf("%s", studentArray[empty].department);
printf("\nPlease enter the students rank: ");
scanf("%d", &studentArray[empty].rank);
EDIT: Weird stuff as in, if I enter two names, ie joe shmo, it will take joe as the name and automatically add shmo to the department. studentArray is an array of a struct I made...
typedef struct {
char name[MAX_NAME_LENGTH];
char department[MAX_DEPT_LENGTH];
int rank;
} student;
When the program reaches the fgets() I bet there is a pending '\n' in the input buffer from a previous scanf(). I suggest you get rid of that '\n' and any previous input.
For example, with
int getridofextrainput(void) {
int ch;
while (((ch = getchar()) != '\n') && (ch != EOF)) /* void */;
return ch;
}
Then use that function in your code where you think it's necessary (before fgets).
This is what happens when you mix fscanf and fgets.
When fscanf reads a number, it stops right at the end of this number, before the following newline character. When afterwards fgets reads a string, it stops at the next newline character, which unfortunately immediately follows.
If you used only fscanf to read all data, you would not get problems. This is not trivial, because some of your names contain spaces. It is possible to read a name containing a space using fscanf like this:
scanf("%[^\n]", studentArray[empty].department);
If you used only fgets to read all data, you would be OK either. Unfortunately, this is not trivial too: it requires a temporary buffer for reading numbers.
char temp[42];
fgets(temp, sizeof temp, stdin);
sscanf(temp, "%d", &studentArray[empty].rank);

Resources