C beginner for-loop output issue - c

I am new to C (self-learning).
When I execute this for-loop function when I type 'hello' the output will be 012345. However it skips to last print function outside of the for-loop?
int main() {
int c;
for (c = 0; getchar() != EOF; ++c) {
printf("%d\n", c);
}
printf("%d\n", c);
return 0;
}
The output:
hello
0
1
2
3
4
5

"When I execute this for-loop function and I type 'hello' the output will be 012345".
What do you expect else? c just get incremented by each iteration, starting at 0.
"However it skips to the last print function outside of the for-loop?"
No, it doesn´t. In fact, It isn´t even out of the for loop. The newline made by the press to Enter doesn´t let you break out of the loop; only a signalized EOF is doing that.
So, the program isn´t even terminated. It stucks in the loop.
You need to signalize EOF with CTRL + D on Linux or CTRL + Z on Windows to break out of the loop.

No it is not skipping anything.
Note: you are printing c which is integer (not character, if that is what you want). So, input "hello" has 5 characters: so, output is:
0
1
2
3
4
Then, as there is newline character '\n' as you pressed enter (there is your output 5). However, you loop never exits, unless you force program to do so (I mean, interrupting with Ctrl +C). If you, test again your code, and input data even after "hello", you will see that, you are still in the loop.

Change your program to this:
#include <stdio.h>
int main() {
int c;
int ch;
for (c = 0; (ch = getchar()) != EOF; ++c) {
printf("%d %d\n", c, ch);
}
printf("%d %d\n", c, ch);
return 0;
}
Now you should understand yourself what happens.

The while loop doesn't end when you type hello and presses Enter, because getchar() still won't be equal to EOF. So the loop will continue with getchar() waiting to read new characters.
You need to press Ctrl+Z on Windows' cmd.exe, or Ctrl+D on Linux's terminal, to proceed with the execution of the program without writing any character to the input, then getchar will fail to read a character and return EOF, finally exiting the loop. Once it is out of the loop the final printf call will be made before ending the program.
Alternatively you could change the condition to make the loop end when getchar reads a new line character \n, instead of when it fails to read a character, so that the loop will end after you press Enter:
int main() {
int c;
for (c = 0; getchar() != '\n'; ++c) {
printf("%d\n", c);
}
printf("%d\n", c);
return 0;
}

I see what you're tryng to do, but first of all i'd declare "c" as a char , this way you're doing an implicit cast to char, which is allowed in C language, but should be avoided.
My best guess would be that you'r compiler (i suppose mingw on windows) is not telling you what's going on exactly, try this:
When you build (compile) something outside linux for C language do as follows :
" gcc -o nameoftheexecutable file.c -Wall " and to execute it " ./nameoftheexecutable
That -Wall will print out all warnings to the console, including EOF warnings.
By doing this, and understanding what IDE or Environment are you programming in, we can help you out.

Related

Why is return 0 not working in this case? [duplicate]

