Counting characters via C book [duplicate] - c

This question already has answers here:
Why does program not execute final printf statement?
(2 answers)
Closed 6 years ago.
I've been trying to learn some C language via "The C Programming Language by BRIAN W KERNIGHAN & DENNIS M. RITCHIE", and I've got a question that I cannot understand.
Here's the deal, in section 1.5 (page 17) related to character counting of an input, here's my code:
#include <stdio.h>
int main()
{
double nc;
for (nc = 0; getchar() != EOF; ++nc);
printf("%0.f\n", nc);
}
This part:
printf("%0.f\n", nc);
Should print the actual character counter, right? The problem is that it gives me exactly nothing. I've been trying it via Code Blocks and also via terminal by doing "cc code.c", and all it does it just waits for me to put and input, and just nothing more.
Am I missing something here?
Thanks in advance,
Anoubis

You are trapped here getchar() != EOF if you only input random text input.
The program wait for EOF - End Of File
I copied your code into a.cand compiled it using gcc a.c -o a.out
If a run ./a.out I get the behaviour you describe until I hit Ctrl+D which corresponds to EOF in my terminal.
The program will print the number of chars received once it has received EOF.
Another way to use the code is to pipe another file to it.
Create a dummy file named blaha.txtand write something in it.
You can then pipe it to the program like this:
a.out < blaha.txt

Your program waits for input and consumes it until it reaches the end of file. You can signal the end of file from the terminal by typing a special character such as control-Z followed by enter on Windows and control-D on linux and MacOS.

Related

Why some code examples from The C Programming Language book don't work as expected?

I'm trying to learn C Language, and I'm reading and testing a lot about it, but sometimes is difficult to understand why somethings just don't work as expected. Why the example code showed on page 18 of The C Programming Language, Second Edition (Kernighan and Ritchie), don't work? It doesn't show any results for me.
#include <stdio.h>
main()
{
long nc;
nc = 0;
while (getchar() != EOF)
++nc;
printf ("%ld\n", nc);
}
It doesn't show anything because it's waiting for input.
If you're running this like ./the_executable, it'll always be reading your input because of getchar(). And it'll show the results only after the input stream ends.
You can cut it off manually by pressing Control+D. Or use the contents of a file as input:
./the_executable < test_file.txt
The C Programming Language, Second Edition by Brian Kernighan and Dennis Ritchie is a very good book, but it is quite old and refers to an outdated definition of the C language. The program you posted uses an obsolete syntax for main. It should be modified as:
#include <stdio.h>
int main() {
long nc;
nc = 0;
while (getchar() != EOF)
++nc;
printf("%ld\n", nc);
return 0;
}
As you can see, the difference is minimal and in this particular case, the above version would also compile with the pre-ansi compilers in use at the time the book was written.
The program reads bytes from the standard input and just counts how many it could read before reaching the end of file.
You should run this program from a terminal window and type some data and signal the end of file by pressing Ctrl and D on unix systems such as linux and OS/X or Ctrl and Z followed by Enter on Microsoft systems.
You can also redirect input from a file and will get the number of bytes in this file, possibly adjusted on Microsoft systems due to line ending conversion.
Running the program directly from an IDE is not demonstrative because IDE's usually do not keep the terminal window open when the program exits, preventing the user from seeing the final output.
It should indeed work as expected.
The reason why you are confusing it with not working because you are expecting printf to print something for you (value of nc), but the catch is there is another statement getchar() before printf which is reading standard input with the help of while loop until you input EOF which is entered by ^D (control + D) in unix, like cat command if you used on *nix or by redirecting input to your program from a file using < operator, like
./a.out < someFile.txt
You have to enter the "end of file" condition. So ctrl Z or ctrl C should work.

Why my little C game ignore player's first attempt? [duplicate]

