scanning a line of strings with spaces using scanf - c

I was using scanf for all my inputs in C. Now I saw other similar questions about scanf() and they suggested using fgets() instead of scanf(). I will do so in the future. However, at the moment this particular part of code with scanf() never seems to work. I know there is a solution.
My code is:
#define LENGTH 1000
#define WORD 100
int main(){
int i = 0;
char s[WORD][LENGTH];
do {
scanf("%s", s[i]);
i++;
}
while (s[i][strlen(s[i])] != EOF);
printf("%s\n", s);
return 0;
}
There should be something instead of EOF in the while loop which checks for the end of line. The final result should be an array of words in s[] and the program should print that array of words without spaces.

Unfortunately scanf() does not read the character you need to check for end of line, or at least not using "%s" as the specifier.
Instead, use the following
char line[100];
if (scanf("%99[^\n]", line) == 1) {
fprintf(stdout, "%s\n", line);
}
This way, it does not stop at white space characters, and it behaves similar to fgets(), except that it does not read the '\n' character and that might be a problem if you call it again.

Related

Counting the Whole String Including The Spaces in C

I'm trying to set up a code that counts the whole string and doesn't stop after the first space that it finds. How do I do that?
I tried this kind of code but it just counts the first word then goes to display the number of letters in that first word.
So far this is what I have tried.
int main(){
char get[100];
int i, space=0, len=0, tot;
scanf("%s", get);
for (i=0; get[i]!='\0'; i++)
{
if (get[i] == ' ')
space++;
else
len++;
}
tot = space + len;
printf("%i", tot);
}
And
int main(){
char get[100];
int len;
scanf("%s", &get);
len = strlen(get);
printf("%i", len);
}
But would still get the same answer as the first one.
I expected that if the
input: The fox is gorgeous.
output: 19
But all I get is
input: The fox is gorgeous.
output: 3
strlen already includes spaces, since it counts the length of the string up to the terminating NUL character (zero, '\0').
Your problem is that that the %s conversion of scanf stops reading when it encounters whitespace, so your string never included it in the first place (you can verify this easily by printing out the string). (You could fix it by using different scanf conversions, but in general it's easier to get things right by reading with fgets – it also forces you to specify the buffer size, fixing the potential buffer overflow in your current code.)
The Answer by Arkku is correct in its diagnose.
However, if you wish to use scanf, you could do this:
scanf("%99[^\n]", get);
The 99 tells scanf not to read more than 99 characters, so your get buffer won't overflow. The [^\n] tells scanf to read any character until it encounters the newline character (when you hit enter).
As Chux pointed out, the code still has 2 issues.
When using scanf, it is always a good idea to check its return value, which is the number of items it could read. Also, indeed the \n remains in the input buffer when using the above syntax. So, you could do this:
if(scanf("%99[^\n]", get) == 0){
get[0] = 0; //Put in a NUL terminator if scanf read nothing
}
getchar(); //Remove the newline character from the input buffer
I will take one example to explain the concept.
main()
{
char s[20], i;
scanf("%[^\n]", &s);
while(s[i] != '\0') {
i++;
}
printf("%d", i);
return 0;
}
i have used c language and u can loop through the ending the part of the string and you will get the length. here i have used "EDIT SET CONVESRION METHOD" to read string, you can also gets to read.

C string compare wont allow space bar

using the cprogrammingsimplified tutorial for writing my own stringcompare.
Finished reformatting it and ran it.
works fine for single words,
But
typing space bar skips the second scan and immediately outputs
'words aren't the same'
anyone any idea how to allow the use of even a single space bar?
Thanks in advance.
#include <stdio.h>
int mystrcmp(char s1[], char s2[]);
int main(){
char s1[10], s2[10];
int flag;
printf("Type a string of 10\n\n");
scanf("%s",&s1);
printf("type another string of 10 to compare\n\n");
scanf("%s",&s2);
flag = mystrcmp(s1,s2);
if(flag==0)
printf("the words are the same\n\n");
else
printf("the words are not the same\n\n");
return 0;
}
int mystrcmp(char s1[], char s2[]){
int l=0;
while (s1[l] == s2[l]) {
if (s1[l] == '\0' || s2[l] == '\0')
break;
l++;
}
if (s1[l] == '\0' && s2[l] == '\0')
return 0;
else
return -1;
}
Use fgets() to read full lines, rather than scanf() to read space-separated words.
Remember that fgets() will include the linefeed in the string, though.
It is not strcmp that wouldn't allow space bar, it's scanf with %s format specifier. The input is truncated at the space, so the second string that you read is actually the continuation of the first string.
You can fix this by using %9[^\n] instead of %s in your format specifier:
printf("Type a string of 10\n\n");
scanf("%9[^\n]",s1); //s1 is char [10]
printf("type another string of 10 to compare\n\n");
scanf("%9[^\n]",s2); //s2 is char [10]
9 limits input to nine characters, because you are using a ten-character buffer.
Many answers have told you that scanf("%s",s1) only reads word by word. This is because by default scanf("%s",s1) is delimited by all white spaces, this includes \t, \n, <space>, or any other you can think of.
What scanf("%[^\n]s",s1) does is set the delimiter to \n. So in effect reads all other spaces.
#dasablinklight has also specified a 9 before the '[^\n]' this denotes that scanf() takes 9 values from input buffer.
IMO scanf() is a really nice function due to it's hidden features. I suggest you read more about it in it's documentation.
The problem is that if you type abc def on the first line, the first scanf("%s", s1) (no ampersand required — it should be absent) reads abc and the second reads def. And those are not equal. Type very very and you'd find the words are equal. %s stops reading at a space.
Your buffers of size 10 are too small for comfort.
Fix: read lines (e.g. char s1[1024], s2[1024];) with fgets() or POSIX's getline(), remove trailing newlines (probably: s1[strcspn(s1, "\n")] = '\0'; is a reliable way to do it) and then go ahead compare the lines.

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

How to take inputs for strings one by one in C

I have to take inputs like below, and print the same (only the sentences):
2
I can't believe this is a sentence.
aarghhh... i don't see this getting printed.
Digit 2 shows the number of lines to be followed (2 lines after this here).
I used all the options scanf and fgets with various regex used.
int main() {
int t;
char str[200];
scanf ("%d", &t);
while (t > 0){
/*
Tried below three, but not getting appropriate outputs
The output from the printf(), should have been:
I can't believe this is a sentence.
aarghhh... i don't see this getting printed.
*/
scanf ("%[^\n]", str);
//scanf("%200[0-9a-zA-Z ]s", str);
//fgets(str, 200, stdin);
printf ("%s\n", str);
t--;
}
}
I am sorry, i have searched all related posts, but I am not able to find any answer to this:
All versions of scanf() produce no results, and fgets() prints only the first sentence.
Thanks in advance.
You should just use fgets(). Remember that it will keep the linefeed, so you might want to remove that manually after reading the line:
if(scanf("%d", &t) == 1)
{
while(t > 0)
{
if(fgets(str, sizeof str, stdin) != NULL)
{
const size_t len = strlen(str);
str[len - 1] = '\0';
printf("You said '%s'\n", str);
--t;
}
else
printf("Read failed, weird.\n");
}
}
To make it easier let's say the input is "2\none\ntwo\n".
When you start your program, before the first scanf() the input buffer has all of it and points to the beginning
2\none\ntwo
^
After the first scanf(), the "2" is consumed leaving the input buffer as
2\none\ntwo
^^
And now you attempt to read everything but a newline ... but the first thing in the buffer is a newline, so nothing gets read.
Suggestion: always use fgets() to read full lines, and then parse the input as you think is better.
To use regex in C you must include regex.h. In this case, you do not need regex. Where you have "%[^\n]", replace it with "%s". Make sure that you include stdio.h.

Changing the scanf() delimiter

My objective is to change the delimiter of scanf to "\n".
I tried using scanf("%[^\n]s",sen); and works fine for single inputs.
But when i put the same line inside a for loop for multiple sentences it gives me garbage values.
Does anyone know why?
Here's my code:
char sen[20];
for (i=0;i<2;i++)
{
scanf("%[^\n]s",sen);
printf("%s\n",sen);
}
Consider this (C99) code:
#include <stdio.h>
int main(void)
{
char buffer[256];
while (scanf("%255[^\n]", buffer) == 1)
printf("Found <<%s>>\n", buffer);
int c;
if ((c = getchar()) != EOF)
printf("Failed on character %d (%c)\n", c, c);
return(0);
}
When I run it and type in a string 'absolutely anything with spaces TABTABtabs galore!', it gives me:
Found <<absolutely anything with spaces tabs galore!>>
Failed on character 10 (
)
ASCII (UTF-8) 1010 is newline, of course.
Does this help you understand your problem?
It works in this case (for a single line) but if I want to take multiple lines of input into an array of arrays then it fails. And I don't get how scanf returns a value in your code?
There are reasons why many (most?) experienced C programmers avoid scanf() and fscanf() like the plague; they're too hard to get to work correctly. I'd recommend this alternative, using sscanf(), which does not get the same execration that scanf() and fscanf() do.
#include <stdio.h>
int main(void)
{
char line[256];
char sen[256];
while (fgets(line, sizeof(line), stdin) != 0)
{
if (sscanf(line, "%255[^\n]", sen) != 1)
break;
printf("Found <<%s>>\n", sen);
}
int c;
if ((c = getchar()) != EOF)
printf("Failed on character %d (%c)\n", c, c);
return(0);
}
This reads the line of input (using fgets() which ensures no buffer overflow (pretend that the gets() function, if you've heard of it, melts your computer to a pool of metal and silicon), then uses sscanf() to process that line. This deals with newlines, which are the downfall of the original code.
char sen[20];
for (i=0;i<2;i++)
{
scanf("%[^\n]s",sen);
printf("%s\n",sen);
}
Problems:
You do not check whether scanf() succeeded.
You leave the newline in the buffer on the first iteration; the second iteration generates a return value of 0 because the first character to read is newline, which is the character excluded by the scan set.
The gibberish you see is likely the first line of input, repeated. Indeed, if it were not for the bounded loop, it would not wait for you to type anything more; it would spit out the first line over and over again.
Return value from scanf()
The definition of scanf() (from ISO/IEC 9899:1999) is:
§7.19.6.4 The scanf function
Synopsis
#include <stdio.h>
int scanf(const char * restrict format, ...);
Description
2 The scanf function is equivalent to fscanf with the argument stdin interposed
before the arguments to scanf.
Returns
3 The scanf function returns the value of the macro EOF if an input failure occurs before
any conversion. Otherwise, the scanf function returns the number of input items
assigned, which can be fewer than provided for, or even zero, in the event of an early
matching failure.
Note that when the loop in my first program exits, it is because scanf() returned 0, not EOF.
%[^\n] leaves the newline in the buffer. %[^\n]%*c eats the newline character.
In any case, %[^\n] can read any number of characters and cause buffer overflow or worse.
I use the format string %*[^\n]%*c to gobble the remainder of a line of input from a file. For example, one can read a number and discard the remainder of the line by %d%*[^\n]%*c. This is useful if there is a comment or label following the number, or other data that is not needed.
char sen[20];
for (i=0;i<2;i++)
{
scanf("%[^\n]s",sen);
printf("%s\n",sen);
getchar();
}
Hope this helps ... actually "\n" remains in stream input buffer... Ee need to flush it out before scanf is invoked again
I know I am late, but I ran into same problem after testing C after a long time.
The problem here is the new line is considered as input for next iteration.
So, here is my solution, use getchar() to discard the newline the input stream:
char s[10][25];
int i;
for(i = 0; i < 10; i++){
printf("Enter string: ");
scanf("%s", s[i]);
getchar();
}
Hope it helps :)
While using scanf("%[^\n]", sen) in a loop, the problem that occurs is that the \n stays within the input buffer and is not flushed. As a result next time, when the same input syntax is used, it reads the \n and considers it as a null input. A simple but effective solution to address this problem is to use:
char sen[20];
for (i=0;i<2;i++)
{
scanf("%[^\n]%*c",sen);
printf("%s\n",sen);
}
%*c gets rid of the \n character in the input buffer.

Resources