This question already has answers here:
How to enter the value of EOF in the terminal
(4 answers)
Closed 2 years ago.
I recently started learning C from The C Programming Language by Brian Kernighan and Dennis Ritchie. In that book, there's a whole subsection (1.5.1, 2nd Ed.) where the authors create a file copying program (but I am using this as a text (input by the user) copying program). Their code basically looks like this
#include <stdio.h>
int main()
{
int c;
c = getchar();
while (c != EOF) {
putchar(c);
c = getchar();
}
}
This code works fine when run, but the program never stops. The program keeps on waiting for inputs and goes on copying them, endlessly, never terminating. Now I wanted to create a program where this endless copying does terminate. To do so, I tweaked the code a little bit. Here's my code
#include <stdio.h>
int main()
{
int c;
c = getchar();
while (c != EOF) {
putchar(c);
c = getchar();
}
return 0;
}
I thought that explicitly writing return 0; at the end might do the job, but it seems that the output doesn't change at all. I also tried using if-else conditions and looping them as follows
#include <stdio.h>
int main()
{
int c;
c = getchar();
while (1) {
if (c != EOF){
putchar(c);
c = getchar();
}
else
return 0;
}
}
But the program didn't change at all in this case as well.
My question is that how do I change the code so that my program ends just after copying once (or, even better, generalising it to copying n times)?
Here, it is important for me to clarify what I mean by "once" (or "n times" for that matter). When I use the command prompt (I use Windows) to run the compiled file, the program expects an input. I enter the input through my keyboard, and then press Enter to see the reproduced input. After this, the program again expects me to enter some input. I don't want this to happen. I want the program to end by itself after it copies my input once. This is what I mean by "once" (and the above definition can easily be extended for "n times" as well).
#anatolyg and #Jabberwocky have suggested the use of \n (new line escape character) to make the program work. But this solution fails when the input contains linebreaks, for example
my code does
not work so
I am asking
for help here
Copying this into the command prompt as the input, and using the program suggested by the above two users yields only my code does as the output, which is not what I wanted as an output. Is there any way I can make this program work for text blocks with linebreaks and also make it stop after one input (in this case, the whole text block is just one input)?
After interacting with the other people here, I have come to realise that my definition of "one input" or "once" is quite vague, unclear and not at all concrete. Thus it is nothing but expected that C cannot do what I want it to do. I am accepting the answer which suggests to use the new-line escape character as a signal to terminate the program, because that is the closest to what I had in my mind. Thank you all.
Your return 0 won't make any difference as the execution will stay in the while until c becomes EOF. So you need to make c equal to EOF. Try ctrl-D or ctrl-Z depending on OS.
My question is that how do I change the code so that my program ends just after copying once (or, even better, generalising it to copying n times)?
Introduce a counter like:
#define MAX_INPUTS 10
...
int cnt = 1;
while (c != EOF && cnt < MAX_INPUTS) {
putchar(c);
c = getchar();
++cnt;
}
For starters this loop
while (c != EOF) {
putchar(c);
c = getchar();
}
is not endless. There is a condition in the while loop that if it is not satisfied the loop terminates.
To generate the output of the function getchar equal to EOF you should enter the key combination Ctrl + c in Windows or Ctrl + d in an Unix system.
Adding a return statement either in the body of the loop or after the loop does not principally influence on the program control flow.
Pay attention to that the return statement in main may be omitted. From the C Standard (5.1.2.2.3 Program termination)
1 If the return type of the main function is a type compatible with
int, a return from the initial call to the main function is equivalent
to calling the exit function with the value returned by the main
function as its argument;11) reaching the } that terminates the main
function returns a value of 0.
So for example these two programs
int main( void )
{
return 0;
}
and
int main( void )
{
}
are valid and equivalent.
Since you want to read only one line of input, you can terminate the loop on the end-of-line character '\n'.
c = getchar();
while (c != '\n') {
putchar(c);
c = getchar();
}
If you use a Windows terminal to enter data to your program, this will be enough. If you redirect the input to your program, so that it comes from a file, it will read the file up to the first newline character. However, if the file contains no newline character, your program will get EOF at end of file. So the terminating condition should also check for EOF.
c = getchar();
while (c != '\n' && c != EOF) {
putchar(c);
c = getchar();
}
If you want to read the first n lines from the file/terminal, you need a counter. Then your code will become a bit more complicated, and I think an endless loop with exits in the middle would be a better implementation.
int line_counter = 0;
int max_lines = 5;
while (1) {
int c = getchar();
if (c == EOF)
break;
putchar(c);
if (c == '\n')
{
++line_counter;
if (line_counter == max_lines)
break;
}
}
Another method for separating between inputs is with an empty line. This redefines input format to have "paragraphs" of text. This will complicate the code a little more - it should also hold the previous character it read. To detect an empty line, which marks the end of a paragraph: if both previous and current character are end-of-line characters, the paragraph of text has just ended.
int record_counter = 0;
int max_records = 5;
int prev_c = '\n';
while (1) {
int c = getchar();
if (c == EOF)
break;
putchar(c);
if (prev_c == '\n' && c == '\n')
{
++record_counter;
if (record_counter == max_records)
break;
}
prev_c = c;
}
Ypur latest edit suggests you might want something like this:
#include <stdio.h>
int main()
{
int c;
c = getchar();
while (1) {
if (c != EOF && c != '\n') { // '\n' is End of line (Enter)
putchar(c);
c = getchar();
}
else
return 0;
}
}
or simpler:
int main()
{
do
{
int c = getchar();
if (c != EOF && c != '\n') { // '\n' is End of line (Enter)
putchar(c);
}
else
{
return 0;
}
} while (1);
}
This code works fine when run, but the program never stops.
This is not true, if you don't satisfy the condition of the while statement:
while (c != EOF)
the program will terminate.
Now how you can send EOF to the input?
Depends. Which stdin operation are you trying to EOF? If stdin is terminalinput just press control-D. If the ONLY thing you want to send is EOF, use echo -n | (your program). If you are sending it FROM your C program, you are pretty much stuck with exiting from the program, at which point the state of its stdout will be EOF, which will in turn be reflected in whichever stdin it was redirected to. I'm pretty sure you can't just send EOF from within C without getting a hold of an underlying buffer, which aren't standardized, and therefore would leave you with some dirty programming to do.
Another solution is check in or some digitable character in the while condition for example:
#include <stdio.h>
int main()
{
int c;
c = getchar();
while (c != EOF && c!= 'A') {
putchar(c);
c = getchar();
}
}
in this case if you digit "A" the program will ends up.
The function getChar() in this case is always waiting for the new character, and in this case c is never to get the EOF value. You can set a character to finish (for example 'e' to exit) or you can count with a counter as you say to exit the loop. Do not use while(1) because is not a good practise.

