Some satements in for loop not executing at each iteration - c

#include<stdio.h>
int main()
{
int NC=0,k=0;
char mychar;
scanf("%d",&NC);
for(k=0;k < NC;k++)
{
printf("\nenter a character:-");
scanf("%c",&mychar);
printf("\n%c",mychar);
}
return 0;
}
statements below first printf statement are executing at alternative iteration of the for loop.
ie. enter image description here

When you enter a character at the keyboard, you press one key for the character, and then you press ENTER. Two characters are in the input stream: the character you enter, and a newline character. scanf() is leaving a \n character behind in the input stream. This newline character gets picked up by scanf() in the next iteration of the loop. Change to:
scanf(" %c",&mychar);
to skip over leading whitespace characters, including newlines.
To expand on this a little more, scanf() reads characters from the input stream. The %c specifier matches one character, so the second character, a \n, is left in the input stream. By adding a leading space: " %c", you are telling scanf() to first match zero or more whitespace characters (newline characters are whitespace characters, as are \t and \r), then to match another character, which is then stored in mychar. This way even when the next character to be read from the input stream is a newline character, it is skipped over. Note that most conversion specifiers automatically skip over leading whitespace characters. The ones that don't are: %c, %[], and %n.

Related

Why won't this scanf format-string work? "%[^\n]\n"

