How to check if user input a string value? - c

So here's my code:
main()
{
char *iochar;
printf(" Enter a standard line: ");
scanf ( "%s", &iochar);
if (iochar != NULL)
{
printf(" Here's what you entered: %s ", &iochar);
}
else
{
printf(" Oops! Looks like you forgot to enter something! ");
}
}
My problem is that I can scan the user entry and store it and if something exists it puts out the correct message. But if I just hit return to test for no input (null, empty, etc) the program neither quits nor outputs my error message. It just hangs until I input something.
I've been programming in Java for the last two semesters so C is totally lost on me right now. So any help would be much appreciated.

scanf ( "%s", &iochar); is not useful for detecting an empty line.
"%s" first directs scanf() to read and discard all leading white-space, including '\n' before proceeding to read non-white-space characters. So code has lost the '\n'.
Instead use fgets()
// Enough room for 80 characters + \n + \0
#define LINE_SIZE (80 + 1 + 1)
char buf[LINE_SIZE];
if (fgets(buf, sizeof buf, stdin) == NULL) {
puts("end-of-file or input error detected");
} else if (buf[0] == '\n') {
puts("Empty line entered");
} else {
printf("Input line: <%s>\n", buf);
}
Input
Hello World (and <Enter>)
Output (Note the \n read in is still retained)
Input line: <Hello World
>
To be clear: In C, a string is a sequence of characters up to and including a terminating null character '\0'. Users do not enter strings. User input is usually a line of text up to and including a terminating line feed '\n'. fgets() reads a line of input and then appends a null character to the resultant buffer is a string`.

Here's my advice: Don't use scanf. Its rules are confusing, and it's very difficult to get the behaviour you want.
Instead, I recommend you use getch to manually read each character into a buffer until the user enters a newline character '\n'. Then you can zero terminate the buffer with a 0, and then use the buffer as a normal string. For it to be empty, just check the length of the string with strlen(x).

Related

Search whitespace in string inC

problem is when I try to enter a string with space compiler render that as separate 2 strings. But requirement is whenever there is a space in string don't treat it as 2 strings,but rather a single string. The program should print yes only if my four inputs are MAHIRL,CHITRA,DEVI and C. my code is:
#include<stdio.h>
#include<string.h>
int main()
{
char str1[10],str2[10],str3[10],str4[10];
scanf("%s",str1);
scanf("%s",str2);
scanf("%s",str3);
scanf("%s",str4);
if(strcmp(str1,"MAHIRL")==0 && strcmp(str2,"CHITRA")==0 && strcmp(str3,"DEVI")==0 && strcmp(str4,"C")==0 ){
printf("yes");
}
else{
printf("no");
}
return 0;
}
I tried using strtok() and strpbrk(), but I'm not quite sure how to implement them in my code. Any help or suggestion is appreciated. Thanks.
problem is when I try to enter a string with space compiler render that as separate 2 strings
That's not a problem, that's the feature / behaviour of %s format specifier with scanf(). You cannot read space-delimited input using that.
For conversion specifier s, chapter §7.21.6.2, C11
s Matches a sequence of non-white-space characters. [...]
So, the matching ends as soon as it hits a white-space character, here, the space.
If you have to read a line (i.e., input terminated by newline), use fgets() instead.
The %s directive matches characters up to a whitespace before storing them, so it is not possible to get lines of input this way. There are other ways to use scanf() to read lines of input, but these are error-prone, and this is really not the right tool for the job.
Better to use fgets() to fetch a line of input to a buffer, and sscanf() to parse the buffer. Since the requirement here is that four strings are entered, this is a simple problem using this method:
#include <stdio.h>
#include <string.h>
int main(void)
{
char str1[10],str2[10],str3[10],str4[10];
char buffer[100];
if (fgets(buffer, sizeof buffer, stdin) == NULL) {
fprintf(stderr, "Error in fgets()\n");
return 1;
}
if (sscanf(buffer, "%9s%9s%9s%9s", str1, str2, str3, str4) == 4) {
if (strcmp(str1,"MAHIRL") == 0 &&
strcmp(str2,"CHITRA") == 0 &&
strcmp(str3,"DEVI") == 0 &&
strcmp(str4,"C") == 0 ){
printf("yes\n");
} else {
printf("no\n");
}
} else {
printf("Input requires 4 strings\n");
}
return 0;
}
An additional character array is declared, buffer[], with enough extra space to contain extra input; this way, if the user enters some extra characters, it is less likely to interfere with the subsequent behavior of the program. Note that fgets() returns a null pointer if there is an error, so this is checked for; an error message is printed and the program exits if an error is encountered here.
Then sscanf() is used to parse buffer[]. Note here that maximum widths are specified with the %s directives to avoid buffer overflow. The fgets() function stores the newline in buffer[] (if there is room), but using sscanf() in this way avoids needing to further handle this newline character.
Also note that sscanf() returns the number of successful assignments made; if this return value is not 4, the input was not as expected and the values held by str1,..., str4 should not be used.
Update
Looking at this question again, I am not sure that I have actually answered it. At first I thought that you wanted to use scanf() to read a line of input, and extract the strings from this. But you say: "whenever there is a space in string don't treat it as 2 strings", even though none of the test input in your example code contains such spaces.
One option for reading user input containing spaces into a string would be to use a separate call to fgets() for each string. If you store the results directly in str1,...,str4 you will need to remove the newline character kept by fgets(). What may be a better approach would be to store the results in buffer again, and then to use sscanf() to extract the string, this time including spaces. This can be done using the scanset directive:
fgets(buffer, sizeof buffer, stdin);
sscanf(buffer, " %9[^\n]", str1);
The format string here contains a leading space, telling sscanf() to skip over zero or more leading whitespace characters. The %[^\n] directive tells sscanf() to match characters, including spaces, until a newline is encountered, storing them in str1[]. Note that a maximum width of 9 is specified, leaving room for the \0 terminator.
If you want to be able to enter multiple strings, each containing spaces, on the same line of user input, you will need to choose a delimiter. Choosing a comma, this can be accomplished with:
fgets(buffer, sizeof buffer, stdin);
sscanf(buffer, " %9[^,], %9[^,], %9[^,], %9[^,\n]", str1, str2, str3, str4);
Here, there is a leading space as before, to skip over any stray whitespace characters (such as \n characters) that may be in the input. The %[^,] directives tell sscanf() to match characters until a comma is encountered, storing them in the appropriate array (str1[],..., str3[]). The following , tells sscanf() to match one comma and zero or more whitespace characters before the next scanset directive. The final directive is %[^,\n], telling sscanf() to match characters until either a comma or a newline are encountered.
#include <stdio.h>
#include <string.h>
int main(void)
{
char str1[10],str2[10],str3[10],str4[10];
char buffer[100];
if (fgets(buffer, sizeof buffer, stdin) == NULL) {
fprintf(stderr, "Error in fgets()\n");
return 1;
}
/* Each individual string str1,..., str4 may contain spaces */
if (sscanf(buffer, " %9[^,], %9[^,], %9[^,], %9[^,\n]",
str1, str2, str3, str4) == 4) {
if (strcmp(str1,"test 1") == 0 &&
strcmp(str2,"test 2") == 0 &&
strcmp(str3,"test 3") == 0 &&
strcmp(str4,"test 4") == 0 ){
printf("yes\n");
} else {
printf("no\n");
}
} else {
printf("Input requires 4 comma-separated strings\n");
}
return 0;
}
Here is a sample interaction with this final program:
test 1, test 2, test 3, test 4
yes
While reading strings from user, use __fpurge(stdin) function from stdio_ext.h. This flushes out the stdin. When you are entering a string, you press enter at last, which is also a character. In order to avoid that, we use fpurge function.
scanf("%s",str1);
__fpurge(stdin);
scanf("%s",str2);
__fpurge(stdin);
scanf("%s",str3);
__fpurge(stdin);
scanf("%s",str4);
__fpurge(stdin);
Also if you want to input a string from user containing spaces, use following:
scanf("%[^\n]", str1);
This will not ignore the spaces you enter while inputting string.
EDIT: Instead of using fpurge function, one can use following code:
while( getchar() != '\n' );

Scanf clarification in c language

Is it possible to read an entire string including blank spaces like gets() function in scanf()?
I am able to do it using the gets() function.
char s[30];
gets(s);
This will read a line of characters. Can this be done in scanf()?
You can read a line, including blank spaces, with scanf(), but this function is subtle, and using it is very error-prone. Using the %[^\n] conversion specifier, you can tell scanf() to match characters to form a string, excluding '\n' characters. If you do this, you should specify a maximum field width. This width specifies the maximum number of characters to match, so you must leave room for the '\0' terminator.
It is possible that the first character in the input stream is a '\n'. In this case, scanf() would return a value of 0, since there were no matches before encountering the newline. But, nothing would be stored in s, so you may have undefined behavior. To avoid this, you can call scanf() first using the %*[\n] conversion specifier, discarding any leading '\n' characters.
After the string has been read, there will be additional characters in the input stream. At least a '\n' is present, and possibly more characters if the user entered more than the maximum field width specifies. You might then want to discard these extra characters so that they don't interfere with further inputs. The code below includes a loop to do this operation.
The first call to scanf() will consume all newline characters in the input stream until a non-newline character is encountered. While I believe that the second call to scanf() should always be successful, it is good practice to always check the return value of scanf() (which is the number of successful assignments made). I have stored this value in result, and check it before printing the string. If scanf() returns an unexpected result, an error message is printed.
It is better, and easier, to use fgets() to read entire lines. You must remember that fgets() keeps the trailing newline, so you may want to remove it. There is also a possibility that the user will enter more characters than the buffer will store, leaving the remaining characters in the input stream. You may want to remove these extra characters before prompting for more input.
Again, you should check the return value of fgets(); this function returns a pointer to the first element of the storage buffer, or a NULL pointer in the event of an error. The code below replaces any trailing newline character in the string, discards extra characters from the input stream, and prints the string only if the call to fgets() was successful. Otherwise, an error message is printed.
#include <stdio.h>
int main(void)
{
char s[30];
int result;
printf("Please enter a line of input:\n");
scanf("%*[\n]"); // throw away leading '\n' if present
result = scanf("%29[^\n]", s); // match up to 29 characters, excluding '\n'
/* Clear extra characters from input stream */
int c;
while ((c = getchar()) != '\n' && c != EOF)
continue; // discard extra characters
if (result == 1) {
puts(s);
} else {
fprintf(stderr, "EOF reached or error in scanf()\n");
}
printf("Please enter a line of input:\n");
char *ps = fgets(s, 30, stdin); // keeps '\n' character
if (ps) {
while (*ps && *ps != '\n') {
++ps;
}
if (*ps) { // replace '\n' with '\0'
*ps = '\0';
} else {
while ((c = getchar()) != '\n' && c != EOF)
continue; // discard extra characters
}
puts(s);
} else {
fprintf(stderr, "EOF reached or error in fgets()\n");
}
return 0;
}
Note that these two methods of getting a line of input are not exactly equivalent. The scanf() method, as written here, does not accept an empty line (i.e., a line consisting of only the '\n' character), but does accept lines consisting of other whitespace characters. The fscanf() method will accept an empty line as input.
Also, if it is acceptable to ignore leading whitespace characters, it would be simpler to follow the recommendation given by Jonathan Leffler in the comments to use only a single call to scanf():
result = scanf(" %29[^\n]", s);
This will ignore leading whitespace characters, including newlines.
Do not use scanf() or gets() function — use fgets() instead. But for the above question please find the answer.
int main() {
char a[30];
scanf ("%29[^\n]%*c", name);
printf("%s\n", a);
return 0;
}
Its also highly recommended like I told in the beginning to use fgets() instead. We clearly do not understand the weird requirement. I would have used the fgets() to read the character.
fgets(a, size(a), stdin);

What does gets() save when it reads just a newline

Here's the description of gets() from Prata's C Primer Plus:
It gets a string from your system's standard input device, normally
your keyboard. Because a string has no predetermined length, gets()
needs a way to know when to stop. Its method is to read characters
until it reaches a newline (\n) character, which you generate by
pressing the Enter key. It takes all the characters up to (but not
including) the newline, tacks on a null character (\0), and gives the
string to the calling program.
It got my curious as to what would happen when gets() reads in just a newline. So I wrote this:
int main(void)
{
char input[100];
while(gets(input))
{
printf("This is the input as a string: %s\n", input);
printf("Is it the string end character? %d\n", input == '\0');
printf("Is it a newline string? %d\n", input == "\n");
printf("Is it the empty string? %d\n", input == "");
}
return 0;
}
Here's my interaction with the program:
$ ./a.out
This is some string
This is the input as a string: This is some string
Is it the string end character? 0
Is it a newline string? 0
Is it the empty string? 0
This is the input as a string:
Is it the string end character? 0
Is it a newline string? 0
Is it the empty string? 0
The second block is really the thing of interest, when all I press is enter. What exactly is input in that case? It doesn't seem to be any of my guesses of: \0 or \n or "".
This part in the description of gets might be confusing:
It takes all the characters up to (but not including) the newline
It might be better to say that it takes all the characters including the newline but stores all characters not including the newline.
So if the user enters some string, the gets function will read some string and the newline character from the user's terminal, but store only some string in the buffer - the newline character is lost. This is good, because no one wants the newline character anyway - it's a control character, not a part of the data that user wanted to enter.
Therefore, if you only press enter, gets interprets it as an empty string. Now, as noted by some people, your code has multiple bugs.
printf("This is the input as a string: %s\n", input);
No problem here, though you might want to delimit your string by some artificial characters for better debugging:
printf("This is the input as a string: '%s'\n", input);
printf("Is it the string end character? %d\n", input == '\0');
Not good: you want to check 1 byte here, not the whole buffer. If you try to compare the whole buffer with 0, the answer is always false because the compiler converts \0 to NULL and interprets the comparison like "does the buffer exist at all?".
The right way is:
printf("Does the first byte contain the string end character? %d\n", input[0] == '\0');
This compares just 1 byte to \0.
printf("Is it a newline string? %d\n", input == "\n");
Not good: this compares the address of the buffer with the address of "\n" - the answer is always false. The right way to compare string in C is strcmp:
printf("Is it a newline string? %d\n", strcmp(input, "\n") == 0);
Note the peculiar usage: strcmp returns 0 when the strings are equal.
printf("Is it the empty string? %d\n", input == "");
The same bug here. Use strcmp here too:
printf("Is it the empty string? %d\n", strcmp(input, "") == 0);
BTW as people always say, gets cannot be used in a secure way, because it doesn't support protection from buffer overflow. So you should use fgets instead, even though it's less convenient:
char input[100];
while (fgets(input, sizeof input, stdin))
{
...
}
This leads to possible confusion: fgets doesn't delete the newline byte from the input it reads. So if you replace gets in your code by fgets, you will get different results. Fortunately, your code will illustrate the difference in a clear way.
It sets the string to "", that is, {'\0'}. Don’t use gets(), though. It causes buffer overflows.

Don't understand how to input/print and compare string in loop in C

I'm newcomer to C and I am stuck. I want to write simple program, which will take input from keyboard and output it if it isn't an 'exit' word. I've tried few different approaches and none of them works. Almost in all cases I get infinite output of the first input.
Here is one of my approaches:
#include <stdio.h>
int main() {
char word[80];
while (1) {
puts("Enter a string: ");
scanf("%79[^\n]", word);
if (word == "exit")
break;
printf("You have typed %s", word);
}
return 0;
}
I thought after it finish every loop it should give me prompt again, but it doesn't.
What I am doing wrong.
Please if you know give me some advice.
Thanks in advance. Really, guys I will be so happy if you help me to understand what I am doing wrong.
Oh, by the way I've noticed that when I typed some word and press 'Enter', the result string also include Enter at the end. How can I get rid of this ?
Improper string compare - use strcmp().
if (word == "exit") simply compares 2 address: the address of the first char in word and the address of the first char in string literal "exit". Code needs to compare the content beginning at those addresses: strcmp() does that.
Left-over '\n' from the previous line's Enter. Add a space to scanf() format to consume optional leading white-space. Also check scanf() results.
scanf() specifiers like "%d", "%u" and "%f" by themselves consume optional leading white-space. 3 exceptions: "%c", "%n" and "%[".
Add '\n' at end of printf() format. # Matt McNabb
#include <stdio.h>
int main() {
char word[80];
while (1) {
puts("Enter a string: ");
// v space added here
if (scanf(" %79[^\n]", word) != 1)
break; // Nothing saved into word or EOF or I/O Error
if (strcmp(word, "exit") == 0)
break;
printf("You have typed %s\n", word);
}
return 0;
}
Nice that OP used a proper width limited value of 79 in scanf()
Oh, by the way I've noticed that when I typed some word and press 'Enter', the result string also include Enter at the end. How can I get rid of this ?
This is because you don't output a newline after printf("You have typed %s", word);. The next statement executed is puts("Enter a string: "); . So you will see You have typed helloEnter a string:. To fix this, change to printf("You have typed %s\n", word);
As others have mentioned, use strcmp to compare strings in C.
Finally, the scanf format string "%79[^\n]" does not match a newline. So the input stream still contains a newline. Next time you reach this statement the newline is still in the stream , and it still doesn't match because you specifically excluded newlines.
You will need to discard that newline (and any other input on the line) before getting the next line. One way to do that is to change the input to scanf("%79[^\n]%*[^\n]", word); getchar(); That means:
Read up to 79 non-newlines
Read all the non-newline things , and don't store them
Read a character (which must be a newline now) and don't store it
Finally it would be a good idea to check the return value of scanf so that if there is an error then you can exit your program instead of going into an infinite loop.
The specifier [^\n] will abort scanf if the next character is a newline (\n), without reading the newline. Because of that, the scanf calls after the first one won't read any input.
If you want to read single words, use the %79s specifier and the following code to remove the \n at the end of your string:
if(word[strlen(word)]=='\n')
word[strlen(word)]='\0';
If you want to read whole lines, you can remove the newline from the input buffer this way:
char line[80];
int i;
while(1)
{
puts("Enter a string:");
i=-1;
scanf("%79[^\n]%n",line,&i);
//%n returns the number of characters read so far by the scanf call
//if scanf encounters a newline, it will abort and won't modify i
if(i==-1)
getchar(); //removes the newline from the input buffer
if(strcmp(line,"exit")==0)
break;
printf("You have typed %s\n",line);
}
return 0;
It is better to clear (to have a reproducible content) with memset(3) the memory buffer before reading it, and you should use strcmp(3) to compare strings. Also, consider using fflush(3) before input (even if it is not actually necessary in your case), don't forget to test result of scanf(3), also most printf(3) format control strings should end with a \n -for end-of-line with flushing- so:
#include <stdio.h>
int main() {
char word[80];
while(1) {
puts("Enter a string: ");
memset (word, 0, sizeof(word)); // not strictly necessary
fflush(stdout); // not strictly necessary
if (scanf("%79[^\n]", word)<=0) exit(EXIT_FAILURE);
if (!strcmp(word,"exit"))
break;
printf("You have typed %s\n", word);
};
return 0;
}
I would suggest reading a whole line with fgets(3) and getting rid of its ending newline (using strchr(3)). Also read about getline(3)
Don't forget to compile with all warnings and debug info (e.g. gcc -Wall -g) and learn how to use the debugger (e.g. gdb)
Your first problem is that you can't compare a string with '=='. So:
if (word == "exit")
should be
if ( strncmp( word, "exit", 4 ) == 0 )
(You could also use strncmp( word, "exit", strlen(word) ) if you know that word is zero-terminated and safe from bad values. There's a few other options also.)
Your second problem is that scanf() is not consuming the input, probably because it's not matching what you've told it to expect. Here is a good explanation of how to do what you want to do:
http://home.datacomm.ch/t_wolf/tw/c/getting_input.html

Reading of standard input with fgets not waiting for input

Having this piece of code:
int main(void)
{
char str[4];
do
{
if (fgets(str,sizeof(str),stdin) == NULL)
break;
printf("\n %s \n", str);
}while (strncmp(str,"q\n",sizeof("q\n")));
return 0;
}
if i type more than 4 characters, then two lines are displayed. if i type 123456 and then press enter, does input store ['1','2','\n','\0'] or ['1','2','3','\0']? hen the second time printf is reached if i only press enter key one time?. How i can avoid this behaviour? I would like type 123456 and then get:
1234
The reason why fgets is only reading partial input is because the str array is too small. You need to increase the buffer size of str array.
Also remember that fgets will pick up \n ( enter / return ) that you press after giving your input.
To get rid of the \n do this:
fgets(str,sizeof(str),stdin);
str[strlen(str)-1] = '\0';
There is one MAJOR issue with your while condition ... I am not sure what your are trying to do there but strcmp is used to see if two strings are the same or not ... what you are doing is trying to compare a string to the size of something ...
There are multiple problems in your code:
you do not include <stdio.h>.
fgets() is given a very short buffer: 4 bytes, allowing for only 3 characters to be input at a time, including the '\n'. If you type more characters, they are buffered by the terminal and the standard stream library. It will take several calls to fgets() to read them all, 3 bytes at a time.
Your termination test is bogus: strncmp(str, "q\n", sizeof("q\n")) compares the string read by fgets() with "q\n" upto a maximum number of characters of 3 because sizeof("q\n") counts the q, the \n and the null terminator. You should just use strcmp() for this test.
You print the string with printf("\n %s \n", str);. Note however that a regular line read into str will contain the trailing newline so the printf call will actually output 2 lines.
Here is a modified version:
#include <stdio.h>
#include <string.h>
int main(void) {
char str[80];
while (fgets(str, sizeof(str), stdin) != NULL) {
str[strcspn(str, "\n")] = '\0'; // strip the newline if present
printf("\n %s \n", str);
if (!strcmp(str, "q"));
break;
}
return 0;
}
Try using getc() or fgetc() before using fgets()
When you use a scanf(), you press enter key (newline) which operates as accepting the input and transferring the input from stdin (standard input device) to your program.
scanf() itself does not consume the newline pressed. So, we need something down the code which will accept this newline and prevent this newline from acting as an input to the subsequent fgets(). This newline can be accepted using getc() or fgetc(), which should be written before fgets().
fgetc(stdin); OR getc(stdin);

Resources