C, why does printf add a "D" after a single digit long?

I'm working through the K&R C book and one of the example programs is this:
#include <stdio.h>
int main() {
long nc;
nc = 0;
while (getchar() != EOF) {
++nc;
}
printf("%ld", nc);
return 0;
}
When I run this program, it mostly behaves as I expect. So for an input like This is a sentence, it prints 19.
However, if I input anything under 10 characters (including EOF), there is a capital D appended to the output number.
E.g. for input hello, the output is 6D.
Why is there a D appended to an integer value and what does it mean?
Note: This occurs with cc, gcc and clang.
It turns out that D is part of the ^D that gets printed to the console when I input an EOF (control + D on Unix). Because there is no \n at the start of the printf statement, a single-digit number will overwrite the ^, while a double-digit number will overwrite the entire ^D, which is what gave the impression of some weird behaviour.
What version of gcc are you using? I ran the exact same code using gcc and it runs fine. Maybe it's an artifact left over by your terminal where it's trying to print the Ctrl-D for end of file

putchar and printf not behaving as expected

I'm working through some of the exercises in K&R. Exercise 1-6 asks for verification that the expression getchar() != EOF is either 0 or 1. I understand why it is, but the code I wrote to prove it didn't work as expected. I wrote the following two snippets:
Version 1:
int main(void)
{
int c;
while (c = getchar() != EOF)
{
putchar(c);
}
printf("%d at EOF\n", c);
return 0;
}
Version 2:
int main(void)
{
int c;
while (c = getchar() != EOF)
{
printf("%d\n", c);
}
printf("%d at EOF\n", c);
return 0;
}
My questions:
When I type in a character and hit enter with version one, why do I not see either a 0 or 1 on the screen? Instead, my cursor moves to the first position on next line, which is otherwise empty. I though putchar would send c to stdout.
While the use of printf in the second version does produce a 0 or 1 appropriately, it duplicates the 1 for each non-EOF character (I see the number 1 on two consecutive lines for each character I input). Why?
Many thanks in advance for your thoughts. If there is a reference that you think would help, please send a link.
CLARIFICATION:
I know I'm assigning c a value of either 0 or 1. That's what I want to do, and it's what the exercise wants. That's also why I don't have parentheses around c = getchar(). My question deals more with understanding why the output isn't what I had expected. Sorry for any confusion.
The assignment operator = has lower precedence than the inequality operator !=.
So this:
while (c = getchar() != EOF)
Is parsed as:
while (c = (getchar() != EOF))
So then c is assigned the boolean value 1 if getchar is not EOF and 0 if it does return EOF.
As a result, the first program print the character for the ASCII code 1, which is a non-printable character. That's why you don't see anything. The second program, using the %d format specifier to printf, converts the number 1 to its string representation.
You need parenthesis to have the result of getchar assigned to c:
while ((c = getchar()) != EOF)
EDIT:
To further clarify the output you're getting, in both programs the variable c has the value 1 inside of each while loop. The difference here is that putchar is printing the character with the ASCII value of 1 (an unprintable character), while printf with %d print the textual representation of the value 1, i.e. 1.
If you changed the printf call to this:
printf("%c", c);
You would get the same output as using putchar.
As for the printing of 1 twice for each character, that is because you're actually entering two characters: the key you press, plus the enter key. When reading from the console, the getchar function doesn't return until the enter key is pressed.