This question already has answers here:
Why doesn't getchar() wait for me to press enter after scanf()?
(10 answers)
Closed 3 years ago.
I'm learning programmation in C and tried to create a program that asks the user his age. When the user writes his age (for example 18) he gets the message "So you're 18 years old". When I execute the .exe file it automatically closes after you see the message, so fast that you don't see it. Then I added getchar so that the user reads the message and then presses Enter to quite. Here's the program I wrote:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int age=0;
printf("How old are you?\n");
scanf("%d",&age);
printf("So you're %d years old", age);
getchar();
return 0;
}
Unfortunately, when I execute the .exe file, it still closes automatically like if the getchar() doesn't exist and I don't know why.
scanf("%d",&age);
When the execution of the program reaches the above line,you type an integer and press enter.
The integer is taken up by scanf and the \n( newline character or Enter )which you have pressed remains in the stdin which is taken up by the getchar().To get rid of it,replace your scanf with
scanf("%d%*c",&age);
The %*c tells scanf to scan a character and then discard it.In your case,%*c reads the newline character and discards it.
Another way would be to flush the stdin by using the following after the scanf in your code:
while ( (c = getchar()) != '\n' && c != EOF );
Note that c is an int in the above line
You're only having trouble seeing the result because you're starting the program from a windowing environment, and the window closes as soon as its internal tasks are completed. If you run the compiled program from a command line in a pre-existing shell window (Linux, Mac, or Windows), the results will stay on the screen after you're returned to the prompt (unless you've ended by executing a clear-screen of some sort). Even better, in that case, you don't need the extraneous getchar() call.
For Windows, after opening the command prompt window, you'd issue a "cd" command to change to the directory that contains the compiled program, and then type its name. For Linux (and, I presume, Mac, since Mac is UNIX under the hood), you'd need to type ./ ahead of the program name after changing to the appropriate directory with "cd".

Using control+D (EOF) but return an unexpected character D [duplicate]

