I have a very simple C example program that does a crude count of characters words and spaces from input. The program compiles without error but when tested the program doesn't return any of the int variables via the print function. I am using VS2012 for coding and compiling. Stepping into the code shows that the values are being calculated correctly. Is there something wrong with my code or the compiler?
#include <stdio.h>
#define IN 1
#define OUT 0
/* count digits, white space, others */
main()
{
int c, nl, nw, nc, state;
state = OUT;
nl = nw = nc = 0;
while ((c = getchar()) != EOF){
++nc;
if(c == '\n'){
++nl;
}
if (c == ' ' || c == '\n' || c == '\t'){
state = OUT;
} else if (state == OUT){
state = IN;
++nw;
}
}
printf("%d %d %d\n", nl, nw, nc);
}
It works if you run it with stdin coming from a file a.exe < test.txt. It works if you run it with stdin coming from the console on Linux. It does not work if you run it with stdin coming from the console on Windows.
It must be some sort of Windows console oddity.
In order to see the actual output, start the debugger with Ctrl-F5. This will keep the console window open.
See this answer for more information.
Your loop is permanent. Meaning it doesn't end.. so it doesn't reach the call of printf.
EOF is indicator that clearly doesn't work like that here. You must break the loop on a specific key. Like enter for instance, which character decimal representation is 13 for carriage return. 10 for NL.
Related
Beginner here.
In the ANSI C textbook by K&R, page 20, they ask: How would you test the word count program?
I have copied exactly from the text book, using the CodeBlocks IDE, console application. I have seen many great input tests online, but my question is even dumber. How do I actually input something? Nothing happens when I press enter. Do I have this problem because I am using an IDE and therefore not learning how to run C programs properly?
Thanks in advance. I added a picture to show you what I mean
Here is the code:
#include <stdio.h>
#define IN 1 /* inside a word */
#define OUT 0 /* outside a word */
/* counts lines, words and characters as input */
main()
{
int c, nl, nw, nc, state;
state = OUT;
/* set these three constants to 0: */
nl = nw = nc = 0;
while ((c = getchar()) != EOF){
++nc;
if (c == '\n')
++nl;
/* || == OR (&& == AND)
evaluation of the following line
will stop as soon as the truth or
falsehood is known, so the order matters */
if (c == ' ' || c == '\n' == c == '\t')
state = OUT;
else if (state == OUT){
state = IN;
++nw;
}
}
printf("%d %d %d\n", nl, nw, nc);
}
On MacOS:
gcc kr_wc.c -o kr_wc
./kr_wc < example_text.txt
Example output:
40 260 1397
Where example_text.txt is this file:
1.5.4 Word Counting
The fourth in our series of useful programs counts lines, words, and
characters, with the loose definition that a word is any sequence of
characters that does not contain a blank, tab or newline. This is a
bare-bones version of the UNIX program wc.
#include <stdio.h>
#define IN 1 /* inside a word */
#define OUT 0 /* outside a word */
/* count lines, words, and characters in input */
int main() {
int c, nl, nw, nc, state;
state = OUT;
nl = nw = nc = 0;
while ((c = getchar()) != EOF) {
++nc;
if (c == '\n')
++nl;
if (c == ' ' || c == '\n' || c == '\t')
state = OUT;
else if (state == OUT) {
state = IN;
++nw;
}
}
printf("%d %d %d\n", nl, nw, nc);
}
Every time the program encounters the first character of a word, it
counts one more word. The variable state records whether the program
is currently in a word or not; initially it is "not in a word", which
is assigned the value OUT. We prefer the symbolic constants IN and
OUT to the literal values 1 and 0 because they make the program more
readable. In a program as tiny as this, it makes little difference,
but in larger programs, the increase in clarity is well worth the
modest extra effort to write it this way from the beginning. You'll
also find that it's easier to make extensive changes in programs
where magic numbers appear only as symbolic constants.
The program to count words in K&R 2nd edition is made to run on an environment in which you signal the end of input somehow. Normally, as they used UNIX all the time, they used Ctrl-D sequence (which is valid if you run the program in Linux or any Unix-like operating system) This has been so since the early beginning of the UNIX system.
Windows signals the end of input in a console application by the input of a Ctrl-Z (probably followed by a keyboard return key)
If you redirect the input from a file (as when you say a.out <my_input_file.txt) you'll get the number of words at the end, when there's no more input in the file.
You are running the program in an IDE, which is something that normally hides you where standard input and standard output go, or how to signal the window you show how to say that there's not more input to the program.
For the program to get to it's end, you have first to know how to get to an end on input.
The examples in K&R omit a return type of main, which is not valid in modern C, so add int before main():
#include <stdio.h>
#define IN 1 /* inside a word */
#define OUT 0 /* outside a word */
/* counts lines, words and characters as input */
int main()
{
int c, nl, nw, nc, state;
state = OUT;
/* set these three constants to 0: */
nl = nw = nc = 0;
while ((c = getchar()) != EOF){
++nc;
if (c == '\n')
++nl;
/* || == OR (&& == AND)
evaluation of the following line
will stop as soon as the truth or
falsehood is known, so the order matters */
if (c == ' ' || c == '\n' == c == '\t')
state = OUT;
else if (state == OUT){
state = IN;
++nw;
}
}
printf("%d %d %d\n", nl, nw, nc);
}
"How do I actually input something? Nothing happens when I press enter."
If you got problems with your IDE just run it online.
"How would you test the word count program"?
To cite the authors of a bundle of K&R solutions with an answer to that particular question here:
It sounds like they are really trying to get the programmers to learn how to do a unit test. I would submit the following:
input file contains zero words
input file contains 1 enormous word without any newlines
input file contains all white space without newlines
input file contains 66000 newlines
input file contains word/{huge sequence of whitespace of different >kinds}/word
input file contains 66000 single letter words, 66 to the line
input file contains 66000 words without any newlines
input file is /usr/dict contents (or equivalent)
input file is full collection of moby words
input file is binary (e.g. its own executable)
input file is /dev/null (or equivalent)
66000 is chosen to check for integral overflow on small integer machines.
I am currently working through K&R for C. In section 1.5, we basically create a program for word count. The code is as follows,
#include <stdio.h>
#define IN 1
#define OUT 0
int main()
{
int c;
long int nl, nc, nw;
int state;
nl = nw = nc = 0;
state = OUT;
while((c = getchar())!= EOF){
++nc;
if (c == '\n'){
++nl;
}
if (c == ' '||c == '\n'|| c == '\t'){
state = OUT;
} else if (state == OUT){
state = IN;
++nw;
}
}
printf("\n%ld %ld %ld\n", nl, nc, nw);
}
When I compile this program with gcc and open the executable and type something such as
Hello
World
I get output
1 11 2
Which makes sense as we have 1 '\n' newline characters, 11 characters (including newline), and 2 word. What is interesting is when I do
vim hello.txt
and type
Hello
World
and then issue the command
cat hello.txt|./a.out
I get the following output
2 12 2
Why are the outputs from this different from before because all I am doing is streaming the file into the executable so I do not understand what is different. Please do explain.
Thank You.
Not your program's feature, but Vim's. See: What does the noeol indicator at the bottom of a vim edit session mean?
Vim automatically appends a newline at the end of file if there isn't when saving.
Type
:set noeol
in Vim and save the file again, then your program will output 11 as the second number.
P.S. It's redundant to use cat something | program, just program < something is enough.
After you type the charactors into the file and save it, at the end of the file, a 0x0a is added to the end of the file automaticly
I have encountered something I don't have a clear grasp on. I am having trouble reading the delete input from my MacBook Air. I am writing a program in c to read the input, and have used the following escape sequence character:
c = '127'
I can set the variable c to the decimal value of 8, which from my understanding is the backspace escape sequence. And also in Terminal>Preferences>Advanced, I check the box that enables delete to send Control-H.
Once I do the mentioned things above, I can read the input setting c variable as the following:
c = '8'
Here is my code to attempt to read the delete key from my MacBook
Air:
#include <stdio.h>
main() {
/* Copy program input to program output,
replacing each tab by \t,
each backspace by \b,
and each backslas by \\.
This makes tabs and backspaces visible in an unambiguous way.
*/
int c; // a variable for a character
while((c = getchar()) != EOF) {
if (c == '\t')
printf("\\t");
// check box found in:
// Terminal>Preferences>Advanced>Delete sends Control-H
// default setting DOES NOT send Control-H
// The Delete key does not appear to work with the ascii decimal character value 127.
if (c == '\127')
printf("Print to the screen if Delete key is detected.");
if (c == '\\')
printf("\\\\");
if (c != '\t')
if (c != '\b')
if (c != '\\')
putchar(c);
}
}
Try the following code and see what happens:
#include <stdio.h>
#include <stdlib.h>
int
main() {
int c;
system("stty raw -echo");
while (1) {
c = getchar();
if (c == 3) break; // exits when Ctrl-C is pressed
printf("pressed code: %d\r\n", c);
}
system("stty -raw echo");
return 0;
}
Hope this helps.
The reason that you can't read it is that it is not actually there. Using the delete code to delete characters is inefficient, so most programs actually delete the character instead of adding a delete character in order to hide the previous character.
I'm a beginner in C and I bought the book "The C programming language" and started reading and doing everything it says. There is a code in the book which should print out the number of lines,words and characters of a sentence. This is the code of the book.
#include <stdio.h>
#define IN 1 /* inside a word */
#define OUT 0 /* outside a word */
/* count lines, words, and characters in input */
main()
{
int c, nl, nw, nc, state;
state = OUT;
nl = nw = nc = 0;
while ((c = getchar()) != EOF) {
++nc;
if (c == '\n')
++nl;
if (c == ' ' || c == '\n' || c = '\t')
state = OUT;
else if (state == OUT) {
state = IN;
++nw;
}
}
printf("%d %d %d\n", nl, nw, nc);
}
For some reason the values that should be printed out with the printf aren't shown. I really don't know what is wrong. It only prints out numbers if I put the printf in the while loop but this can't be right because it prints the numbers every time the values change.
You have a typo in this line -- the assignment of c = '\t' always evaluates to true
if (c == ' ' || c == '\n' || c = '\t')
To fix, change = to ==
if (c == ' ' || c == '\n' || c == '\t')
To answer your question why does it not print anything out -- I think that the compiler is either giving your an error or warning causing the program not being linked, and hence you are not actually compiling the source code as listed, but rather you are running an old version of whatever code you compiled before.
gcc gives a compile error on this line:
if (c == ' ' || c == '\n' || c = '\t')
looking # that line, it's easy to spot a typo: c = '\t')
missing an equality test, no?
:)
It looks like you are reading your input from STDIN (the keyboard) and leave the loop only on "End of file", which will not happen. Do as the other answer suggests.
Besides the typo others have mentioned, you need to send an End-Of-File signal to end the input loop. This will depend on the environment you are running it - will be Ctrl+Z in Windows, and should be Ctrl+D in *NIX environments. I needed to enter this on a new line and press Enter afterwards when using my usual IDE (Code::Blocks).
Remember too that at the time K&R (1 & 2) was written, command line programming was the norm, and typically you would expect the output to be visible if you just ended the program. Some IDEs will close their terminal emulator at the end of the program before you can view the results, so you may need to add something like
printf("\nPress return to continue");
getchar();
at the end of the program. Or, run it yourself from the OS terminal emulator (using cmd.exe on Windows, or gnome-terminal, yakuake, or whatever your OS provides). Navigate to the folder and
your_executable.exe
or
./your_executable
it was a equality issue as pointed above in if (c == ' ' || c == '\n' || c = '\t').
I would suggest you use a good IDE like Eclipse CDT which warns you of such bugs .
Right now I am going through a book on C and have come across an example in the book which I cannot get to work.
#include <stdio.h>
#define IN 1
#define OUT 0
main()
{
int c, nl, nw, nc, state;
state = OUT;
nl = nw = nc = 0;
while ((c = getchar()) != EOF) {
++nc;
if (c == '\n')
++nl;
if (c == ' ' || c == '\n' || c == '\t')
state = OUT;
else if (state == OUT) {
state = IN;
++nw;
}
}
printf("%d %d %d\n", nl, nw, nc);
}
It's supposed to count the number of lines, words, and characters within an input. However, when I run it in the terminal it appears to do nothing. Am I missing something or is there a problem with this code?
The program only terminates when the input ends (getchar returns EOF). When running on terminal, this normally never happens and because of this it seems that the program is stuck. You need to close the input manually by pressing Ctrl+D (possibly twice) on Linux or pressing F6 and Enter at the beginning of the line on Windows (different systems may use different means for this).
It's waiting for input on stdin. Either redirect a file into it (myprog < test.txt) or type out the data and hit Ctrl-D (*nix) or Ctrl-Z (Windows).
When you run it, you need to type in your text, press return, then type Ctrl-d and return (nothing else on the line) to signify end-of-file. Seems to work fine with my simple test.
What it is doing is entering a loop for input. If you enter a character or newline, nothing happens on the screen. You need to interrupt the process (on my Mac this is CTRL+D) which serves as EOF. Then, you will get the result.
getchar() returns the input from the standard input. Start typing the text for which you want to have the word count and line count. Your input terminates when EOF is reached, which you do by hitting CTRL D.
CTRL D in this case acts as an End Of Transmission character.
cheers
I usually handle this kind of input like this (for Linux):
1. make a file (for example, named "input.txt"), type your input and save
2. use a pipe to send the text to your application (here assume your application named "a.out" and in the current directory):
cat input.txt | ./a.out
you'll see the program running correctly.