EOF behavior when accompanied by other values

*Note: I'm using windows, so EOF is ctrl + Z for me.
For a while I've noticed an EOF input seems to behave differently in isolation than it does when accompanied by other input. For example, ^Z (the EOF command for windows in command prompt) and a^Z seem to cause different behavior in the following code:
#include <stdio.h>
#define MAX 1000
int getline(char s[]);
main() {
int line;
char arr[MAX];
while( (line = getline(arr)) != EOF)
printf("%s",arr);
system("Pause");
return 0;
}
int getline(char s[])
{
int c, i = 0;
while ((c = getchar()) != EOF && c != '\n') {
s[i++] = c;
}
if (c == '\n') {
s[i++] = c;
}
else
return EOF;
s[i] = '\0';
return 1;
}
If I input ^Z + enter in the command prompt, the program predictably jumps to system("Pause"); However, if I input abc^Z + enter, nothing happens, as though EOF was ignored and a '\n' command was never received. If, at this point, I press enter again, it shows the following:
I've been tinkering with and debugging this code and small variations of it for over an hour now and can't seem to find anything wrong with it. In theory, if I input abc^Z + enter, I expect the input to be interpreted as abcEOF\n, which would give:
s[0] = 'a'
s[1] = 'b'
s[2] = 'c'
i = 3 when loop breaks from c = EOF
if (c == '\n') skipped since c = EOF
leads to else -> return EOF
in main(), line = EOF since that is what the function getline returned
while loop breaks because of above
system("Pause"); follows
Is there something wrong with my code that I'm overlooking or is there some quirk to EOF or command prompt that I should be aware of? I'm almost certain this isn't the only instance where mixing ^Z with other values caused unintended behavior.
Don't think of CTRL-Z as the end-of-file character, there is actually a real character with code point 26 (which is what you'd normally expect CTRL-Z to generate).
Instead, think of CTRL-Z as a way for your terminal device to indicate the end of the input stream to your program. If you were to read a real file of the disk and it contained CTRL-Z, it should keep going (though that may not be the case in certain implementations where you, for example, open it with the mode r instead of rb).
In Windows, that translation of CTRL-Z to the end-stream operation only happens when it appears at the start of the line which is why you're not getting EOF when you enter abcCTRL-Z.
When you enter CTRL-Z on a character position that isn't the start of the line, it's treated as a real CTRL-Z, not a stream-closing operation. That's why you're getting that → character, which is the printable character at code point 26.
It is the normal behaviour of getchar..
getchar() is a standard function and requires you to press *ENTER* to get the input
Many compilers/platforms support the non-standard getch() that does not require ENTER.
EOF is not a character. The EOF is a macro that getchar() returns when it reaches the end of input or encounters some kind of error

getchar() function bypasses one loop

I have this program and I want it to increment by one and print the value of my counter each time I give a character
#include <stdio.h>
int main(void){
//Declarations
long nc;
//Instantiations
nc = 0;
while (getchar() != EOF){
++nc;
printf("%ld\n", nc);
}
return 0;
}
When the loop initiates if I press ENTER I get 1,2,3,4,5... which is ok.But if I type a character or something else it prints the next two numbers 12,34,56,78. Why is that happening??
I am running the program on gcc 4.6.3 Ubuntu 12.04 release.
Terminal input is normally line buffered. Your program only gets input to process when you press ENTER. If you type several characters, you will get one line of output for each character you input (plus the newline itself) as getchar() returns each character in sequence.

Resources