I've seen a few examples where people give scanf a "%[^\n]\n" format string to read a whole line of user input. If my understanding is correct, this will read every character until a newline character is reached, and then the newline is consumed by scanf (and not included in the resulting input).
But I can't get this to work on my machine. A simple example I've tried:
#include <stdio.h>
int main(void)
{
char input[64];
printf("Enter some input: ");
scanf("%[^\n]\n", input);
printf("You entered %s\n", input);
}
When I run this, I'm prompted for input, I type some characters, I hit Enter, and the cursor goes to the beginning of the next line but the scanf call doesn't finish.
I can hit Enter as many times as I like, and it will never finish.
The only ways I've found to conclude the scanf call are:
enter \n as the first (and only) character at the prompt
enter Ctrl-d as the first (and only) character at the prompt
enter some input, one or more \n, zero or more other characters, and enter Ctrl-d
I don't know if this is machine dependent, but I'm very curious to know what's going on. I'm on OS X, if that's relevant.
According to the documentation for scanf (emphasis mine):
The format string consists of whitespace characters (any single whitespace character in the format string consumes all available consecutive whitespace characters from the input), non-whitespace multibyte characters except % (each such character in the format string consumes exactly one identical character from the input) and conversion specifications.
Thus, your format string %[^\n]\n will first read (and store) an arbitrary number of non-whitespace characters from the input (because of the %[^\n] part) and then, because of the following newline, read (and discard) an arbitrary number of whitespace characters, such as spaces, tabs or newlines.
Thus, to make your scanf stop reading input, you either need to type at least one non-whitespace character after the newline, or else arrange for the input stream to end (e.g. by pressing Ctrl+D on Unix-ish systems).
Instead, to make your code work as you expect, just remove the last \n from the end of your format string (as already suggested by Umamahesh P).
Of course, this will leave the newline still in the input stream. To get rid of it (in case you want to read another line later), you can getc it off the stream, or just append %*c (which means "read one character and discard it") or even %*1[\n] (read one newline and discard it) to the end of your scanf format string.
Ps. Note that your code has a couple of other problems. For example, to avoid buffer overflow bugs, you really should use %63[^\n] instead of %[^\n] to limit the number of characters scanf will read into your buffer. (The limit needs to be one less than the size of your buffer, since scanf will always append a trailing null character.)
Also, the %[ format specifier always expects at least one matching character, and will fail if none is available. Thus, if you press enter immediately without typing anything, your scanf will fail (silently, since you don't check the return value) and will leave your input buffer filled with random garbage. To avoid this, you should a) check the return value of scanf, b) set input[0] = '\0' before calling scanf, or c) preferably both.
Finally, note that, if you just want to read input line by line, it's much easier to just use fgets. Yes, you'll need to strip the trailing newline character (if any) yourself if you don't want it, but that's still a lot easier and safer that trying to use scanf for a job it's not really meant for:
#include <stdio.h>
#include <string.h>
void chomp(char *string) {
int len = strlen(string);
if (len > 0 && string[len-1] == '\n') string[len-1] = '\0';
}
int main(void)
{
char input[64];
printf("Enter some input: ");
fgets(input, sizeof(input), stdin);
chomp(input);
printf("You entered \"%s\".\n", input);
}
Whitespace characters in format of scanf() has an special meaning:
Whitespace character: the function will read and ignore any whitespace
characters encountered before the next non-whitespace character
(whitespace characters include spaces, newline and tab characters --
see isspace). A single whitespace in the format string validates any
quantity of whitespace characters extracted from the stream (including
none).
Thus, "%[^\n]\n" is just equivalent to "%[^\n] ", telling scanf() to ignore all whitespace characters after %[^\n]. This is why all '\n's are ignored until a non-whitespace character is entered, which is happened in your case.
Reference: http://www.cplusplus.com/reference/cstdio/scanf/
Remove the the 2nd new line character and the following is sufficient.
scanf("%[^\n]", input);
To answer the original one,
scanf("%[^\n]\n", input);
This should also work, provided you enter a non white space character after the input. Example:
Enter some input: lkfjdlfkjdlfjdlfjldj
t
You entered lkfjdlfkjdlfjdlfjldj

Adding characters at the end of a string

I am trying to add some characters at the end of a string using the following code. I am not getting the desired output.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
int l,i;
char a[30];
printf("Enter \n");
scanf("%s",a);
l=strlen(a);
for(i=l;i<(29-l);i++)
{
scanf("%c",&a[i]);
a[i+1]='\0';
printf("\n%s",a);
}
return 0;
}
I guess, the problem is with whitespace. After you enter the first string, there is still a newline \n in the input buffer. When you then read one character with scanf, you get the newline and not the character you entered.
You can skip the whitespace, when you prefix the format string with a space
scanf(" %c",&a[i]);
Now it will append the character entered at the end of the string.
Update:
From scanf
The format string consists of a sequence of directives which describe how to process the sequence of input characters.
...
• A sequence of white-space characters (space, tab, newline, etc.; see isspace(3)). This directive matches any amount of white space, including none, in the input.
This means, when you insert a space in the format string, it will skip all white-space in the input.
This will happen automatically with other input directives like %s or %d. But %c takes the next character, even if it is a white-space char. Therefore, if you want to skip white-space in this case, you must tell scanf by inserting a space in the format string.

Make scanf pick up spaces in the middle of a string

I am trying to use scanf() for input. It worked perfectly except when I typed a space. Then it doesn't pick up the string -- why?
char idade;
scanf("%c", &idade);
I tried do to this:
scanf("%[^/n]c", &idade);
But it did not work. For example, when I typed in "Hello world", my string only contained "Hello" All I want is for it to recognize the space and take the full string. How can I do that?
The %c conversion specifier in the format string of scanf does not skip (read and discard) the leading whitespace characters. If you have a leading whitespace character in the format string, then this means scanf will skip any number of leading whitespace characters in the input which is probably what you want. Assuming you want to read a single character -
char idade;
scanf(" %c", &idade);
// ^ note the leading space
However, if you want to read an input string from stdin, then
char input[50+1]; // max input length 50. +1 for the terminating null byte
// this skips any number of leading whitespace characters and then
// reads at most 50 non-whitespace chars or till a whitespace is encountered -
// whichever occurs first, then adds a terminating null byte
scanf("%50s", input);
// if you want to read a input line from the user
// then use fgets. this reads and stores at max 50 chars
// or till it encounters a newline which is also stored - whichever
// occurs first, then it adds a terminating null byte just like scanf
fgets(input, sizeof input, stdin);
Please read the man page of fgets.
There's a small error in your line
scanf("%[^/n]c", &idade);
It should read
scanf("%[^\n]", &idade);
Backslash '\' is the escape character, not '/'.
You have to put '\n' (line feed character) in the exclusion list or else scanf will not know when to stop parsing.
Your expression excluded '/' and 'n' as input characters.

Why do interleaved scanf() + printf() statements result in both scanf() calls executing first, then both printf() calls?

Can you please explain one thing in the following code:
#include<stdio.h>
int main()
{
int n;char ch,ch1;
scanf("%d\n",&n);
printf("d-%d \n",n);
scanf("\n%c",&ch);
printf("ch-%d \n",ch);
scanf("\n%c",&ch1);
printf("ch1-%d \n",ch1);
printf("%d %d %d\n",n,ch,ch1);
return 0;
}
Why is it that after entering the value of n,it directly asks for the value of ch and then directly executes the statements to print their respective values ie the statements:
printf("d-%d \n",n);
printf("ch-%d \n",ch);
scanf("%d\n",&n); skips any number of trailing white-spaces (including none) after actual the input. It can also be written asscanf("%d ",&n);.
scanf("\n%c",&ch); skips any number of leading white-spaces (including none) before the actual input. It can also be written as scanf(" %c",&ch);.
NOTE: A white-space in a format specifier is able to skip any number of white-spaces.
Now what does it mean by skipping white-spaces ?
It means scanf repeatedly reads white-space characters from input until it reaches a non-white-space character. Now there is no white-space characters left in the buffer.
When it encounters a non-white-space character, then this character is put back to be read again during the scanning of the next input item or during the next call of scanf.
Now coming to your question.
Why do interleaved scanf() + printf() statements result in both scanf() calls executing first, then both printf() calls?
I am assuming the input for n is 15. When you press Enter key then the \n character goes with 15 in the input buffer. scanf("%d\n",&n); reads the 15 and then skips \n. Now this scanf waits for a non-white-space character to be entered (unlike what you supposed that 15 should be printed) . When you enter a, it puts it back for the next call of scanf. The next statement scanf("\n%c",&ch); reads this a from the buffer and do not let the user to input the value for ch. Since the value of n and ch both is now read by these scanfs, it appears to be that both of
printf("d-%d \n",n);
printf("ch-%d \n",ch);
executes after both of the scanfs call (which is not the case!).
Any whitespace in a scanf format is like any other whitespace in a scanf format. It simply tells scanf to skip any whitespace in the input.
Most format codes doesn't need it though as they skip leading whitespace automatically, but one that does (unless you want to actually read a whitespace character) is the "%c" format code.
You might also want to read this reference.

Input taking spaces by default in c

In the below program when am reading input from keyboard its taking only 2 characters instead of 4 and remaining 2 characters its taking spaces by default.
why is it???
program to take char input through pointers/
int c,inc,arrysize;
char *revstring;
printf("enter the size of char arry:");
scanf("%d",&arrysize);
revstring = (char *)malloc(arrysize * sizeof(*revstring));
printf("%d",sizeof(revstring));
printf("enter the array elements:");
for(inc=0;inc<arrysize;inc++)
{
scanf("%c",&revstring[inc]);
}
for(inc =0;inc<arrysize;inc++)
printf("%c",revstring[inc]);
getch();
return 0;
}
scanf reads formatted inputs. When you tape a number, you tape the digits, and then, you press <Enter>. So there is a remaining \n in stdin, which is read in the next scanf. The same applies if you press <Enter> between the characters.
A solution is to consume the characters in the standard input stream after each input, as follow:
#include <stdio.h>
void
clean_stdin (void)
{
int c;
while ((c = getchar ()) != '\n' && c != EOF)
;
}
Another idea is to use fgets to get human inputs. scanf is not suitable for such readings.
Most of the time scanf reads formatted input. For most % formats, scanf will first read and discard any whitespace and then parse the item specified. So with scanf("%d", ... it will accept inputs with initial spaces (or even extra newlines!) with no problems.
One of the exceptions, however, is %c. With %c, scanf reads the very next character, whatever it may be. If that next character is a space or newline, that is what you get.
Depending on what exactly you want, you may be able to just use a blank space in your format string:
scanf(" %c",&revstring[inc]);
The space causes scanf to skip any whitespace in the input, giving you the next non-whitespace character read. However, this will make it impossible to enter a string with spaces in it (the spaces will be ignored). Alternately, you could do scanf(" "); before the loop to skip whitespace once, or scanf("%*[^\n]"); scanf("%*c"); to skip everything up to the next newline, and then skip the newline.

Resources