-1

Why did my scanf function inside while runs only one time?

#include<stdio.h>
#include<stdlib.h>

int main()

{

char s[9999];

while(scanf("%[^\n]s",s)>0)

{ 
    
    int count=0, prev=0; 
    for (int i=0;i<strlen(s);i++)
{
if(s[i]==' ')
{
count=i-prev;
prev=i+1;
printf("%c", (char) (96+count));
}
else if(strlen(s)-1==i)
{
count=i-prev+1; printf("%c", (char) (96+count)); }
} 
printf(" ");
}}

my test case and output:

enter image description here

Input is considered as a string with a maximum length 1000

Spark
  • 219
  • 2
  • 13
  • 2
    The first `scanf` leaves the newline in the input buffer. So the second `scanf` fails and returns 0, which stops the loop. btw, `%[^\n]` should **not** be followed by an `s`. – user3386109 Sep 20 '21 at 16:36
  • 1
    Use `fgets` to read the whole line, including the newline. See [this question](https://stackoverflow.com/questions/2693776) for advice on how to remove the newline from the buffer. – user3386109 Sep 20 '21 at 16:39
  • 1
    Use `" %9998[^\n]"`. In particular, note the leading space. – William Pursell Sep 20 '21 at 17:11

2 Answers2

1

Unless you understand scanf, you shouldn't use it. When you understand scanf, you will not use it. There are several problems with

while(scanf("%[^\n]s",s)>0)

scanf will read the input stream, writing characters into the variable s until it sees a newline. It will then try to match a literal s in the input stream. Clearly, the next character is not an s (it is a newline), so the s in the format string does not match. (This is not really a problem, but is certainly bizarre that you have asked scanf to match a literal s when an s is certainly not there. If you had tried to do further matches with something like "%[^\n]s%d", you might be confused as to why scanf never matches an integer. It is because scanf stops scanning as soon as the input stream does not match the format string, and the s in the format string will not match.) On the second iteration of the loop, the first character scanf sees is that newline, so it makes no conversions and returns 0. If you want to discard that newline and are okay with removing leading whitespace, you can simply use " %[\n]" as a conversion specifier. If you do not want to discard leading whitespace, you can discard the newline with " %[\n]%*c" Note that you really ought to protect against overwriting s, so you should use either:

while(scanf(" %9998[^\n]", s) > 0)

or

while(scanf("%9998[^\n]%*c", s) > 0)
William Pursell
  • 204,365
  • 48
  • 270
  • 300
  • what is that 9998 ? and *c ? – Spark Sep 20 '21 at 17:27
  • I don't want carriage return to be appended in my string what should I do? – Spark Sep 20 '21 at 17:29
  • 1
    If you use either of the suggestions above, the newline will not be in your string. The `9998` instructs scanf to read only that many characters. Since it will write everything it reads plus a null-terminator, you need that to prevent it from overwriting your buffer. The `%*c` instructs scanf to read one character and discard it. – William Pursell Sep 20 '21 at 17:39
0

Here, during the first iteration, s stores the first line, and at the second iteration s read \n. Since I used %[^\n], scanf will stop scanning.

Now here, the number of elements scanned is zero. So the while loop condition is failed. Hence, the loop is iterated only for one line.

We can change the condition as:

while(scanf("%[^\n]\n",s)>0)

This will skip scanning \n, and desired output is printed.

Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77
Spark
  • 219
  • 2
  • 13
  • 1
    This will confuse the interactive user, `scanf` will not return until some non-whitespace character is seen on the input stream after the first newline. (ie, the user will have to enter the 2nd line of input before the 1st will be processed) – William Pursell Sep 20 '21 at 17:14
  • Oh but when I'm using this I'm getting desired output.Using this I gave a conclusion and even I'm not sure – Spark Sep 20 '21 at 17:19
  • I checked by adding printf("%d",strlen(s)). I can find carraige return is added to string. – Spark Sep 20 '21 at 17:23
  • Yes, the data is read as you expect, but when it is interactive it appears that processing is delayed. It will work fine if you are just piping data to the program. – William Pursell Sep 20 '21 at 17:25
  • In `"%[^\n]\n"`, the second `\n` is not necessary and does not do what you think it does. The "right way" to fix this is to use `" %[^\n]"`, without the extra `\n`, but with a leading space. This is a surprising and confusing result, difficult to explain, which is why I don't personally recommend using `%[...]` at all. (I said "right way" to fix it, but an even better way to fix it is to dispense with `scanf` altogether, and use `fgets`, which is a better way to read whole lines in almost, albeit not quite, every way.) – Steve Summit Sep 21 '21 at 02:44