This question already has answers here:
Simple program adding "D" to output
(3 answers)
Why does C program print 0D instead of 0? (When EOF sent as Ctrl+D) [duplicate]
(1 answer)
Closed 5 years ago.
I was coding a very simple programme to detect word pattern by entering to stdin and return the times found the pattern.
However the code return me the correct number but follow a char D.
#include <stdio.h>
#include "string.h"
#define MAXLINE 1000 /* maximum input line length */
char pattern[] = "ould"; /* pattern to search for */
/* print all lines from standard input that match pattern */
int main()
{
char line[MAXLINE];
int found = 0;
while (fgets(line, MAXLINE, stdin) != NULL)
if (strstr(line, pattern) != NULL) {
printf("%s", line);
found++;
}
printf("%d \n", found);
return 0;
}
Result:
glaroam2-180-76:Lab2 apple$ ./find0
fould
fould
1D
The code is correct (apart from the #include "string.h" which should be
#include <string.h>)1, the problem is that when you press
Ctrl+D on your terminal, your terminal might write
something on the terminal, which you cannot control and this output might be
^D
After fgets returns NULL, you do printf("%d \n", found); which prints the '1'.
But because there was ^D on the terminal, the ^ was replaced by the '1' and
you end up with:
1D
Change your last printf to this:
printf("\n\n%d \n, found);
And you might see only a '1' in the next lines of the output.
This has nothing to do with your C program, it's the behaviour of your terminal.
My terminal for example doesn't print when pressing Ctrl+D,
but when pressing Ctrl+C I get ^C. There's nothing you
can do.
edit
With There's nothing you can do I mean that you cannot control the way the
terminal from you C program without calling external tools like stty. While
this might solve your problem, you are loosing portability.
However, before you start you program, you can configure your terminal using a
program like stty. See Jonathan Leffler's answer for more info on that.
Fotenotes
1As Jonathan Leffler points out in the comments, using quotes instead
of angle brackets for system headers is not an error per se. For example my GCC
compiler searches in the same directory of the compiled file for headers that
were included with quotes. But in general, it's a good practice to include the
header files included provided by your system with angle brackets.
It's a terminal setting: echoctl. It means that when you type Control-D, the terminal echoes ^D, and then the 1 overwrites the ^. Try using:
stty -echoctl
and then rerunning your program.
With that said, I'm surprised that the D isn't wiped out by the blank after the %d in the format string. I suspect your actual code may be missing that. When I tested on my Mac, the program with the space after the %d did not show the D for long enough for me to spot it; when I removed that space, I got the output shown in the question.

execute after EOF in C

I'm doing homework for my C programming class. The question states "Write a program which reads input as a stream of characters until encountering EOF". I'm using Xcode on my macbook and the only way I know to make the program encounter EOF is using ctrl + D or ctrl + Z. But it will exit my program completely.
For example I have this code:
int main()
{
int ch;
while ((ch = getchar()) != EOF)
{
putchar(ch);
}
printf("%d",ch);
return 0;
}
Is there away for the code to execute the printf("%d",ch) after the loop (after i hit ctrl + D on my keyboard)?
You can test your program using (with a POSIX shell) here documents.
First compile your source code mycode.c into a binary mybin with
gcc -std=c99 -Wall -Wextra -g mycode.c -o mybin
(it could be clang or cc instead of gcc)
then run mybin with a "here document" like
./mybin << EOF
here is my
input
EOF
You could also use input redirection. Make some file myfile.txt and run ./mybin < myfile.txt
You could even run your program on its own source code: ./mybin < mycode.c
And the input could even come from some pipe, e.g. ls * | ./mybin
BTW, what you are observing is that stdin, when it is a terminal, is line-buffered. See this answer (most of it should apply to MacOSX).
Notice that your code is incorrect: you are missing an #include <stdio.h> near the top of the file, and your main should really be int main(int argc, char**argv) (BTW you could improve your program so that when arguments are given, they are file names to be read). At last the ending printf would surely show -1 which is generally the value of EOF
Also, it is much better to end your printf format control string with \n or else use appropriately fflush(3)
Notice that end-of-file is not an input (or a valid char), it is a condition on some input file stream like stdin, and the getchar(3) function is specified to return EOF which is an int outside of the range of char (on my Linux system EOF is -1 because char-s are between 0 and 255 included). You might test end-of-file condition after some input operation (never before!) using feof(3)
A terminal in usual cooked mode is handled by the kernel so that when you press Ctrl D an end-of-file condition is triggered on the file descriptor (often STDIN_FILENO i.e. 0) related to that terminal.
I'm using Xcode on my macbook and the only way I know to make the program encounter EOF is using ctrl + D or ctrl + Z. But it will exit my program completely.
No it won't. If you run your program in the Xcode debugger, provided the console pane has the focus, all input you type will go to your program (note that, by default, stdin is line buffered, so you'll only see output when you press the return key). If you hit control-d (not control-z), you're program will exit the loop and print -1 in the console window (which is what you expect because that is the value of EOF in OS X).
Here is the result when I ran your program without change in the Xcode debugger (I typed command-r in Xcode)
bgbgdfsfd
bgbgdfsfd
hgfdgf
hgfdgf
-1
Regular font was typed by me, bold font was from your program. At the end of each of the lines typed by me, I pressed carriage return. After your program printed hgfdgf I typed control-D. Your program then printed the value of the last thing it got from getchar() which was EOF which is -1 in the OS X C library.
Edit
If you are unsure that your program is printing the EOF, change your printf format string to (for example)
printf("Last character is [%d]\n", ch);
Then instead of -1 your program will output Last character is [-1] on the last line.
First of all ctrl+z does not input EOF to your program. If you hit ctrl+Z your shell will put your program to sleep.
Second, if you want to handle these ctrl+Z in your program you need to learn about signal handling in C.
And I think because you were hitting ctrl+Z you were not seeing any output on the screen.
Make sure you are sending the EOF signal, not a signal that actually terminates your program.
For example, for c program running in windows the EOF is represent by typing ctrl+z and pressing enter. Doing this will exit your while loop but still runs the rest of your program.
However, ctrl+c, which some people may have mistakenly tried for EOF, actually kills your program and will prevent the code behind your while loop from executing.
For mac you will need to find what is the input that corresponds to EOF, and make sure that is what you are sending through rather than the kill signal, which I suspect is what you are doing here.

getchar not taken in consideration after scanf [duplicate]

This question already has answers here:
Why doesn't getchar() wait for me to press enter after scanf()?
(10 answers)
Closed 3 years ago.
I'm learning programmation in C and tried to create a program that asks the user his age. When the user writes his age (for example 18) he gets the message "So you're 18 years old". When I execute the .exe file it automatically closes after you see the message, so fast that you don't see it. Then I added getchar so that the user reads the message and then presses Enter to quite. Here's the program I wrote:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int age=0;
printf("How old are you?\n");
scanf("%d",&age);
printf("So you're %d years old", age);
getchar();
return 0;
}
Unfortunately, when I execute the .exe file, it still closes automatically like if the getchar() doesn't exist and I don't know why.
scanf("%d",&age);
When the execution of the program reaches the above line,you type an integer and press enter.
The integer is taken up by scanf and the \n( newline character or Enter )which you have pressed remains in the stdin which is taken up by the getchar().To get rid of it,replace your scanf with
scanf("%d%*c",&age);
The %*c tells scanf to scan a character and then discard it.In your case,%*c reads the newline character and discards it.
Another way would be to flush the stdin by using the following after the scanf in your code:
while ( (c = getchar()) != '\n' && c != EOF );
Note that c is an int in the above line
You're only having trouble seeing the result because you're starting the program from a windowing environment, and the window closes as soon as its internal tasks are completed. If you run the compiled program from a command line in a pre-existing shell window (Linux, Mac, or Windows), the results will stay on the screen after you're returned to the prompt (unless you've ended by executing a clear-screen of some sort). Even better, in that case, you don't need the extraneous getchar() call.
For Windows, after opening the command prompt window, you'd issue a "cd" command to change to the directory that contains the compiled program, and then type its name. For Linux (and, I presume, Mac, since Mac is UNIX under the hood), you'd need to type ./ ahead of the program name after changing to the appropriate directory with "cd".

Resources