I am learning the 1.5.4 Word Counting chapter 1 of "C Programming Language, 2nd Edition"
#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);
}
I intimate the codes line by line, but it report error when I tried to compile it,
$ cc word_counting.c
word_counting.c:7:1: warning: type specifier missing, defaults to 'int'
[-Wimplicit-int]
main()
^
word_counting.c:15:16: warning: result of comparison against a string literal is
unspecified (use strncmp instead) [-Wstring-compare]
if ( c == "\n")
^ ~~~~
word_counting.c:15:16: warning: comparison between pointer and integer
('int' and 'char *')
if ( c == "\n")
I double-checked my codes, there's not difference with the original codes.
c is a character. '\n' is a character. "\n" is a string.
You can't compare character and string.
Correct code is
if ( c == '\n')
++nl;
Related
Why the below condition:
if (c !=' ' && c !='\t' && c !='\n')
matches either:
not space + not \n - when input is "abc \n"
or
not \t + not \n - when input is "abc\t\n"
When AND logical operator is used?
Should not AND require to match all conditions the same time?
Not space + NOT \t + NOT \n
#include <stdio.h>
#define IN 1 /* inside a word */
#define OUT 0 /* outside a word */
int main() {
int c, state;
state = OUT;
while ((c = getchar()) != EOF) {
if (c !=' ' && c !='\t' && c !='\n')
{
printf("%c", c);
state = IN;
}
else if (state)
{
printf("\n");
state = OUT;
}
}
}
You seem to be confused regarding what the condition is actually checking for.
This condition:
if (c !=' ' && c !='\t' && c !='\n')
Written out as English, says: "if c is not a space AND c is not a tab AND c is not a newline".
In other words, the condition is true when c matches none of those 3 characters.
It is working as intended, test it with vertical-tab.
#include <stdio.h>
#define IN 1 /* inside a word */
#define OUT 0 /* outside a word */
int main() {
int c, state;
state = OUT;
while ( (c = getchar()) != EOF) {
if (c != ' ' && c != '\t' && c != '\n') {
printf ("%c", c);
state = IN;
} else if (state) {
printf ("\v");
state = OUT;
}
}
return 0;
}
space, newline & tab chars are ignored and after every word we print a vertical-tab. We see this step pattern to prove that.
There are tabs in 2nd edition
./a.out
C Programming Language 2nd edition exercise 1-12 question
C
Programming
Language
2nd
edition
exercise
1-12
question
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) {
This code is taken from C Programming by K & R. I am newbie to C programming and i need little help in understanding this code. This code gives me error please help me how to fix it
#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);
}
Error :
E:\Files\C\main.c:5:1: warning: return type defaults to 'int' [-Wreturn-type]
E:\Files\C\main.c: In function 'main':
E:\Files\C\main.c:14:40: error: lvalue required as left operand of assignment
E:\Files\C\main.c:21:1: warning: control reaches end of non-void function [-Wreturn-type]
You are assigning the value for c instead of comparing.
if (c == ' ' || c == '\n' || c = '\t') state = OUT;
should be
if (c == ' ' || c == '\n' || c == '\t') state = OUT;
And your main function should be like int main(void) and put a return 0 at the end
you are assigning value rather than comparing it:if (c == ' ' || c == '\n' || c = '\t'), == is used for comparison and = is used for assignment.
first of all change main function to int main() at line 5.
Also at line 13 try to use == for making it equal in the way shown below.
if (c == ' ' || c == '\n' || c == '\t') state = out;
//you assign a value instead
Also to terminate a program, at the end write return 0;
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.
I'm new to C. I'm trying to get a lot of text from the user and count the number of words, characters, lines, whitespaces and letters. This is what I've done:
#include <ctype.h>
#include <stdio.h>
int main(void)
{
char c = getchar();
char previousc;
int charcount = 0;
int wordcount = 0;
int whitespacecount = 0;
int linecount = 0;
int lettercount = 0;
while(c != EOF)
{
if(isLetter(c) == 1) lettercount++;
if(isWhitespace(c) == 1)
{
whitespacecount++;
if(isWhitespace(previousc) == 0) wordcount++;
}
if(c == "\n") linecount++;
previousc = c;
c = getchar();
charcount++;
}
printf("Character Count: %d\n Word Count: %d\n Whitespace Count: %d\n Letter Count: %d\n Line Count: %d\n", charcount, wordcount, whitespacecount, linecount, lettercount);
}
int isLetter(char c) // 1 for true, 0 for false.
{
// instead of writing tons of if's
if(isalpha(c) > 0)
return 1;
return 0;
}
int isWhitespace(char c) // 1 for true, 0 for false.
{
if(c == "\n" || c == " " || c == " ") return 1;
return 0;
}
But I get so many errors and warnings I'm just lost...
program2.c: In function ‘main’:
program2.c:20: warning: comparison between pointer and integer
program2.c: At top level:
program2.c:28: error: conflicting types for ‘isLetter’
program2.c:28: note: an argument type that has a default promotion can’t match an empty parameter name list declaration
program2.c:14: error: previous implicit declaration of ‘isLetter’ was here
program2.c:35: error: conflicting types for ‘isWhitespace’
program2.c:35: note: an argument type that has a default promotion can’t match an empty parameter name list declaration
program2.c:15: error: previous implicit declaration of ‘isWhitespace’ was here
program2.c: In function ‘isWhitespace’:
program2.c:36: warning: comparison between pointer and integer
program2.c:36: warning: comparison between pointer and integer
program2.c:36: warning: comparison between pointer and integer
I googled the different errors but didn't find a solution that solves my problem.
Can you help me a bit?
Thanks.
For
program2.c:20: warning: comparison between pointer and integer
Change
if(c == "\n")
to
if(c == '\n')
For
program2.c:28: error: conflicting types for ‘isLetter’
program2.c:28: note: an argument type that has a default promotion can’t match an empty parameter name list declaration
program2.c:14: error: previous implicit declaration of ‘isLetter’ was here
program2.c:35: error: conflicting types for ‘isWhitespace’
program2.c:35: note: an argument type that has a default promotion can’t match an empty parameter name list declaration
program2.c:15: error: previous implicit declaration of ‘isWhitespace’ was here
Define prototypes for your functions.
int isLetter(char c);
int isWhitespace(char c);
For
program2.c: In function ‘isWhitespace’:
program2.c:36: warning: comparison between pointer and integer
program2.c:36: warning: comparison between pointer and integer
program2.c:36: warning: comparison between pointer and integer
Change
if(c == "\n" || c == " " || c == " ") return 1;
to
if(c == '\n' || c == ' ' || c == '\t')
Start with the first error/warning, fix it and then work your way down one by one always compiling after each change. Often, you will find, getting rid of an error/warning on a line also gets rid of others in subsequent lines.
Line 20:
if(c == "\n") linecount++;
gives the warning
program2.c:20: warning: comparison between pointer and integer
c is a char (internally converted to an integer before the comparison); "\n" is an array[2] of char (internally converted to char * before the comparison).
That's why the compiler complains about comparing an integer and a pointer.
You need to compare c to a character (both will get internally converted to integers)
if(c == '\n') linecount++;
Declare the following functions before calling them (i.e., above function main):
int isLetter(char c);
int isWhitespace(char c);
In function main:
Replace the variable-declaration char c with int c
Replace the function-call isLetter(c) with isLetter((char)c)
Replace the function-call isWhitespace(c) with isWhitespace((char)c)
Replace the variable-assignment previous = c with previous = (char)c
Replace the conditional-statement if (c == "\n") with if ((char)c == '\n')
The reason for int c, is that function getchar returns int in order support the EOF indicator.
In function isWhitespace, change the conditional-statement to:
if (c == ' ' || c == '\n' || c == '\r' || c == '\t')
EOF is an integer value which indicate the end of input. It's a value such that for any character ch, ch == EOF is always false. Therefore, you should always compare a value of int type with EOF, not char type. It's working on your machine because the char type is implemented as signed char but on machines where char type is unsigned char, this won't.
Now coming to the warnings and errors
The scope of a function is from the point of its definition or declaration till the end of the program. You are calling the functions like isLetter in main before they have been declared.
"\n" is a string literal, not a character. So are " " and " ". The string literal here evaluates to a pointer to its first element and you are comparing this pointer with a character - a different type. You should, instead, compare with '\n', ' ', '\t' respectively.
you have to declare the function header before using it in the main, for example:
int isLetter(char c);
int main(void){
char c = getchar();
char previousc;
int charcount = 0;
int wordcount = 0;
int whitespacecount = 0;
int linecount = 0;
int lettercount = 0;
while(c != EOF)
{
if(isLetter(c) == 1) lettercount++;
if(isWhitespace(c) == 1)
{
whitespacecount++;
if(isWhitespace(previousc) == 0) wordcount++;
}
if(c == "\n") linecount++;
previousc = c;
c = getchar();
charcount++;
}
printf("Character Count: %d\n Word Count: %d\n Whitespace Count: %d\n Letter Count: %d\n Line Count: %d\n", charcount, wordcount, whitespacecount, linecount, lettercount);}
that will fix the conflicting types error.
but also you'll have to change " " to ' ' if you are checking on characters.