C Programming; Word, Character and Line Count K&R 1-11 - c

#include <stdio.h>
#define YES 0
#define NO 0
int main()
{
int c, nl, nc, nw, tab;
nl = 0;
nc = 0;
nw = 0;
tab = NO;
while ((c = getchar()) != EOF)
{
++nc;
if (c == '\n')
++nl;
if (c == ' ' || c == '\t' || c == '\n')
tab = NO;
else if (tab == NO)
{
tab = YES;
++nw;
}
}
printf("NL: %d\nNC: %d\nNW: %d\n", nl, nc, nw);
}
Hey guys, new coder here. Actually, very much new, I just started a few days ago in hopes of broadening my job opportunities. Anyway, with this program, it counts every new line, word and character. For the most part, I understand what is going on but what I don't understand is the new word part. For example, at the top where we #define YES/NO, the number proceeding the word apparently does not matter? I swapped out 1 and 0 for so many other choices and yet still received the same outcome, why is that? Apologies in advance if this is a dumb question, for I myself am a dumb coder. Take care and thank you for your time!

Previous point:
In C a conditional expression will evaluate to false if it is 0 and true if it is any other value, so YES can be 1, 1000, -1000, etc., as long as it is not 0 the conditional expression where it's evaluated will always be true.
As for the question:
For the code to work as expected YES must be 1, or, as per the explanation above, not 0.
In
else if (tab == NO)
{
tab = YES;
++nw;
}
If YES is 0, tab will always be 0 and NW will not be accurate because it will count all the characters except if they are \t, or \n and this is not what program should do, NW should be the number of words.
For instance, for this input:
This is a word I wrote
You'll have:
NL: 1
NC: 23
NW: 17
When it should be:
NL: 1
NC: 23
NW: 6
Setting tab to 1 (YES) serves as a flag to signal that piece of code to only increment nw 1 time in case there is one of those three charaters thus counting the spaces between the words or the newline character one time only, giving you the number of words in the inputed text.

Welcome to this wolrd!you dont need it. I think this should be the right way(I am sorry for my english and my poor explanations):
#include <stdio.h>
int main()
{
int c, nl, nc, nw;
nl = 0;
nc = 0;
nw = 0;
while ((c = getchar()) != EOF)
{
++nc;
if (c == '\n')
++nl;
if (c != ' ' && c != '\t' && c != '\n')
++nw;
}
printf("NL: %d\nNC: %d\nNW: %d\n", nl, nc, nw);
}

Related

Visual Studio (C) ignoring escape sequences

