count tabs in C (fails) - c

So, I'm supposed to be creating a program in C to count: "blanks, tabs, and spaces". My code is provided below (including comments). you'll see that I have commented the areas of the code that is tasked with counting, and displaying the count of, tabs.
As it stands, the program counts "Blanks" and "Lines" accurately, but "Tabs" always results in "0". I've combed over the tiny code again and again looking for typoes or something, but have found no reason why '\t' fails to be counted. Then I came here and read through a few posts dealing with this same challenge. Thus far, I have found nothing anywhere which would shed any light on the problem I am experiencing with my code.
please, look it over, compile it, and test it out yourself to verify.
If anyone can tell me where my mistake is, that is causing my code not to count "Tabs" (as desired), that would be fantastic.
thank you.
#include <stdio.h>
/* count blanks (" "), tabs (\t), and newlines (\n) */
main()
{
int c, nb, nt, nl;
nb = nt = nl = 0;
while ((c = getchar()) != EOF)
if (c == ' ')
++nb;
else if (c == '\t')
++nt; /* fails to accumulate count */
else if (c == '\n')
++nl;
printf("Spaces:\t%d\n", nb);
printf("Tabs:\t%d\n", nt); /* fails to report new tabs (\t) */
printf("Lines:\t%d\n", nl);
}

Related

K&R Chapter 1.5.4: "How would you test the word count program?"

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.

What is normal C getchar/putchar behaviour?

I am working through the exercises in Stephen Prata's "C Primer Plus", and have a question re. listing 8.1:
/* echo.c -- echoes input */
#include <stdio.h>
int main(void)
{
char ch;
while ((ch = getchar()) != '#')
putchar(ch);
// while ((ch = getchar()) != '.')
// putchar(ch);
return 0;
}
The original code did not include the comments; I added them and they are the subject of my question. If I uncomment those lines there is no discernible effect on the output. It still ends at the # sign, without printing it. No additional text is displayed and I am returned to the command prompt.
Why is that? Also, does the # get consumed by getchar()? That was why I included the second loop - I was trying to display any remaining characters in the buffer, out of curiosity. Obviously, I don't know what I'm doing!

C printf() not returning values

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.

K&R Exercise 1-8 Counting blanks, tabs, and new lines

I'm going through K&R's book, and one of the exercises is to count the blanks, tabs, and new lines from input. But whenever I run the following code, it only correctly counts the blanks, tabs, and new lines for everything above the last new line. If there's no new line, it doesn't count anything.
hey how
returns
0 0 0
and
hey how
hey how
hey how
returns
2 0 2
If I had tabbed instead of using spaces it would be 0 2 2.
The spaces and tabs seem dependent on the new line, and I don't know why. So how do I get this to work so it doesn't require a new line at the end?
Here's my code.
#include <stdio.h>
/* counts blanks, tabs, and new lines */
main()
{
int c, blanks, tabs, nl;
blanks = 0;
tabs = 0;
nl = 0;
while((c = getchar()) != EOF)
{
if(c == ' ')
++blanks;
if(c == '\t')
++tabs;
if(c == '\n')
++nl;
}
printf("\n%d\t%d\t%d\n" , blanks , tabs , nl);
}
Use a different keyboard shortcut. You don't want to kill the program, you want to simulate end-of-file with the appropriate key combination:
Ctrl+C: Kills the program.
Ctrl+Z, Enter: Signals EOF in Windows.
Ctrl+D: Signals EOF in Linux.

Program not printing out numbers

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 .

Resources