Reputation: 21
I'm new in the journey of learning C and to my knowledge, I knew that while loop would run forever if someone gives condition such as while (1 == 1)
it would become a forever loop.
But While reading from a book I noticed a code such as
#include<stdio.h>
int main() {
char a;
int started = 0;
puts("Scanning\n");
while (scanf("%s[^\n]",&a) == 1)
{
if (a >= 65 && a <= 90)
{
printf("Char is capital\n");
}
else
{
printf("Not cap.\n");
}
}
puts("Done\n");
return 0;
}
Command line => char.exe < file.txt
It takes input from stdin but scanf returns the number of argument i.e 1 so the condition should become while (1 == 1)
But why this is not a forever loop and exists after reading the file?
Thanks
Upvotes: 1
Views: 394
Reputation: 2973
&a
indicates that you are trying to read a whole line in a stack variable.
But why this is not a forever loop and exists after reading the file?
Trying to read a file in a stack variable will cause stack smashing and your program would crash.
Look for different storage types and memory management in C on internet. a
is a character variable allocated on the program stack and is only suppose to store one character. If you take it's address and try to put more data then it will corrupt adjacent stack memory/variables until OS detects that and kills your program. Your format indicates it will read a whole line i.e. until new line.
scanf
will still return 1 but it will try to store that line in the address of a
.
Did you run it like:
cat <your file>| ./a.out
Allocate a big enough buffer like char a[4096];
and pass a
as
while(scanf("%s[^\n]", a) == 1)
Note now a
is an array now and does not need a &
in front. Your loop will still exit but on EOF when the file finishes. Try to use a file smaller than 4 Kb side for the worst case if new line does not appear until 4Kb.
Provisions for reading a bigger file/lines seem out of scope of your experiment.
Working code
#include<stdio.h>
int main() {
char a[4096];
int started = 0;
puts("Scanning\n");
while (scanf("%s[^\n]", a) == 1)
{
if (a >= 65 && a <= 90)
{
printf("Char is capital\n");
}
else
{
printf("Not cap.\n");
}
}
puts("Done\n");
return 0;
}
Upvotes: 0
Reputation: 32596
In
char a;
...
while (scanf("%s[^\n]",&a) == 1)
your format is invalid because dedicated to a string while you want to read only a char, so you will write out of the char at least for the ending null char producing an undefined behavior
do
char a;
...
while (scanf(" %c",&a) == 1)
and notice the space in the format, remove it if you want to manage all the characters
In
if (a >= 65 && a <= 90)
it is wrong to use ASCII code, this is not readable and not compatible with non ASCII
you can do
if (a >= 'A' && a <= 'Z')
or better use isupper (<ctype.h>
) because it is not guaranty than the uppercase letters are consecutive
Your printf can be replaced by puts removing the \n in the string, or a fputs, is is useless to have printf to print a simple string (without % and arg)
But why this is not a forever loop and exists after reading the file?
scanf does not return 1 on EOF, so the loop stops on EOF, about scanf family :
These functions return the number of input items successfully matched and assigned, which can be fewer than provided for, or even zero in the event of an early matching failure.
The value EOF is returned if the end of input is reached before either the first successful conversion or a matching failure occurs. EOF is also returned if a read error occurs, in which case the error indicator for the stream (see ferror(3)) is set, and errno is set indicate the error.
Upvotes: 2
Reputation: 53
When you enter a letter the condition (1==1)
becomes true and the body of while
loop is iterated.
After iteration of while
loop it goes for next letter. scanf
waits till you enter next character.
Again condition (1==1)
is satisfied.
This loop is an indefinite loop and you could go on entering letters and you would never reach the puts
statement.
Upvotes: 0
Reputation: 181714
But why this is not a forever loop and exists after reading the file?
It will loop indefinitely only if scanf
returns 1 every time it is called. The loop terminates the first time that function returns a different result.*
scanf
's return value conveys the number of input fields successfully scanned and assigned, and under some circumstances also conveys information about I/O errors. In particular, scanf
will return the value of macro EOF
if it reaches the end of the input before matching any fields. EOF
is unequal to 1.
*Provided that the program's behavior is well defined. Your program's is not, for reasons described in comments and another answer.
Upvotes: 1
Reputation: 1037
The function scanf returns the following value:
>0
The number of items converted and assigned successfully.0 — No item was assigned.
<0 — Read error encountered or end-of-file (EOF) reached before any assignment was made.
Upvotes: 0