how the break command acts in my test code - c

my test code is as follows:
#include <stdio.h>
int main(){
char c;
while ((c=getchar())!=EOF){
if(c>='A'&& c<='Z'){
c=c-'A'+'a';
putchar(c);
}
//else break;
}
return 0;
}
without the else break command, the while loop went forever, but when I added the "else" command line, the loop only executed for once, I typed "A" it displayed "a" on the monitor and then stopped. But I thought it should be like this: if A~Z is input, then it produces the lower case letter, if the input character is not within the range, eg. a number of something, it would break the loop and execution would stop. Where am I made the mistake? I have tried to add curly brackets after "else" around "break", but the result remained.

The getchar function will read EVERY char from stdin, even the newline character from the "Enter/Return" key.
When you enable your else part, your code also reacts to the '\n', which causes the break.
You may try to change the
else break;
by
else if (c != '\n') break;
in your code.

If you enter only A and nothing else, your program sees A and the newline character \n. The newline character doesn't match the pattern A...Z, so the break statement is executed.
You can see this by printing the code of the character:
while ((c=getchar())!=EOF){
printf("Character code: %d\n", c);
...
}
You can enter something like ABACABB to see your desired behavior.

char c;
while ((c=getchar())!=EOF){
needs to be
int c;
while ((c=getchar())!=EOF){
see http://www.tutorialspoint.com/c_standard_library/c_function_getchar.htm
IN addition your code does not say 'stop if they enter a char thats not A-Z', it says' ask them for input till they type EOF - echoing back to them when they type A-Z'. EOF is types as ctrl-D on UNix

Related

Undefined behaviour of scanf() in a do-while loop

I'm currently learning C by a book "C Programming a modern approach" and encountered this code. When I tried to run it, after typing consecutive characters like 'abc' and hitting Enter (new line), nothing was printed. Please explain what is going on here.
char ch;
do {
scanf("%c" , &ch);
} while (ch != '\n');
printf("%c", ch);
You're asking the user to input a character using scanf. This is happening in a loop until the user inputs a '\n' or newline character (the same as pressing the enter key), which is when the loop will break.
Your print statement will then print the character in the variable ch, which at that point will be '\n' (since this variable just stores one character, the last one you typed).
This newline character will probably be invisible when you run your program so you may not be seeing it. You can add another print statement after the loop and if that print statement starts at a newline, you know that the '\n' was printed on the previous line.
Something like:
#include <stdio.h>
int main()
{
char ch;
do
{
scanf("%c" , &ch);
} while (ch != '\n');
printf("%c", ch);
printf("I should show up on a newline");
return 0;
}
The code you provided reads characters from the input using the scanf() function and stores them in the variable ch until a newline character (\n) is encountered. After that, the program prints the last character that was read, which is the newline character.
The reason you are not seeing any output when you enter characters followed by a newline character is because the printf() statement is only executed after the loop has finished running. So, the program is waiting for you to enter a newline character to terminate the loop and print the last character that was read.
If you want to see the characters you enter, you can add a printf() statement inside the loop, like this:
char ch;
do {
scanf("%c" , &ch);
printf("%c", ch);
} while (ch != '\n');
This will print out each character as it is read from the input, so you can see what you're typing. Happy coding :)
When I tried to run it, after typing consecutive characters like abc and hitting Enter (new line), nothing was printed.
Well with the posted code, if the loop even finishes, the last byte read by scanf("%c", &ch) and stored into ch is the newline character. Hence printf("%c", ch) outputs this newline and it seems nothing is printed but something is, the newline which is invisible on the terminal but does move the cursor to the next line.
You can make this more explicit by changing the printf call to this:
printf("last value: '%c'\n", ch);
Note however that the posted code is not a recommended way to read the contents of the input stream:
scanf("%c", &ch) may fail to read a byte if the stream is at end of file. Failure to test this condition leads to undefined behavior (ch is unmodified, hence stays uninitialized if the input stream is an empty file) or to an infinite loop as ch may never receive a newline.
this code is a typical example of a do / while with a classic bug. It would be much better to write the code using getchar() and a while loop.
Here is a modified version:
#include <stdio.h>
int main(void) {
int c; // must use int to distinguish EOF from all valid byte values
int count = 0; // to tell whether a byte was read at all
char ch = 0; // the last byte read
// read all bytes from the input stream until end of file or a newline
while ((c = getchar()) != EOF && c != '\n') {
ch = (char)c;
count++;
}
if (count == 0) {
printf("no characters entered: ");
if (c == EOF) {
printf("end of file or read error\n");
} else {
printf("empty line\n");
}
} else {
printf("last character on line is '%c'\n", ch);
if (c == EOF) {
printf("end of file or input error encountered\n");
}
}
return 0;
}

I dont understand how this code can display a string by using just getchar

I don't understand how this code can display a string by using just getchar, I know that it has something to do with buffers, but I don't understand it.
#include <stdio.h>
int main() {
int c;
puts("Enter text. Include a dot ('.') in a sentence to exit:");
do {
c = getchar();
putchar(c);
} while (c != '.');
return 0;
}
Simply reads each character one by one with getchar and prints immediately with putchar. When encounters a dot (.), prints it and then terminates. Hence it doesn't store more than a single character at a time.
do-while loop
Executes a statement repeatedly, until the value of expression becomes false. The test takes place after each iteration.
getchar
Reads the next character from stdin.
Equivalent to getc(stdin).
putchar
Writes a character ch to stdout. Internally, the character is converted to unsigned char just before being written.
Equivalent to putc(ch, stdout).
Code may look like I/O happens immediately, but certainly both stdin and stdout are buffered by lines.
The first getchar() likely does not return until a line (characters up to and including a '\n') of input happens. Then the first call gets the first characters, 2nd calls gets the second, etc.
Similar for output. Output is not "printed" until a '\n' is sent.
To see output without waiting for a putchar('\n'), follow the putchar() with fflush(stdout);.
To read one character immediately with getchar() takes more work. No answer for that at this time.

Count lowercase letters till the input is string

I wrote a short code in C which count the lowercase letters (only letters) and it'll stop working when I enter a number or something else. Here is the code:
char letter;
int num=0;
do
if(islower(letter = getchar()))
num++;
while(isalpha(letter));
printf("%d", num);
return 0;
My problem is that it isn't working properly (only print "1" as result).
And it has to be stopped when the next character isn't alphabetical letter. Not sure that part is right.
Any idea what did I wrong? Thanks.
what's about this?
char letter;
int num=0;
while (isalpha(letter = getchar())) {
if (islower(letter)) num++;
}
printf("%d", num);
return 0;
And it has to be stopped when the next character isn't alphabetical letter.
keyboard input can be buffered - not processing until Enter be pressed
only print "1" as result
can you write some examples of inputed in console caused to "1" output?
The problem is that, after inputting a single character, the subsequent call to getchar() returns a newline character, as the '\n' from the return key is buffered. So, the first iteration of
do
if (islower(letter = getchar()))
num++;
while (isalpha(letter));
works, but the program displays "1" as the islower() call returns false when the newline is processed.
To fix this, use a while loop to eat away the extra newlines. You could do it as such:
do {
while ((letter = getchar()) == '\n')
;
if (islower(letter))
num++;
} while (isalpha(letter));

Input Redirection not working?

My instructions: Write a program that repeatedly (until end-of-file) reads in a character
from the input stream. If the character is upper case, change it to lower case
and write it to the output stream. For all other characters, write the
character unchanged to the output stream.
Use getchar() for input, Use putchar() for output, and use input redirection
for connecting the input file to the program
My project name is Input and my textfile is input.txt. When I run it I type "Input < input.txt" The program just mimics that on the command window though so how do I get it to read from the text file?
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main()
{
char c, x;
c=getchar();
while (c != EOF)
{
c=getchar();
x = tolower(c);
if (isupper(c))
{
putchar(x);
}
else
{
putchar(c);
}
}
system("Pause");
}
I believe the problem is that you do not want to go to the program and type in Input < input.txt. Instead, you want to open a terminal program, change directory into the directory containing the project, and then run the program from the command line by writing Input < input.txt. This starts up the program and uses the contents of input.txt as the standard input stream, rather than reading text from the console.
That said, there are two bugs in your code. First, note that you have the line
c = getchar();
outside of your loop that does the input reading. You then immediately call
c = getchar();
again inside the loop. This means that you are discarding the very first character that you read in.
Second, your loop runs one more time than it needs to. If the second call to getchar() returns EOF, you do not detect this until after the current loop iteration finishes. This is because your check for EOF is at the top of the loop, which isn't reached until after you've already printed out the EOF character. To fix this, consider using the loop-and-a-half idiom and breaking out of the loop in the middle:
for (;;) {
/* Read data. */
if (/* no data left */) break;
/* Process data. */
}
Stylistically, are you sure that you need both the if and else branches here? Recall that tolower will not change the values of characters that aren't upper-case, so having one case for upper-case letters and one for lower-case is redundant. You can just output the character produced by tolower without the special cases.
Hope this helps!
The idiomatic way of doing this for ASCII text only is:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main()
{
int c;
while((c = getchar()) != EOF)
putchar(tolower(c));
exit(EXIT_SUCCESS);
}
As textbooks are so fond of saying, UTF-8 is left as an easy exercise to the reader ;-)

Where does `getchar()` store the user input?

I've started reading "The C Programming Language" (K&R) and I have a doubt about the getchar() function.
For example this code:
#include <stdio.h>
main()
{
int c;
c = getchar();
putchar(c);
printf("\n");
}
Typing toomanychars + CTRL+D (EOF) prints just t. I think that's expected since it's the first character introduced.
But then this other piece of code:
#include <stdio.h>
main()
{
int c;
while((c = getchar()) != EOF)
putchar(c);
}
Typing toomanychars + CTRL+D (EOF) prints toomanychars.
My question is, why does this happens if I only have a single char variable? where are the rest of the characters stored?
EDIT:
Thanks to everyone for the answers, I start to get it now... only one catch:
The first program exits when given CTRL+D while the second prints the whole string and then waits for more user input. Why does it waits for another string and does not exit like the first?
getchar gets a single character from the standard input, which in this case is the keyboard buffer.
In the second example, the getchar function is in a while loop which continues until it encounters a EOF, so it will keep looping and retrieve a character (and print the character to screen) until the input becomes empty.
Successive calls to getchar will get successive characters which are coming from the input.
Oh, and don't feel bad for asking this question -- I was puzzled when I first encountered this issue as well.
It's treating the input stream like a file. It is as if you opened a file containing the text "toomanychars" and read or outputted it one character at a time.
In the first example, in the absence of a while loop, it's like you opened a file and read the first character, and then outputted it. However the second example will continue to read characters until it gets an end of file signal (ctrl+D in your case) just like if it were reading from a file on disk.
In reply to your updated question, what operating system are you using? I ran it on my Windows XP laptop and it worked fine. If I hit enter, it would print out what I had so far, make a new line, and then continue. (The getchar() function doesn't return until you press enter, which is when there is nothing in the input buffer when it's called). When I press CTRL+Z (EOF in Windows), the program terminates. Note that in Windows, the EOF must be on a line of its own to count as an EOF in the command prompt. I don't know if this behavior is mimicked in Linux, or whatever system you may be running.
Something here is buffered. e.g. the stdout FILE* which putchar writes to might be line.buffered. When the program ends(or encounters a newline) such a FILE* will be fflush()'ed and you'll see the output.
In some cases the actual terminal you're viewing might buffer the output until a newline, or until the terminal itself is instructed to flush it's buffer, which might be the case when the current foreground program exits sincei it wants to present a new prompt.
Now, what's likely to be the actual case here, is that's it's the input that is buffered(in addition to the output :-) ) When you press the keys it'll appear on your terminal window. However the terminal won't send those characters to your application, it will buffer it until you instruct it to be the end-of-input with Ctrl+D, and possibly a newline as well.
Here's another version to play around and ponder about:
int main() {
int c;
while((c = getchar()) != EOF) {
if(c != '\n')
putchar(c);
}
return 0;
}
Try feeding your program a sentence, and hit Enter. And do the same if you comment out
if(c != '\n') Maybe you can determine if your input, output or both are buffered in some way.
THis becomes more interesting if you run the above like:
./mytest | ./mytest
(As sidecomment, note that CTRD+D isn't a character, nor is it EOF. But on some systems it'll result closing the input stream which again will raise EOF to anyone attempting to read from the stream.)
Your first program only reads one character, prints it out, and exits. Your second program has a loop. It keeps reading characters one at a time and printing them out until it reads an EOF character. Only one character is stored at any given time.
You're only using the variable c to contain each character one at a time.
Once you've displayed the first char (t) using putchar(c), you forget about the value of c by assigning the next character (o) to the variable c, replacing the previous value (t).
the code is functionally equivalent to
main(){
int c;
c = getchar();
while(c != EOF) {
putchar(c);
c = getchar();
}
}
you might find this version easier to understand. the only reason to put the assignment in the conditional is to avoid having to type 'c=getchar()' twice.
For your updated question, in the first example, only one character is read. It never reaches the EOF. The program terminates because there is nothing for it to do after completing the printf instruction. It just reads one character. Prints it. Puts in a newline. And then terminates as it has nothing more to do. It doesn't read more than one character.
Whereas, in the second code, the getchar and putchar are present inside a while loop. In this, the program keeps on reading characters one by one (as it is made to do so by the loop) until reaches reaches the EOF character (^D). At that point, it matches c!=EOF and since the conditions is not satisfied, it comes out of the loop. Now there are no more statements to execute. So the program terminates at this point.
Hope this helps.

Resources