Going through Kernighan, and I am coding on visual studio with windows. Why doesn't the following program doesn't pick up tab characters, new lines, or spaces? I have to manually type its associated integer. Here's the word count program:
#define IN 1 /*State of being inside word*/
#define OUT 0 /*State of being outside word*/
countWords() {
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);
}
}
My test input was 'one two three' and the output was '0 1 14'. Indicating that it didn't recognise space character ' '. Is there a setting on VS that needs to be changed to get this working?
Be careful with operator precedence.
while ((c = getchar() != EOF)) {
The c variable gets the boolean value of the expression getchar() != EOF. It doesn't hold the character that was read in like you are probably expecting.
You probably meant to write it as:
while ((c = getchar()) != EOF) {

Why printf() after the while loop would not work?

I'm a beginner and I've recently started learning C and here is an example in "The C Programming Language by Brian W. Kernighan, Dennis M. Ritchie" that I don't understand. This program is supposed to count new lines in input and print out the final result. This is the exact same program that is in the book (page 19). The output of it is nothing. I can input forever and it just goes to a new line...
main()
{
int c, nl;
nl = 0;
while ((c = getchar()) != EOF)
if (c == '\n')
++nl;
printf("%d\n", nl);
}
If I put the "printf("%d\n", nl)" statement in the body of the if statement, the output would be printed each time on a new line and the value of "nl" wouldn't reset either. it just increments every time I input something and the program wouldn't terminate.
Why doesn't the example work?
int main()
{
int c, nl;
nl = 0;
while ((c = getchar()) != EOF)
if (c == '\n')
++nl;
printf("%d\n", nl);
return 0;
}
I ran it on my computer using Code::Blocks and it worked just fine. maybe you just forgot the int before main and return 0 ^^

is there any way to stop a (c = getchar()) != EOF) if my work inside the while loop is done?

I am reading the C programming language book Dennis M. Ritchie and
trying to solve this question:
Write a program to print a histogram of
the lengths of words in
its input. It is easy to draw the histogram with the bars horizontal; a vertical
orientation is more challenging.
I think my solution works, but the problem is that if I don't press EOF, the terminal won't show the
result. I know that the condition specifies that exactly, but I am
wondering whether there is any way to make the program terminate after
reading a single line? (Sorry if my explanation of the problem is a bit shallow. Feel free to ask more.)
#include <stdio.h>
int main ()
{
int digits[10];
int nc=0;
int c, i, j;
for (i = 0; i <= 10; i++)
digits[i] = 0;
//take input;
while ((c = getchar ()) != EOF) {
++nc;
if (c == ' ' || c=='\n') {
++digits[nc-1];
//is it also counting the space in nc? i think it is,so we should do nc-1
nc = 0;
}
}
for (i = 1; i <= 5; i++) {
printf("%d :", i);
for (j = 1; j <= digits[i]; j++) {
printf ("*");
}
printf ("\n");
}
// I think this is a problem with getchar()
//the program doesn't exit automatically
//need to find a way to do it
}
You could try to make something like
while ((c = getchar ()) != EOF && c != '\n') {
and then adding a line after the while loop to account for the last word:
if (c == '\n') {
++digits[nc-1];
nc = 0;
There is also another problem inside your program. ++digits[nc-1]; is correct, however, for the wrong reason. You should make it because an array starts at zero, i.e. if you have an array of length 10, it will go from 0 to 9, so you should count the length of the words and then add one to the position of the array length - 1 (as there are no words of length zero). The problem is that you are still counting the blank spaces or the newline characters inside the length of a word, so if you have two blank spaces after a word of length 4, the program will add to the array a word of length 5 + a word of length 1. To avoid this, you should do something like this:
while ((c = getchar ()) != EOF) {
if ((c == ' ' || c == '\n' || c == '\t') && nc > 0) {
++digits[nc-1]; // arrays start at zero
nc = 0;
}
else {
++nc;
}
}

What is the need of using IN and OUT state in the following script?

Hello everyone I just started learning C through THE c PROGRAMMING LANGUAGE Second Edition
by Brian. W.Kernighnan (ISBN-13: 978-8131704943)
So here is a script which counts the characters, line, words
#include <stdio.h>
#define IN 1
#define OUT 0
main()
{
int c, nl, nw, nc, state;
/* c = input, nl = new line, nc = new character, nw = new word, state = (IN/OUT) */
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(" The number of lines is: %d,\n The number of words is: %d,\n The number of characters is: %d. \n", nl, nw, nc);
}
However I made a script which does the following without the need of defining state IN and OUT
#include <stdio.h>
main()
{
int nw, nl, nc, c ;
nl = nw = nc = c = 0 ;
while ((c = getchar()) != EOF)
{
++nc;
if (c == '\n')
++nl;
else if (c == ' ' || c == '\n' || c == '\t')
++nw;
}
printf("Words:%d \nCharacters:%d \nLines:%d", nw, nc, nl);
}
So what is the difference between these two, why does the author use the state to define IN and OUT ??
[EDIT]
Oh! I see so the script is just to avoid two things :
1. To avoid word count when there are more than one spaces following the word.
2. Secondly my script would count n-2 words I suppose if proper spacing is done.
Which makes the author's script more fullproof.....Is there anything else except these two ??
And thank You for your answes too....
P.S: I'm sorry this is a bit off-topic is it ok to label the question [SOLVED] or is there any other way of doing this ??
Your version is slightly different from his one: in your program, if you have N consecutive spaces, they will be considered as N - 1 words, because for every space you add one to the word count. Also, the last input word won't be considered.
IN literally means "inside a word" and OUT literally means "outside a word". He is tracking the state of the proverbial cursor as he moves through the lines.

Word Count logic

So for an intro to C class we have to write a program that will count the number of lines, characters, and words in a file. In the program a word is defined as a sequence of letters, digits, and apostrophes that begins with a letter. For some reason the logic for counting words just isn't working for me, maybe it's because I'm new to C or because I've always been bad at formulating logic. My code now, when passed in
hey whats up\n
hey what's up\n
hey wh?ts 'p\n
returns 3 lines, 31 words, 40 characters. Thanks for any help, I know this is a super lame question it's just driving me insane.
Here is my code:
#include <stdio.h>
typedef enum yesno yesno;
enum yesno {
YES,
NO
};
int main() {
int c; // character
int nl, nw, nc; // number of lines, words, characters
yesno inword; // records if we are in a word or not
yesno badchar;
// initialize variables:
badchar=NO;
inword = NO;
nl = 0;
nw = 0;
nc = 0;`
while ((c = getchar()) != EOF) {
++nc;
if (c == '\n')
++nl;
if (c == ' ' || c == '\n' || c == '\t')
inword = NO;
else if (inword == NO) {
inword = YES;
}
while (inword == YES){
if (( c<'A' || c>'Z')||(c<'a'||c>'z')||(c<'0'|| c>'9') ){
inword= NO;
//badchar = YES;
}
if (( c<'A' || c>'Z')||(c<'a'||c>'z')|| (c<'0'|| c>'9') ||(c!= '\'')){
nw=nw;
inword = NO;
//badchar=YES;
}
if(badchar==NO){
nw++;
badchar=NO;
inword= NO;
}
}
}
printf("%d %d %d\n", nl, nw, nc);
}
One problem is this condition:
if (( c<'A' || c>'Z')||(c<'a'||c>'z')||(c<'0'|| c>'9') ){
inword = NO;
Consider a value of c such as:
'A': this is going to be less than 'a', so you'll switch to inword = NO.
'a': this is going to be greater than 'Z', so you'll switch to inword = NO.
'0': this is going to be less than 'A', so you'll switch to inword = NO.
You need to use && between the sets of conditions:
if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') && (c < '0' || c > '9')){
Or, better, you could use the macros/functions from <ctype.h>:
if (!isupper(c) && !islower(c) && !isdigit(c))
but that can be abbreviated to:
if (!isalnum(c))
You'll need to review the other tests too. There could be other problems too, but I've simply not reviewed the rest of the code.
I've never programmed C. But when I've programmed this same thing in other languages, it's not too tough. For word count, replace "\n" with space, then split the string into an array using a space as the delimiter, and finally count the number of elements in the array. Similar thing to get the line count: split the string into an array using "\n" as the delimiters, then count the number of elements in the array.

Resources