I currently got assignment to make word counting program in c. Task is your program should count characters, lines and words. Lines should be counted even if it is inside comment. Comments should be represented as an " " space character.
I tried to use switch function to implement cases inside and outside word. But I am having trouble with comment. In first if statement I tried to check if we are in comment or not and if so skip it.
#include <stdio.h>
#include <ctype.h>
#define word 1
#define nword 0
int main(void)
{
int c,d,nmb = 0 , state = nword , ch = 0, ln = 0;
while((c=getchar())!=EOF)
{
if( c == '/' )
{
if((d=getchar())=='*')
{
int f;
c = getchar();
d = getchar();
while(c!='*' || d !='/')
{
c = d;
d = getchar();
if(d == '\n')
{ ln++ ; ch++; }
if(d == EOF)
{ f=1 ; break; }
}
if(f==1)
printf("problem in line: %d\n", ln);
state=word;
nmb++;
}
}
switch(state)
{
case nword:
if(isspace(c))
{
state=word;
nmb++;
}
break;
case word:
if(!isspace(c))
state=nword;
break;
}
if (c == '\n')
ln++;
ch++;
}
printf("words: %d\n", nmb);
printf("chars: %d\n", ch);
printf("lines: %d\n", ln);
return 0;
}
I cant get right answers to test cases. I cant debug too because I cant see certain pattern which can be fixed. Some test cases matches right but others dont.(Test cases in https://ee209-2019-spring.github.io/assignment/wc209/ )
Related
I'm in my first programming class and having trouble with a project of ours. The program is designed to take a string's inputs and see if they match the pattern and recognize if the pattern is broken; in this case it is meant to recognize if the user inputs "hahaha!", "hohohoho!", or a mixture of the two 'ha' and 'ho' (always ending in '!').
My trouble is that I have started an attempt at this code using switch cases, but do not know if this is the most effective way to program for the project, or if it is even possible to do it this way.
Here is my code so far, please help me.
#include <stdio.h>
#include <string.h>
#define string_len 100
int main ()
{
char string[string_len];
int state = 0;
while(1)
{
for(int i = 0; i < string_len; i++)
{
printf("Hello, I can tell if you are laughing or not, you can exit by typing 'bye': \n");
scanf("%s", string);
for(state = 0; state < 5;)
{
switch(state)
{
case 0:
if(strcmp(string, "bye") == 0)
printf("Bye now!\n");
return 0;
break;
case 1:
if(string[i] == 'h')
state++;
else(printf("you are not laughing\n"));
break;
case 2:
if(string[i] == 'a')
state--;
else(state++);
break;
case 3:
if(string[i] == 'o')
state = state-2;
else(printf("you are not laughing\n"));
break;
case 4:
if(string[i] == '!')
printf("You are laughing!\n");
else(printf("You are not laughing\n"));
}
}
}
return 0;
}
}
I think that I may be mixed up with the state part of my program in the switch. I'm trying to allow it to go from:
state 0 : check if it says bye, if so "bye now"
state 1: is it an h? if so, check for a or o, if not "you arent laughing"
state 2: is it an a? if so, check for an 'h' or '!' -This is where I'm especially confused, if not is it an o?
state 3: is it an o? if so, check for an 'h' or '!', if not "you aren't laughing"
state 4: is it an '!'? if so "you are laughing" if not, "you are not laughing"
I hope I have formatted this question well enough, please let me know if I could make this more readable in any way and if you have any questions for me.
Thank you all for the help.
Since you asked if there might be another way preferable to a switch() statement, I decide to code an example of a way for you. This works for me. Should compile cleanly and run fine.
#include <stdio.h>
#include <string.h>
#define MAXLEN 100
char *readline();
int main(void) {
char string[MAXLEN];
for(;;) {
memset(string, '\0', MAXLEN);
printf("Hello, I can tell if you are laughing or not, you can exit by typing 'bye': \n");
readline(string, MAXLEN, stdin);
int i = 0;
int aborted = 0;
char buf[3] = { 0 };
while (i < strlen(string) - 1) {
buf[i % 2] = string[i];
if (i % 2 == 1) {
if (strncmp(buf, "ha", 2) != 0 && strncmp(buf, "ho", 2) != 0) {
printf("\nYou are NOT laughing [1]\n\n");
aborted = 1;
break;
}
}
i++;
}
if (!aborted) {
if (string[i] != '!') {
printf("\nYou are NOT laughing [2]\n\n");
continue;
}
printf("\nYou ARE laughing!\n\n");
}
}
}
char *readline (char *buf, size_t length, FILE *f) {
char *p;
if ((p = fgets (buf, length, f)) != NULL) {
size_t last = strlen (buf) - 1;
if (buf[last] == '\n') {
buf[last] = '\0';
} else {
fscanf (f, "%*[^\n]");
(void) fgetc (f);
}
}
return p;
}
The problem you are having is that you fail to remove the newline from stdin. Instead of:
scanf("%s", string);
You need:
scanf("%[^\n]%*c", string);
What happens is that you read your first input fine, but stdin still contains a newline '\n' (the result of pressing [Enter]). If you don't enter bye, when you reach scanf again, scanf takes the '\n' as your input. The new format string above "%[^\n]%*c" says %[^\n] read all characters up to the newline, then %*c read and discard the newline.
#include <stdio.h>
#define string_len 100
#define n2s_(n) #n
#define n2s(n) n2s_(n)
int main(void){
char string[string_len+1];
while(1){
printf("Hello, I can tell if you are laughing or not, you can exit by typing 'bye': \n");
scanf("%" n2s(string_len) "s", string);
if(strcmp(string, "bye") == 0)
break;
//match (ha | ho)+! ?
int i, match = 1, ch;
for(i = 0; match && (ch=string[i]) && ch != '!'; ++i){
if(i & 1){//odd position
if(string[i] != 'a' && string[i] != 'o'){
match = 0;
}
} else {//even position
if(string[i] != 'h'){
match = 0;
}
}
}
if(match && i != 0 && ch == '!')
printf("You are laughing!\n");
else
printf("You are not laughing\n");
}
return 0;
}
I'm just a beginner and I'm trying to use whatever I know to make a simple program that:
Asks the user to input the letter 'S' or 's'. The program loops if 's' is not input. If the user does input 's', the program then
Asks the user to input a number, 1 or 2. The program loops if the incorrect number is input.
The problem I'm having is that after 's' is successfully input and the user is asked to enter a number, if an incorrect number is input (not 1 or 2) the program asks the user to input a letter again from the beginning which is incorrect. The program loops from the very beginning and doesn't work anymore. Can anyone help me fix this please?
#include <stdio.h>
#include <ctype.h>
int function(int num);
int main()
{
char input,ch,temp,c[64],exit;
int i,invalid,num,index,flag,day;
invalid = 0;
num = 0;
size_t length = 0;
index = 0;
flag = 0;
do
{
puts("Enter the letter S to start the program:");
scanf("%c", &input);
while( input!='\n' && (ch=getchar())!='\n' && ch!= EOF);
{
if(isalpha(input)==0)
{
printf("Invalid input. Please input something.\n");
continue;
}
if(input == 'S' || input == 's')
{
printf("\nProgram start.");
while( sscanf(c, "%d", &num) != 1)
{
length = 0;
flag = 0;
num = 0;
printf("\nEnter 1 for Module A. Enter 2 for Module B. Enter here: ");
fgets(c, 63, stdin);
length = strlen(c);
for(index = 0; index < length; ++index)
{
if(c[index] < '0' || c[index] > '9')
{
flag = 1;
break;
}
}
if( flag)
{
printf("\nInvalid character\n");
continue;
}
if( sscanf(c, "%d", &num) != 1)
{
printf("\nNo input detected.");
continue;
}
if(num == 1)
{
printf("\nModule A Selected.\n");
return(0);
}
if(num == 2)
{
printf("\nModule B Selected.\n");
return(0);
}
}
}
else
{
printf("\nInvalid input.");
continue;
}
}
}
while(1);
}
Make the scanf into like this.
scanf(" %c",&input);
Then While getting the input from the user using fgets It will place the new line character into that buffer. So this will lead to fails this condition.
if(c[index] < '0' || c[index] > '9')
{
flag = 1;
break;
}
So make the this condition into like this.
length=strlen(c)-1;// to skip the new line character
Or else to like this.
length=strlen(c);
if ( c[length] == '\n' )
c[length]='\0';
Output After placing this,
Enter the letter S to start the program:
S
Program start.
Enter 1 for Module A. Enter 2 for Module B. Enter here: 1
Module A Selected.
Make this in you code.
if(num == 1)
{
printf("\nModule A Selected.\n");
return(0);
}
else if(num == 2)
{
printf("\nModule B Selected.\n");
return(0);
}
else
{
printf("\nInvalid option\n");
c[0]='\0'; // It is for satisfy the second while loop condition.
continue;
}
Note that the loop:
while( input!='\n' && (ch=getchar())!='\n' && ch!= EOF);
is limited to the one line by the semicolon at the end. The following code is not the body of the loop, despite indentation trying to pretend that it is.
Also note that getchar() returns an int, not a char; you cannot reliably assign the result to a char and then test it for EOF. Depending on the platform, you will either never detect EOF at all or you will misdetect EOF when some other character (often ΓΏ, y-umlaut, U+00FF, LATIN SMALL LETTER Y WITH DIAERESIS) is typed. You must use int ch;.
Here. I fixed the problem using the following code. This way the code does the following:
Scans letters 'S' or 's'. Keeps looping if these are not entered.
Scans either number 1 or 2. Keeps looping until either number is entered and then exits.
The program does not loop from the very beginning (by outputting "Enter 'S' to start program), if any number other than 1 or 2 in entered in part 2 of the program. This was the problem originally.
The following is the correct code:
#include <stdio.h>
#include <ctype.h>
int function();
char input,temp,c[64],ch,exit;
int i,invalid,num,index,flag,start;
start = 0;
invalid = 0;
num = 0;
size_t length = 0;
index = 0;
flag = 0;
int main()
{
do
{
puts("Enter the letter S to start the program: ");
scanf("%c", &input);
while( input!='\n' && (ch=getchar())!='\n' && ch!= EOF);
{
if(isalpha(input)==0)
{
printf("Invalid input. Please input something.\n");
continue;
}
if(input == 'S' || input == 's')
{
printf("\nProgram start.");
start = 1;
if(start == 1)
{
function();
return(0);
}
}
else
{
printf("\nInvalid input.");
continue;
}
}
}
while(1);
}
int function()
{
while( sscanf(c, "%d", &num) != 1)
{
length = 0;
flag = 0;
num = 0;
printf("\nEnter 1 for Module A. Enter 2 for Module B. Enter here: ");
fgets(c, 63, stdin);
length = strlen(c);
length --;
for(index = 0; index < length; ++index)
{
if(c[index] < '0' || c[index] > '9')
{
flag = 1;
break;
}
}
if( flag)
{
printf("\nInvalid character\n");
continue;
}
if( sscanf(c, "%d", &num) != 1)
{
printf("\nNo input detected.");
continue;
}
if(num == 1)
{
printf("\nModule A Selected.\n");
return(0);
}
else if(num == 2)
{
printf("\nModule B Selected.\n");
return(0);
}
else
{
printf("\nInvalid option\n");
c[0]='\0'; // It is for satisfy the second while loop condition.
continue;
}
}
}
I'm trying to write a program which given a certain number of input will output the product of the listed input (only accounting inputs of 0-9 and ignoring other).
For example:
input:345 would result output: 60, or another example would be, input: 3t4 and output: 12
I have given it many attempts and this is what I'm stuck with :
#include <stdio.h>
main(){
int c,i;
c = getchar();
i = 1;
while (c!= '\n'){
if (c>=48 && c<=57){
i=c*i;
c=getchar();
}
}
printf("%d",i);
}
How can i do this ?
Couple of issues in your code.
After each time the program encounters a non-numeric character it doesn't read further from the input. It reads the same character. Hence c=getchar() should be outside the if block
The multiplication happens for the char variable c. It should be converted to the actual number and then be multiplied. In your code you are multiplying its ascii value. Hence (c-48)*i instead of c*i
Use i=(c-48)*i; instead of i = c*i. So, the changed program would be:
#include <stdio.h>
main(){
int c,i;
c = getchar();
i = 1;
while (c!= '$'){
// printf("%c\n", c);
if (c>=48 && c<=57){
i=(c-48)*i;
}
c=getchar();
}
printf("%d",i);
}
This will ensure that you are using the numeric value of the digit, 0 not as ascii code of 0 but as simple 0.
use c=getchar() outside the if block. This should work.
int i,c;
i = 1;
while (i){
c=getchar();
if(c == '\n')
{
break;
}
if (c < 48 || c > 57)
{
i = -1;
break;
}
i = i * (c-48);
}
if (i == -1)
{
printf("Error. Non-Number Entered\n\n");
}
else {
printf("%d\n\n",i);
}
As part of my course, I have to learn C using Turbo C (unfortunately).
Our teacher asked us to make a piece of code that counts the number of characters, words and sentences in a paragraph (only using printf, getch() and a while loop.. he doesn't want us to use any other commands yet). Here is the code I wrote:
#include <stdio.h>
#include <conio.h>
void main(void)
{
clrscr();
int count = 0;
int words = 0;
int sentences = 0;
char ch;
while ((ch = getch()) != '\n')
{
printf("%c", ch);
while ((ch = getch()) != '.')
{
printf("%c", ch);
while ((ch = getch()) != ' ')
{
printf("%c", ch);
count++;
}
printf("%c", ch);
words++;
}
sentences++;
}
printf("The number of characters are %d", count);
printf("\nThe number of words are %d", words);
printf("\nThe number of sentences are %d", sentences);
getch();
}
It does work (counts the number of characters and words at least). However when I compile the code and check it out on the console window I can't get the program to stop running. It is supposed to end as soon as I input the enter key. Why is that?
Here you have the solution to your problem:
#include <stdio.h>
#include <conio.h>
void main(void)
{
clrscr();
int count = 0;
int words = 0;
int sentences = 0;
char ch;
ch = getch();
while (ch != '\n')
{
while (ch != '.' && ch != '\n')
{
while (ch != ' ' && ch != '\n' && ch != '.')
{
count++;
ch = getch();
printf("%c", ch);
}
words++;
while(ch == ' ') {
ch = getch();
printf("%c", ch);
}
}
sentences++;
while(ch == '.' && ch == ' ') {
ch = getch();
printf("%c", ch);
}
}
printf("The number of characters are %d", count);
printf("\nThe number of words are %d", words);
printf("\nThe number of sentences are %d", sentences);
getch();
}
The problem with your code is that the innermost while loop was consuming all the characters. Whenever you enter there and you type a dot or a newline it stays inside that loop because ch is different from a blank. However, when you exit from the innermost loop you risk to remain stuck at the second loop because ch will be a blank and so always different from '.' and '\n'. Since in my solution you only acquire a character in the innermost loop, in the other loops you need to "eat" the blank and the dot in order to go on with the other characters.
Checking these conditions in the two inner loops makes the code work.
Notice that I removed some of your prints.
Hope it helps.
Edit: I added the instructions to print what you type and a last check in the while loop after sentences++ to check the blank, otherwise it will count one word more.
int ch;
int flag;
while ((ch = getch()) != '\r'){
++count;
flag = 1;
while(flag && (ch == ' ' || ch == '.')){
++words;//no good E.g Contiguous space, Space at the beginning of the sentence
flag = 0;;
}
flag = 1;
while(flag && ch == '.'){
++sentences;
flag=0;
}
printf("%c", ch);
}
printf("\n");
I think the problem is because of your outer while loop's condition. It checks for a newline character '\n', as soon as it finds one the loop terminates. You can try to include your code in a while loop with the following condition
while((c=getchar())!=EOF)
this will stop taking input when the user presses Ctrl+z
Hope this helps..
You can implement with ease an if statement using while statement:
bool flag = true;
while(IF_COND && flag)
{
//DO SOMETHING
flag = false;
}
just plug it in a simple solution that uses if statements.
For example:
#include <stdio.h>
#include <conio.h>
void main(void)
{
int count = 0;
int words = 1;
int sentences = 1;
char ch;
bool if_flag;
while ((ch = getch()) != '\n')
{
count++;
if_flag = true;
while (ch==' ' && if_flag)
{
words++;
if_flag = false;
}
if_flag = true;
while (ch=='.' && if_flag)
{
sentences++;
if_flag = false;
}
}
printf("The number of characters are %d", count);
printf("\nThe number of words are %d", words);
printf("\nThe number of sentences are %d", sentences);
getch();
}
#include <stdio.h>
#include <ctype.h>
int main(void){
int sentence=0,characters =0,words =0,c=0,inside_word = 0,temp =0;
// while ((c = getchar()) != EOF)
while ((c = getchar()) != '\n') {
//a word is complete when we arrive at a space after we
// are inside a word or when we reach a full stop
while(c == '.'){
sentence++;
temp = c;
c = 0;
}
while (isalnum(c)) {
inside_word = 1;
characters++;
c =0;
}
while ((isspace(c) || temp == '.') && inside_word == 1){
words++;
inside_word = 0;
temp = 0;
c =0;
}
}
printf(" %d %d %d",characters,words,sentence);
return 0;
}
this should do it,
isalnum checks if the letter is alphanumeric, if its an alphabetical letter or a number, I dont expect random ascii characters in my sentences in this program.
isspace as the name says check for space
you need the ctype.h header for this. or you could add in
while(c == ' ') and whie((c>='a' && c<='z') || (c >= 'A' && c<='Z')
if you don't want to use isalpace and isalnum, your choice, but it will be less elegant :)
The trouble with your code is that you consume the characters in each of your loops.
a '\n' will be consumed either by the loop that scans for words of for sentences, so the outer loop will never see it.
Here is a possible solution to your problem:
int sentences = 0;
int words = 0;
int characters = 0;
int in_word = 0; // state of our parser
int ch;
do
{
int end_word = 1; // consider a word wil end by default
ch = getch();
characters++; // count characters
switch (ch)
{
case '.':
sentences++; // any dot is considered end of a sentence and a word
break;
case ' ': // a space is the end of a word
break;
default:
in_word = 1; // any non-space non-dot char is considered part of a word
end_word = 0; // cancel word ending
}
// handle word termination
if (in_word and end_word)
{
in_word = 0;
words++;
}
} while (ch != '\n');
A general approach to these parsing problems is to write a finite-state machine that will read one character at a time and react to all the possible transitions this character can trigger.
In this example, the machine has to remember if it is currently parsing a word, so that one new word is counted only the first time a terminating space or dot is encountered.
This piece of code uses a switch for concision. You can replace it with an if...else if sequence to please your teacher :).
If your teacher forced you to use only while loops, then your teacher has done a stupid thing. The equivalent code without other conditional expressions will be heavier, less understandable and redundant.
Since some people seem to think it's important, here is one possible solution:
int sentences = 0;
int words = 0;
int characters = 0;
int in_word = 0; // state of our parser
int ch;
// read initial character
ch = getch();
// do it with only while loops
while (ch != '\n')
{
// count characters
characters++;
// count words
while (in_word)
{
in_word = 0;
words++;
}
// skip spaces
while (ch == ' ')
{
ch = -1;
}
// detect sentences
while (ch == '.')
{
sentences++;
ch = -1;
}
// detect words
while ((ch != '\n')
{
word_detected = 1;
ch = -1;
}
// read next character
ch = getch();
}
Basically you can replace if (c== xxx) ... with while (c== xxx) { c = -1; ... }, which is an artifical, contrieved way of programming.
An exercise should not promote stupid ways of doing things, IMHO.
That's why I suspect you misunderstood what the teacher asked.
Obviously if you can use while loops you can also use if statements.
Trying to do this exercise with only while loops is futile and results in something that as little or nothing to do with real parser code.
All these solutions are incorrect. The only way you can solve this is by creating an AI program that uses Natural Language Processing which is not very easy to do.
Input:
"This is a paragraph about the Turing machine. Dr. Allan Turing invented the Turing Machine. It solved a problem that has a .1% change of being solved."
Checkout OpenNLP
https://sourceforge.net/projects/opennlp/
http://opennlp.apache.org/
I am learning c programing, for exercise I found a task to solve.
It is something like a game hanging where someone chooses a word and other person guess letters. I have to check how many given words could be a correct answer to the choosen word.
Input:
3 3 // numbers n and m n-number of words to compare, m-number of letters checked
A C D // m letters separate by space
--CA // word that is given to guess
KUCA // n words to be checked if they match in this case "--CA"
ZGRADA // words are separated by enter(\n)
MACA // in this case "MACA" does not match "--CA" because there was a "A" in the guessed letters but not on the second dash meant for some letter
Output: 1
Idea is to check if the lenghts are the same if they are it should check if current character is "-" if so it should check every of m characters (guessed letters) if they match current one if so rez--;(sol--;)(before was declared rez=n;)
here is my code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n=0,i=0,m=0,j=0,k=0,duzina=0,rez=0,br=0;
char slova[26], rec[30], pot[30],c;
scanf("%d %d\n",&n,&m);
br = 0;
while ( (c = getchar()) != '\n' ){
if ( c != ' ' ) { slova[br] = c; br++; }
}
slova[br] = '\0';
br = 0;
while ( (c = getchar()) != '\n' ){
rec[br] = c;
br++;
}
rec[br] = '\0';
rez=n;
duzina=strlen(rec);
for(i=0;i<n;i++){
br=0;
while ( (c = getchar()) != '\n' ){
pot[br] = c;
br++;
}
pot[br] = '\0';
if(duzina!=strlen(pot))
rez--;
else{
for(j=0;j<duzina;j++){
if(rec[j]=='-'){
for(k=0;k<m;k++){
if(pot[j]==slova[k]){
rez--;
break;
}
}
}
else{
if(rec[j]!=pot[j])
rez--;
}
}
}
}
printf("%d",rez);
return 0;
}
So my problem is in the wrong answer, and I don't know why.
Code works for example above but for this one it shows -8, it should 3:
10 5
A I L B X
--A--AB-X
PUAQFABHX
IIAFWABIX
MHAKVABPX
BQAXWABWX
TEAUIAB
PCALIABLX
RRAYHAEKJ
NWNKSGBNP
ZOCZKJWZR
ROAJRABZX
In the else portion of the following code:
if(duzina!=strlen(pot))
rez--;
else{
for(j=0;j<duzina;j++){
if(rec[j]=='-'){
for(k=0;k<m;k++){
if(pot[j]==slova[k]){
rez--;
break; // <-- This will break out of the 'for-k' loop
}
}
}
else{
if(rec[j]!=pot[j])
rez--; // <-- Are you missing a 'break' here?
}
}
}
After rez is decremented, you need to break out of the outer loop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int n=0,i=0,m=0,j=0,k=0,duzina=0,rez=0,br=0;
char slova[26], rec[30], pot[30],c;
short booli=1;
scanf("%d %d\n",&n,&m);
br = 0;
while ( (c = getchar()) != '\n' ){
if ( c != ' ' ) { slova[br] = c; br++; }
}
slova[br] = '\0';
br = 0;
while ( (c = getchar()) != '\n' ){
rec[br] = c;
br++;
}
rec[br] = '\0';
rez=n;
duzina=strlen(rec);
for(i=0;i<n;i++){
br=0;
booli=1;// this is the line that i forgot, that caused all the trouble.
while ( (c = getchar()) != '\n' ){
pot[br] = c;
br++;
}
pot[br] = '\0';
if(duzina!=strlen(pot))
rez--;
else{
for(j=0;j<duzina;j++){
if(rec[j]=='-'){
for(k=0;k<m;k++){
if(pot[j]==slova[k]){
rez--;
booli=0;
break;
}
}
if(booli==0) break;/*this is for checking if the for-k loop was ended with break;*/
}
else{
if(rec[j]!=pot[j]){
rez--;
break;
}
}
}
}
}
printf("%d",rez);
return 0;
}
Thaks to agbinfo for saying that I that I need second break;