This question already has answers here:
How to do scanf for single char in C [duplicate]
(11 answers)
compare a character on a char array by using strcmp
(2 answers)
Closed 5 years ago.
I want to compare some strings, but unfortunately I don't find any proper way to do it.
The idea behind is to ask for a keyboard input, read a variable, one symbol and if it is "y" or "n" ("yes" or "no" apparently) it executes certain activities. If the value of the char is neither of them, the question is asked again, until either of "y" or "n" is not pressed. I don't understand how to implement that.
#include <stdio.h>
#include <string.h>
int main()
{
char answer;
answer='a';
while (answer!='n'&&answer!='y')
{
printf("\nQuestion? (y/n) ");
scanf("%c",&answer);
}
return 0;
}
This actually works pretty nice, but if I don't press 'y' or 'n', the "while" starts again and due to a reason I cannot understand, the "printf" is executed one times more, than the length of the input. So if we run this code and we apply "asdf" as an input (four symbols) the "printf" in the "while" is displayed five (four plus one) times. The result is:
Question? (y/n)
Question? (y/n)
Question? (y/n)
Question? (y/n)
Question? (y/n)
Everything else works really nice in my code, but this... Obviously, this is not the best way to approach. I have also tried "strcmp()":
#include <stdio.h>
#include <string.h>
int main()
{
char answer='a';
while (strcmp(answer,'n')!=0&&strcmp(answer,'y')!=0)
{
printf("Question?");
scanf("%c",&answer);
}
return 0;
}
I don't know why, but the program doesn't even start. It is clear, that I haven't implemented "strcmp" properly and I don't understand what is wrong.
Any ideas, what should I do, so I can avoid multiple execution of the "printf" in the "while" or to make "strcmp" work the way I demand it to?
You probably want to read an entire line instead and interpret it as a whole. This way, you don't get the extra unwanted iterations when you enter a line with multiple characters, nor the extra one for the newline character. Look at the fgets() function.
scanf() is generally a poor choice beyond very simple input requirements, precisely because it is somewhat fuzzy and don't allow you to validate parts of the input before parsing it.
The %c format specifier to scanf will read any character, including whitespace characters such as a newline.
So if you enter in a letter and press the ENTER key, the scanf will read the letter and return, leaving the newline in the input buffer. On the next iteration of the loop, the scanf will immediately consume the newline left in the buffer and answer will contain the newline character. That's why you're seeing the prompt printed twice.
You need to add a leading space in your scanf format:
scanf(" %c",&answer);
The space will consume any whitespace characters that are entered so that answer will only contain non-whitespace.
The reason you're having problems with strcmp is because you're not actually comparing strings but individual characters. Each argument to strcmp is expected to be a pointer to a character array containing a string. Instead, you're passing in a single character. The value of that character is then interpreted as an address and dereferenced. This invokes undefined behavior.
In C, a string literal is represented this way: "n", but you have char literals, 'n' ... they're very different. Use a string literal for the argument, and it should work better.
Related
This question already has answers here:
fgets doesn't work after scanf [duplicate]
(7 answers)
Closed 1 year ago.
#include <stdio.h>
#include <string.h>
int main()
{
int num;
char answer[10];
char affirmation[10]="yes";
do
{
printf("Enter a number : \n");
scanf("%d",&num);
if (num % 97 == 0)
{
printf("No. is divisible by 97!\n");
}
else
{
printf("No. is not divisible by 97!\n");
}
printf("Once More ? [yes/no] \n");
fgets(answer,sizeof(answer),stdin);
}
while(strcmp(affirmation,answer) == 0);
return 0;
}
I expected from this program to check the divisibility of a provided number by 97 and then to ask if I again want it to check for another number if I input "yes". But it isn't prompting for my input .
If anybody can explain the reason behind this problem and suggest some ways to get through, it will be appreciated.The output is given below:
This output is for num = 194.
It is being executed but what it's reading is the newline character in the input stream that wasn't read when you did the scanf.
What your scanf does is to first skip any white space, then read an integer up to but not including the first non-digit character, which is probably the \n generated by the ENTER key.
Then, because fgets reads a line up to the next newline, you get an empty line.
In both the preceding two paragraphs, I'm assuming for simplicity ideal conditions such as ensuring it's a valid integer and that the line is not longer than the size you provided. Obviously, deviating from that could cause unruly behaviour.
It's generally not a good idea to mix the two input types unless you know in great detail what will be in the input stream. It's often better to just use line-based input and then sscanf that into more appropriate variables.
That way, you can be more sure about where your input stream is at any given point.
A quick fix in this particular case is simply to augment your scanf so that it skips to the start of the next line:
scanf("%d",&num);
while (getchar() != '\n') {}
The other problem you'll have after that is the fact that your fgets input will actually be "yes\n" rather than "yes", so that string comparison won't work.
If you're after a fairly robust line input function that takes care of that (and many other things), see here.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I'm really struggling with isdigit();
I need to test for simple numbers, the relevant part of my code looks like this:
printf("Enter a number\n");
scanf("%f", &a);
if (isdigit(a))
printf("That's a number");
doesn't matter what I input, it won't acknowledge it as a number. I saw somewhere an answer to a similar problem, where they said you can only pass the ASCII code to isdigit if you want accurate evaluation (so only 48-57 will work). Instead '2' for example will be interpreted as the 'start of text' I couldn't find any answer on how to get around that though. I don't remember having that problem in cpp.
Any suggestions?
The isdigit function expects a character code and returns true if the character is one of '0' - '9'.
What you are doing by using the %f format specifier is reading in some text which gets interpreted as a floating point and is then parsed to result in the actual value encoded in the system floating point format (probably IEEE754).
You don't want scanf to interpret the values for you. You want to read the text directly. So declare a char array big enough to read your input and use the %s format specifier. This will give you a string. Then inspect each character in the string with isdigit.
isdigit() checks if a single character is a digit or not. You're passing something that's not a single character.
It would be helpful to have a complete code snippet so we could e.g. know the data type of a. Since you've passed %f to scanf(), presumably it's a float?
If so, the scanf() will return 1 if it is able to parse a float out of whatever input it is given. You can use the return value to determine if the input was valid and not have to even use isdigit().
If you want to use isdigit() for some reason, then you should read the input as a string (scanf("%s", ...something that is a char *...)) and then iterate over each character, passing it to isdigit()
The definition for isdigit() is
int isdigit( int ch );
Checks if the given character is one of the 10 decimal digits: 0123456789.
The behavior is undefined if the value of ch is not representable as unsigned char and is not equal to EOF.
Returns:
Non-zero value if the character is a numeric character, zero otherwise.
Since you are passing the input to a float variable it will not work.
#include <stdio.h>
#include <ctype.h>
int main() {
unsigned char c;
printf(">");
scanf(" %c", &c);
if(isdigit(c)){
printf("Is a digit\n");
}
}
This question already has answers here:
What is the effect of trailing white space in a scanf() format string?
(4 answers)
Closed 3 years ago.
in my code according to for loop Condtion it is clear that it must iterate only 5 times from 0 to 4.
But it is taking 6 input from the user.
Why it is happening.
Please clear my doubt.
#include <stdio.h>
#include <conio.h>
void main() {
int i, num;
clrscr();
printf("Enter 5 elements in the array\n");
for (i = 0; i < 5; i++) {
scanf("%d\n", &num);
}
getch();
}
According to your code i think you are mixing up the inputs you request with the system pause created by the getch() function you call at the end. The getch() initiates a pause which you can easily mix up with your input prompts since during this pause, user input is possible though not considered.
I propose you introduce an instruction in the loop which indicates the line or some information so you can make the distinction.
You have two problems regarding input.
The first is the getch call at the end of the program. But the other problem is the newline in the scanf format string
scanf("%d\n",&num);
When the scanf function sees a space in the format string (newline is considered a space in this context) then it will read and discard all spaces in the input. The problem with a trailing space in a format string is that to know when the spaces in the input ends, there must be some non space input as well.
So (almost) never have a trailing space (space, newline, carriage-return, tab) in a scanf format string.
The reason this code wait 5 times user input is the getch() at the end.
It waits for the input of one character and probably used to prevent the shell window from directly closing after the program finshed.
This question already has answers here:
How do you allow spaces to be entered using scanf?
(11 answers)
Closed 5 years ago.
For Example if I
Input: 'stephen 8108' it outputs
'stephen'
Instead of outputing 'stephen 8108'.
Can someone help me out!
I want the full string to appear in the output.
It reads the string only till the first white space.
Even if i remove the for loop condition it doesn't seem to work it still reads only till the first white space.
#include<fcntl.h>
#include<stdio.h>
#include <unistd.h>
void main()
{
char a[100];
int i,f2,f3,f4;
f2 = creat("a.txt",0666);
f3 = open("a.txt",O_RDWR);
printf("Enter your name & Roll-no\n");
scanf("%s",a);
for(i=0;a[i] != '\0';i++);
write(f3,a,i);
close(f3);
}
This is intended sprintf functionality.
Cite: http://www.cplusplus.com/reference/cstdio/scanf/
Any number of non-whitespace characters, stopping at the first whitespace character found.
One option is to use the negated character matching (quoted from link above):
[^characters] Negated scanset
Any number of characters none of them specified as characters between the brackets.
For example, to match everything excluding a newline:
scanf("%[^\n]", a);
(Full working example below - although please don't take this as necessarily a full and perfect example of reading user input in C++...)
#include<fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{
char a[100];
int fp;
fp = open("a.txt", O_CREAT|O_WRONLY|O_TRUNC);
printf("Enter your name & Roll-no\n");
scanf("%[^\n]", a);
write(fp, a, strlen(a));
close(fp);
}
However: I would really encourage you to read the extensive warnings about buffer overflows: https://stackoverflow.com/a/1248017/817132
In short, make sure you don't allow the user to write beyond your (currently 100 character long) memory allocation.
At the current state of your code, the for loop doens't have a body { ... } , so the write and the close operations would be executed only one time.
Also if you want scanf to read a string with spaces you can use %[0-9a-zA-Z ] instead of %s
Regarding the input, there are at least two problems:
The s conversion of scanf() parses until it finds whitespace, it's documented that way.
Without a field width, scanf() will continue parsing when it doesn't find whitespace, overflowing your buffer -> undefined behavior.
The quick fix is to replace scanf("%s",a); with scanf("%99[^\n]",a);. But scanf() is definitely not the best tool to read input, it is for parsing. You seem to just want to read a whole line of input and there is already a function for that: fgets(). Use it in your example like this (include string.h if you want to use this method of stripping the newline character):
fgets(a, 100, stdin);
a[strcspn(a, "\n")] = 0; // remove the newline character if it was read by fgets
This question already has answers here:
Simple C scanf does not work? [duplicate]
(5 answers)
Closed 7 years ago.
I need to get words from user which contains space as I expressed at title with struct statement.
For example :
#include <stdio.h>
struct knowledge
{
char name[30];
}person;
int main()
{
scanf("%s",person.name);
printf("\n\n%s",person.name);
}
When I run this program and enter a sentence like "sentence" there is no problem. It show me again "sentence".
However, when I enter "sentence aaa" it shows me just first word ("sentence"). What is the matter here? Why it doesn't show me all ("sentence aaa") I entered?
Instead of scanf() use
fgets(person.name,sizeof(person.name),stdin);
It is always a bad idea to use scanf() to read strings. The best option is to use fgets() using which you avoid buffer overflows.
PS: fgets() comes with a newline character
%s format specifier stops scanning on encountering either whitespace or end of stream. hence, you cannot input a "sentence" with space using scanf() and %s.
To scan a "whole line" with space, you need to use fgets(), instead.