Here's a small program:
#include <stdio.h>
int main() {
char str[21], choice[21]; int size;
while(1){
printf("$ ");
fgets(str, 20, stdin);
printf("Entered string: %s", str);
if(str[0] == 'q') {
printf("You sure? (y/n) ");
scanf("%s", choice);
if(choice[0] == 'y' || choice[0] == 'Y')
break;
}
}
return 0;
}
It reads a string using fgets(). If the string starts with a q, it confirms if the user wants to quit, and exits if the user types y.
When I run it and type q, this happens:
$ q
Entered string: q
You sure? (y/n) n
$ Entered string:
$
Note the $ Entered string:. Clearly, fgets() got an empty character or something as input, even though I didn't type anything.
What's going on?
As described in other answer scanf call leaves the newline in the input buffer you can also use getchar() after scanf like this :
scanf("%20s", choice);// always remember( & good) to include field width
// in scanf while reading
Strings otherwise it will overwrite buffer in case of large strings `
getchar(); //this will eat up the newline
Besides , you should also use fgets like this :
fgets(str,sizeof str, stdin); //Its better
It because the scanf call reads a character, but leaves the newline in the buffer. So when you next time call fgets is finds that one newline character and reads it resulting in an empty line being read.
The solution is deceptively simple: Put a space after the format in the scanf call:
scanf("%s ", choice);
/* ^ */
/* | */
/* Note space */
This will cause scanf to read and discard all training whitespace, including newlines.
Use a 'char' of a specific size char choice [1]
OR
char c[1];
c = getchar();
if(c[0] == 'y' || c[1] == 'y'){
// DO SOMETHING
}
Related
I am trying to take in user input with spaces and store it in an array of characters.
After, I want to take in a single character value and store it as a char.
However, when I run my code, the prompt for the character gets ignored and a space is populated instead. How can I take in an array of chars and still be allowed to prompt for a single character after?
void main()
{
char userIn[30];
char findChar;
printf("Please enter a string: ");
scanf("%[^\n]s", userIn);
printf("Please enter a character to search for: ");
scanf("%c", &findChar);
//this was put here to see why my single char wasnt working in a function I had
printf("%c", findChar);
}
scanf("%c", &findChar); reads the next character pending in the input stream. This character will be the newline entered by the user that stopped the previous conversion, so findChar will be set to the value '\n', without waiting for any user input and printf will output this newline without any other visible effect.
Modify the call as scanf(" %c", &findChar) to ignore pending white space and get the next character from the user, or more reliably write a loop to read the read and ignore of the input line.
Note also that scanf("%[^\n]s", userIn); is incorrect:
scanf() may store bytes beyond the end of userIn if the user types more than 29 bytes of input.
the s after the ] is a bug, the conversion format for character classes is not a variation of the %s conversion.
Other problems:
void is not a proper type for the return value of the main() function.
the <stdio.h> header is required for this code.
Here is a modified version:
#include <stdio.h>
int main() {
char userIn[30];
int c;
char findChar;
int i, found;
printf("Please enter a string: ");
if (scanf("%29[^\n]", userIn) != 1) {
fprintf(stderr, "Input failure\n");
return 1;
}
/* read and ignore the rest of input line */
while ((c = getchar()) != EOF && c != '\n')
continue;
printf("Please enter a character to search for: ");
if (scanf("%c", &findChar) != 1) {
fprintf(stderr, "Input failure\n");
return 1;
}
printf("Searching for '%c'\n", findChar);
found = 0;
for (i = 0; userIn[i] != '\0'; i++) {
if (userIn[i] == findChar) {
found++;
printf("found '%c' at offset %d\n", c, i);
}
}
if (!found) {
printf("character '%c' not found\n", c);
}
return 0;
}
scanf("%[^\n]s", userIn); is a bit weird. The s is guaranteed not to match, since that character will always be \n. Also, you should use a width modifier to avoid a buffer overflow. Use scanf("%29[^\n]", userIn); That alone will not solve the problem, since the next scanf is going to consume the newline. There are a few options. You could consume the newline in the first scanf with:
scanf("%29[^\n]%*c", userIn);
or discard all whitespace in the next call with
scanf(" %c", &findChar);
The behavior will differ on lines of input that exceed 29 characters in length or when the user attempts to assign whitespace to findChar, so which solution you use will depend on how you want to handle those situations.
When I use the function fgets, the program skips the user input, effecting the rest of the program. An example program with this effect is:
#include <stdio.h>
int main() {
char firstDigit[2];
char secondDigit[2];
printf("Enter your first digit: ");
fgets(firstDigit, 1, stdin);
printf("\nEnter your second digit: ");
fgets(secondDigit, 1, stdin);
printf("\n\nYour first digit is %s and your second digit is %s.\n", firstDigit, secondDigit);
}
I then thought that maybe the problem was that fgets might be writing the newline, so I changed the code to account for that:
#include <stdio.h>
int main() {
char firstDigit[3];
char secondDigit[3];
printf("Enter your first digit: ");
fgets(firstDigit, 2, stdin);
printf("\nEnter your second digit: ");
fgets(secondDigit, 2, stdin);
printf("\n\nYour first digit is %c and your second digit is %c.\n", firstDigit[0], secondDigit[0]);
}
This time, the first input works properly, but the second input is skipped.
What am I doing incorrectly?
char firstDigit[2] and char secondDigit[2] are not large enough to hold a digit, a newline character, and a null-terminator:
char firstDigit[3];
char secondDigit[3];
Then, the calls to fgets() need to specify the size of the buffer arrays:
fgets(firstDigit, sizeof firstDigit, stdin);
/* ... */
fgets(secondDigit, sizeof secondDigit, stdin);
When instead fgets(firstDigit, 2, stdin); is used, fgets() stores at most two characters, including the \0 character, in firstDigit[]. This means that the \n character is still in the input stream, and this interferes with the second call to fgets().
In answer to OP's comment, How would you remove the unread characters from the input stream?, a good start would be to use more generous allocations for firstDigit[] and secondDigit[]. For example, char firstDigit[100], or even char firstDigit[1000] will be large enough that any expected input will be taken in by fgets(), leaving no characters behind in the input stream. To be more certain that the input stream is empty, a portable solution is to use the idiomatic loop:
int c;
while ((c = getchar()) != '\n' && c != EOF) {
continue;
}
Note here that it is necessary to check for EOF, since getchar() may return this value if the user signals end-of-file from the keyboard, or if stdin has been redirected, or in the unlikely event of an input error. But also note that this loop should only be used if there is at least a \n character still in the input stream. Before attempting to clear the input stream with this method, the input buffer should be checked for a newline; if it is present in the buffer, the input stream is empty and the loop should not be executed. In the code below, strchr() is used to check for the newline character. This function returns a null pointer if the sought-for character is not found in the input string.
#include <stdio.h>
#include <string.h> // for strchr()
int main(void)
{
char firstDigit[3]; // more generous allocations would also be good
char secondDigit[3]; // e.g., char firstDigit[1000];
printf("Enter your first digit: ");
fgets(firstDigit, sizeof firstDigit, stdin);
/* Clear input stream if not empty */
if (strchr(firstDigit, '\n') == NULL) {
int c;
while ((c = getchar()) != '\n' && c != EOF) {
continue;
}
}
putchar('\n');
printf("Enter your second digit: ");
fgets(secondDigit, sizeof secondDigit, stdin);
/* Clear input stream if not empty */
if (strchr(secondDigit, '\n') == NULL) {
int c;
while ((c = getchar()) != '\n' && c != EOF) {
continue;
}
}
puts("\n");
printf("Your first digit is %c and your second digit is %c.\n",
firstDigit[0], secondDigit[0]);
return 0;
}
It may be even better to use a single buffer[] to store lines of input, and then to store individual characters in chars. You could also write a function to clear the input stream, instead of rewriting the same loop each time it is needed:
#include <stdio.h>
#include <string.h> // for strchr()
void clear_stdin(void);
int main(void)
{
char buffer[1000];
char firstDigit;
char secondDigit;
printf("Enter your first digit: ");
fgets(buffer, sizeof buffer, stdin);
firstDigit = buffer[0];
/* Clear input stream if not empty */
if (strchr(buffer, '\n') == NULL) {
clear_stdin();
}
putchar('\n');
printf("Enter your second digit: ");
fgets(buffer, sizeof buffer, stdin);
secondDigit = buffer[0];
/* Clear input stream if not empty */
if (strchr(buffer, '\n') == NULL) {
clear_stdin();
}
puts("\n");
printf("Your first digit is %c and your second digit is %c.\n",
firstDigit, secondDigit);
return 0;
}
void clear_stdin(void)
{
int c;
while ((c = getchar()) != '\n' && c != EOF) {
continue;
}
}
For the first case, fgets(firstDigit, 1, stdin); cannot read anything from the input because the buffer has a size of only 1 byte, and fgets() must store a null terminator into the destination.
For the second case: fgets(firstDigit, 2, stdin); reads 1 byte from stdin, the digit that you typed, and cannot read the newline because the destination array is already full, allowing for the null terminator. The second fgets() reads the pending newline from the first entry and returns immediately for the same reason, not letting you type the second input.
You must allow fgets() to read at least 2 bytes by providing a buffer size of at least 3:
#include <stdio.h>
int main(void) {
char firstDigit[3];
char secondDigit[3];
printf("Enter your first digit: ");
if (!fgets(firstDigit, sizeof firstDigit, stdin))
return 1;
printf("\nEnter your second digit: ");
if (!fgets(secondDigit, sizeof secondDigit, stdin))
return 1;
printf("\n\nYour first digit is %s and your second digit is %s.\n",
firstDigit, secondDigit);
return 0;
}
Note that if you type more than a single character before the enter key, the program will still behave in an unexpected way.
This is a buffer problem. When you press enter, don't know why it is saved in the stdin buffer.
After you perform an fgets(...) you must type fflush(stdin); on all circumstances.
Something like this:
printf("Enter your first digit: ");
fgets(firstDigit, 1, stdin);
fflush(stdin);
Here first gets() is not working. if I add one more gets() function then from the two last one goes to work. how can I fix it?
CODE
#include<stdio.h>
#include<string.h>
int main(void)
{
short int choice;
char number[15];
do{
printf("\n\nAnswer: ");
scanf("%hd",&choice);
printf("\n");
if(choice==1)
{
printf("Enter the decimal number: ");
gets(number);
}
else
{
printf("Wrong input!.");
system("pause");
system("cls");
}
}while(choice!=1);
return 0;
}
Because the when the user pressed the enter key to give you the input for the scanf call, the enter key added a newline in the input buffer. And the gets call read that newline as an empty line.
One way to solve it is to use fgets to read the first input too, and use sscanf to parse it to a number:
...
printf("\n\nAnswer: ");
char input[64];
fgets(input, sizeof(input), stdin);
sscanf(input, "%hd", &choice);
printf("\n");
...
This make sure that the newline after the input is read and skipped.
Another way is to read one character at a time in a loop after the scanf call, until you have read the newline:
scanf("%hd", &choice);
int ch;
while ((ch = fgetc(stdin)) != EOF && ch != '\n')
{
// Empty
}
And a third way is to simply ask the scanf call to read and ignore white-space after the input:
scanf("%hd ", &choice);
// ^
// |
// Note space here
All of these methods have both pros and cons. You can try them all and use the one that works for you.
You need to skip the whitespace (i.e. the newline) following the number in the input buffer. This can be done by modifying the scanf to:
scanf("%hd ",&choice);
And use fgets(), since gets() is prone to buffer overflows.
well I have a buffer of I'm assuming 10 characters. I notice when I enter 9 characters though it will skip prompt EX.
Enter a p value:
123456789
Enter a q value:
Enter a k value:
But if I put in 8 or less it will accept it normally as the program is intended, even if the user inputs letters or special characters.
My code:
#include <stdio.h>
#include <math.h>
#include <limits.h>
#include <ctype.h>
int main()
{
char pbuffer[10], qbuffer[10], kbuffer[10];
int p=0, q=0, k=0;
int r, i, Q, c, count, sum;
char a[3];
a[0]='y';
while(a[0]=='y' || a[0]=='Y')
{
printf("Enter a p value: \n");
fgets(pbuffer, sizeof(pbuffer), stdin);
p = strtol(pbuffer, (char **)NULL, 10);
printf("Enter a q value: \n");
fgets(qbuffer, sizeof(qbuffer), stdin);
q = strtol(qbuffer, (char **)NULL, 10);
printf("Enter a k value: \n");
fgets(kbuffer, sizeof(kbuffer), stdin);
k = strtol(kbuffer, (char **)NULL, 10);
while(p<q+1)
{
Q=p;
sum=0;
count=0;
while(Q>0)
{
count++;
r = Q%10;
sum = sum + pow(r,k);
Q = Q/10;
}
if ( p == sum && i>1 && count==k )
{
printf("%d\n",p);
}
p++;
a[0]='z';
}
while((a[0]!='y') && (a[0]!='Y') && (a[0]!='n') && (a[0]!='N'))
{
printf("Would you like to run again? (y/n) ");
fgets(a, sizeof(a), stdin);
}
}
return 0;
}
fgets will read in as many characters as it can until it hits either a newline, EOF, or the size of the buffer. It also saves one extra character for a string-terminating \0. So, if you type in 123456789\n and have a 10-character buffer, fgets knows that it can only fit 9 characters in that buffer, so it reads in the first 9 and appends a NULL, giving you 123456789\0 in your buffer, and \n still in STDIN. Then, you call fgets a second time. It doesn't wait for input, because there is already a \n in STDIN, so it reads up to that \n, which happens to be only one character. So, your second buffer is now \n\0, and STDIN is now empty.
Either make your buffers large enough to store the strings that you're going to input, or flush STDIN after every fgets. Likely something like:
while((c = getchar()) != '\n' && c != EOF)
/* Ignore the character */ ;
Add this line after the fgets
scanf("\n");
Instead of reading into a char buffer first, you could use scanf(), e.g. scanf("%d", &p) could replace both fgets() and strtol().
Actually fgets retains the \n character when the size argument provided to it is less than the characters entered. In your case you provided value 10 as size to fgets.
so When you enter 9 characters, it fills the buffer with them and waits for an enter from you to stop reading. And when you press the enter it just puts the null character in the end of it and forward the enter to next prompt and hence skipping it.
check the examples in the answer to a question https://stackoverflow.com/a/11180652/1386897.
Flush the stdin after to the calls to fgets using
int c;
while((c = getchar()) != '\n' && c != EOF);
The reason why fgets dosen't wait for the user to enter data is because fgets knows that the buffer is full (9 chars and one space for \0) and appends a \0 in the end of the string and leaves the \n in the stdin which is taken by the next fgets
New bee in C. This is my code (It replaces a character from a string):
#include <stdio.h>
#include <string.h>
#include <conio.h>
void main()
{
char str[100], r, ra;
printf("enter string");
gets(str);
int length;
length= strlen(str);
printf("length of string is %d",length);
printf("\nenter the the character that will replace");
scanf("%c",&r);
printf("where to replace\n b...begning\ne....ending\np....position");
scanf("%c",&ra);
int pos;
switch(ra)
{
case 'b' : str[1]=r; break;
case 'e' : str[length-1] = r; break;
case 'p' : printf("enter position");
scanf("%d",pos);
if(pos<1 || pos>length-1)
printf("please enter a position between 1 and %d",length-1);
else
str[pos]= r;
break;
}
printf("\n after replacing string is %s", str);
getche();
}
The problem is that the IDE is not compiling this part of the program, I know that I am doing some thing wrong, but can't figure out what? Need help please.
scanf("%c",&ra);
int pos;
switch(ra)
{
case 'b' : str[1]=r; break;
case 'e' : str[length-1] = r; break;
case 'p' : printf("enter position");
scanf("%d",pos);
if(pos<1 || pos>length-1)
printf("please enter a position between 1 and %d",length-1);
else
str[pos]= r;
break;
}
use scanf(" %c",&ra) insted of "%c". Because reading with "%c" give you a garbage value in ra.And that value is new line.
When you enter value in a you press something like p and then Enter key. This Enter key still remains in stdin stream.
Next time when you read in ra then the Enter key in stdin stream is returned in ra.
So for removing that Enter key you need to read like " %c".
scanf(" %c", &ra); // space before %c
Unlike most conversions, %c does not skip whitespace before converting a character. After the user enters the number, a carriage return/new-line is left in the input buffer waiting to be read -- so that's what the %c reads.. SO POST
And for the same reason your switch case is not working, since ra does not have the expected value
the problem is that the ide is not compiling this part of the program
Well, that's a strong accusation. Rather than assume that the compiler does decide not to compile part of the code (on a whim), it's a safer bet that your program's execution flow just does not enter that part as you expected.
In particular, scanf does not behave as you think it does. It reads from stdin, which is a buffered input stream. "Buffered" means that it does not provide your program with input until a newline in read, i.e. until the user presses return. But the scanf family of functions doesn't look for new lines, it treats the new-line character as a normal character. In your case, scanning "%c" tries to read any character from the input. The subsequent "%c" then reads the new line, so &ra really is '\n' in your switch statement.
I usually find working with direct input from the user difficult in C, but if you must prompt the user interactively, I suggest that you read in a whole line of input first with fgets and then analyse that line with sscanf. That gets rid of the seemingly out-of-sync input and also allows you to scan a line several times, perhaps for alternative input syntaxes.
So, here's a version of your code that uses this technique:
#include <stdio.h>
#include <string.h>
int main()
{
char str[100], r, ra;
char line[20];
int length;
int pos;
printf("enter string");
fgets(str, 100, stdin); // note: str includes trailing newline
length = strlen(str);
printf("length of string is %d\n", length);
printf("enter the the character that will replace:\n");
fgets(line, 20, stdin);
sscanf(line, " %c ",&r);
printf("where to replace\n");
printf("b...begning\ne....ending\np....position\n");
fgets(line, 20, stdin);
sscanf(line, " %c ", &ra);
switch (ra)
{
case 'b': str[1] = r;
break;
case 'e': str[length - 1] = r;
break;
case 'p': printf("enter position");
fgets(line, 20, stdin);
sscanf(line, "%d ", &pos);
if(pos < 1 || pos > length-1)
printf("please enter a position between 1 and %d",
length-1);
else
str[pos]= r; break;
}
printf("after replacing string is %s", str);
return 0;
}
There are still problems with your code, mainly to do with zero-based array indexing in C. I leave it to you to sort those out. Also, prefer the safer fgets(buf, len, stdin) over gets(str), which does not prevent buffer overflow. And your query for a position should take a pointer to the address of pos, not just pos. And please make a habit of putting the new-line character last in your printf strings. It makes for cleaner reading and matches the way that the buffered output stream works.
The program doesn't compile, the most likely reason is that you are using a compiler that supports C89 only (I guess it's Visual Studio), or you are using C89 mode.
In this code:
scanf("%c",&ra);
int pos;
switch(ra)
{
the variable pos is defined in the middle of a block, which is supported only since C99. The solution is to move all definitions up to the beginning of a block:
int main()
{
char str[100], r, ra;
int pos;
printf("enter string");
Use fgets() to replace gets(), use int main to replace void main. And fix the problem with using scanf that is covered by the other answers.