C: Trouble starting a program designed to recognize a string pattern - c

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;
}

Related

Word counting program in c (it should exclude comments)

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/ )

Newbie here. C function problem during execution

Edit: Since I understand that I need to provide more info to make it clear for you guys, I added the main function and the getchoice and also two images of the program running. My problem is that after entering the endword, I want to see the menu first and then make a choice, whereas it prompts me to give an input without showing the menu.
This function is part of a bigger program, but this is where a problem occurs.
It reads words inputed, places them into an array, until the keyword ****END is entered. However, when this keyword is entered, it doesn't go immediatelly in the specified if clause (you will see that in the code). I'm a newbie and it could be something really obvious, but any help is greatly appreciated.
#include <string.h>
#define M 50
#define N 15
void getText(char a[M][N])
{
int i, j;
char temp[N];
for (i = 0; i < 50; i++) {
for (j = 0; j < 15; j++) {
if (i == 49 && j == 14) {
printf("Maximum length of text reached.\n");
}
scanf("%s\n", temp);
if (strcmp(temp, "****END") == 0) {
printf("You entered the endkey.\n");
return;
}
strcpy(a[i], temp);
}
}
}
int main(){
int input;
while(1){
input = getChoice();
if(input == 1){
getText(text);
}
else if(input == 2){
getDictionary();
}
else if(input == 3){
correctText();
}
else if(input == 4){
saveText();
}
else if(input == 5){
getStats();
}
else if(input == 6){
break;
}
}
return 0;
}
int getChoice(){
int temp;
printf("Choose function:\n1: Enter text\n2: Enter dictionary\n3: Correct text\n4: Save text\n5: Get text statistics\n6: Exit program\n");
scanf("%d", &temp);
return temp;
}
Entered the endword and now it waits for input instead of showing the menu.
I inputed 2 for the second program function, then it showed the menu and proceeded to function 2.
Apart from the unnecessary double-nested loop, this line
scanf("%s\n", temp);
should be
scanf("%s", temp);
Usually, you should not try to match trailing whitespace with scanf, and the format specifier %s automatically filters out leading whitespace (but note that %c does not).
There are other faults and the code presented was originally incomplete, but notably the input length for %s must be restricted to prevent buffer overflow.
#include <stddef.h> // size_t
#include <ctype.h> // isspace()
#include <stdio.h> // scanf(), puts()
#include <string.h> // strcmp()
// see https://stackoverflow.com/questions/2653214/stringification-of-a-macro-value
#define STRINGIFY(x) #x
#define STRING(x) STRINGIFY(x)
#define LINES 50
#define COLS 15
char const *end = "****END";
// throw away everything until a newline is found
void clear(FILE *stream)
{
int ch;
while ((ch = getc(stream)) != EOF && ch != '\n');
}
size_t getText(char dst[LINES][COLS + 1])
{
size_t i = 0;
for (; i < LINES; i++) {
char temp[COLS + 1] = { 0 };
scanf("%" STRING(COLS) "s", temp); // "%15s" at runtime.
int ch;
// if the next character is not whitespace ...
if ((ch = getchar()) != EOF && !isspace(ch)) {
puts("Warning: Input too long, was truncated!");
clear(stdin);
}
if (strcmp(temp, end) == 0) {
puts("You entered the endkey.");
return i;
}
strcpy(dst[i], temp);
}
return i;
}
int main(void)
{
// COLS + 1 ... we need space for the terminating newline character.
char foo[LINES][COLS + 1];
size_t n = getText(foo);
for (size_t i = 0; i < n; ++i)
puts(foo[i]);
}
The %s conversion specifier should never be used without specifying a width to limit the characters that get stored:
char foo[10];
scanf("%9s");

How can I make sure that there is no limit to how long a password can be?

I wrote a code in C where the user has to have a "$", a number and a capital number in their password for it to be valid, but I'm confused as to what to do so that the password can be as long as they want, without me having to write char password[100000000000]or something like that.
int something = 100;
char password[something];
int index = 0;
int x = 0;
int y = 0;
int z = 0;
printf("Enter Password: "); //Mike$4
scanf("%s", password);
do{ // If index is strlen, then we checked every char of pw
// Ex. Password is length 6, then index 0 - 5 will be checked
if(index == strlen(password) && x>0 && y>0 && z>0){
printf("Good password!");
break;
}
if(index == strlen(password) && (x==0 || y==0 || z==0)){
printf("BAD PASSWORD");
break;
}
if(isupper(password[index]) || isdigit(password[index]) ||
password[index] == '$'){
if(isupper(password[index])){
x++; index++;
continue;}
if(isdigit(password[index])){
y++; index++;
continue;}
if(password[index] == '$'){
z++; index++;
continue;}
}else{index++;
continue;
}
}while(index <= strlen(password));
This is my code. Thanks!
If you truly want unlimited length (although its utility is somewhat questionable -- it's probably better to just pick a big limit and be done with it), you're going to have to ditch scanf for something like fgets that allows you to specify how many characters to read, then read the input in chunks. You'll probably want to use an easy-to-grow structure (like a linked list of slightly-less-than-page-sized string buffers) to read in these chunks, then allocate a buffer for the final string once you hit a newline (or EOF, depending on your desired semantics) in your input.
The simplest way would be to use fgets. Note that scanf("%s") will only get a single word and some passwords might have spaces. But, the real reason to use fgets is that you can prevent overflow as in:
char password[1000];
fgets(password,sizeof(password),stdin);
char *cp = strchr(password,'\n');
if (cp != NULL)
*cp = 0;
That's the simplest solution.
But, if you really need a large password [of unspecified length], you can grow the password variable from realloc, just as would be done for a dynamic array:
char *password = NULL;
int pwmax = 0;
int pwlen = 0;
void *
xrealloc(void *ptr,size_t len)
{
void *tmp;
tmp = realloc(ptr,len);
if (tmp == NULL) {
free(ptr);
exit(1);
}
return ptr;
}
while (1) {
int chr = fgetc(stdin);
if (chr == EOF)
break;
if (chr == '\n')
break;
if (pwlen >= pwmax) {
if (pwlen >= 1000000) {
fprintf(stderr,"password beyond reasonable max limit\n")
exit(1);
}
pwmax += 100;
password = xrealloc(password,pwmax);
}
password[pwlen++] = chr;
}
password = xrealloc(password,pwlen + 1);
password[pwlen] = 0;
Simply process one character of the password at a time; there is no need to have it all in memory at once.
#include <ctype.h>
#include <stdio.h>
#include <stdbool.h>
int main(void)
{
printf("Enter password: ");
bool SawDollar = false;
bool SawDigit = false;
bool SawUpper = false;
while (1)
{
int c = getchar();
if (c == EOF || isspace(c))
break;
if (c == '$')
SawDollar = true;
else if (isdigit(c))
SawDigit = true;
else if (isupper(c))
SawUpper = true;
}
if (SawDollar && SawDigit && SawUpper)
printf("Good password!\n");
else
printf("Bad password.\n");
}

Write a program to check given input string have balance brackets

Given a string of parentheses, write a program to find whether its valid or not.
Examples-
input : {{{}}}
output: Valid
input : }{}{}{}}
output: Invalid
I wrote the following code in C and tested that the output were coming correct.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char str[20];
int i=0;
printf("Enter String: ");
gets(str);
int count = 0;
while (str[i] != '\0')
{
if (str[i] == '}')
count--;
if (str[i] == '{')
count++;
if (count < 0)
{
printf("\nInvalid");
break;
}
i++;
}
if (count == 0)
printf("\nValid");
return 0;
}
This program doesn't work for the case where input is {{{}}, what condition(s) am I missing?
Code should state if the final result is not 0 as in the case of "{"
if (count == 0) {
printf("Valid\n");
} else {
printf("Invalid\n");
}
return 0;
Also simple break out of loop.
if (count < 0) {
// printf("\nInvalid");
break;
}
gets() has been depreciated since C99 and eliminated from C (C11), use fgets().
char str[20];
fgets(str, sizeof str, stdin);
There is no need to read the entire string in. Code could use 1 char ar a time.
int ch;
while ((ch = fgetc(stdin)) != '\n' && ch != EOF) {
if (str[i] == '}')
count--;
if (count < 0) {
break;
}
else if (str[i] == '{')
count++;
}
}
You don't really need to input the whole string at once since you're only every sequentially processing the characters. Hence you can avoid using unsafe methods like gets() and even safe-but-complicating methods like fgets().
Instead, just use getchar() to read and process each individual character - that should greatly simplify what you need to do.
As to the logic, you basically have it right. Maintain the bracket level, a value initially set to zero. Then read each character and action it as follows:
If it's {, just add one to the level.
If it's }, subtract one from the level, then check to ensure the level is non-negative. If not, then you've had too many closing brackets and you can exit.
If it's end of line or end of file, stop processing characters. Check to make sure the final level is zero. If not, you haven't closed off all the brackets so it's invalid. If the level is zero, everything is balanced.
Any other character can be considered an error.
See below for one example on how to implement this:
#include <stdio.h>
int main (void) {
int debug = 0; // for debugging purposes.
int ch, level = 0; // character and current level.
// Output prompt, read characters while valid.
printf("Enter string: ");
while (((ch = getchar()) == '{') && (ch == '}')) {
// Select based on '{' or '}'.
if (ch == '{') {
// Open bracket, just add one.
++level;
if (debug) printf("DEBUG: {:%d\n",level);
} else {
// Close bracket, subtract one and check.
if (--level < 0) {
puts ("Level has gone below zero.");
return 1;
}
if (debug) printf("DEbug: }:%d ",level);
}
}
// If not endline/endfile, we have invalid character.
if ((ch != '\n') && (ch != EOF)) {
puts ("Invalid character in input.");
return 1;
}
// Level should be zero.
if (level != 0) {
puts ("Level still positive at end of line.");
return 1;
}
// All checks now passed okay.
puts ("Input was fine.");
return 0;
}
You should never use gets(), the gcc compiler even warns about it being dangerous because there is no way to prevent a buffer overflow, for example
char str[6];
gets(str);
with the following input
iharob
is a problem, because there is no room for the '\0' terminator or the '\n', instead
fgets(str, sizeof(str), stdin);
would be safe with any input, although the input string would be trimmed to fit the buffer, but no buffer overflow will occur.
Previous answers have covered avoiding buffer overflows and potential cases where it will not work - to improve performance I would modify the while loop to avoid checking conditions which we know will always be false. e.g. no point in checking if count is less than 0 unless we just decreased the count; no point in checking for an open bracket if the character was a close bracket:
while (str[i] != '\0')
{
if (str[i] == '}')
{
count--;
if (count < 0)
{
printf("\nInvalid");
break;
}
}
else if (str[i] == '{')
count++;
i++;
}
I hope you find this useful and simple ^-^
#include<iostream>
#include<string.h>
using namespace std;
{
string mathEx ;
cout<<"Please Enter math Expression contain ')' , '(' to
check balance \n"<<"MathExpression = ";
cin>>mathEx ;
int i =0 , count = 0 ;
while (mathEx [i] != '\0'){
if(mathEx[i]=='('){
count++;
}
if(mathEx[i]==')'){
count--;
}
if(count<0){
break ;
}
i++;
}
if(count==0){
cout<<"True !";
}
else {
cout<<"Invalid !"<<endl;
}
return 0;
}

How to expect different data types in scanf()?

I'm developing a chess game in C just for practicing. At the beginning of the game, the user can type 4 things:
ROW<whitespace>COL (i.e. 2 2)
'h' for help
'q' to quit
How can I use a scanf to expect 2 integers or 1 char?
Seems like it would be most sensible to read a whole line, and then decide what it contains. This will not include using scanf, since it would consume the contents stdin stream.
Try something like this :
char input[128] = {0};
unsigned int row, col;
if(fgets(input, sizeof(input), stdin))
{
if(input[0] == 'h' && input[1] == '\n' && input[2] == '\0')
{
// help
}
else if(input[0] == 'q' && input[1] == '\n' && input[2] == '\0')
{
// quit
}
else if((sscanf(input, "%u %u\n", &row, &col) == 2))
{
// row and column
}
else
{
// error
}
}
It's better to avoid using scanf at all. It usually causes more trouble than what it solves.
One possible solution is to use fgets to get the whole line and then use strcmp to see if the user typed 'h' or 'q'. If not, use sscanf to get row and column.
This one is just using scanf
#include <stdio.h>
int main()
{
char c;
int row, col;
scanf("%c", &c);
if (c == 'h')
return 0;
if (c == 'q')
return 0;
if (isdigit(c)) {
row = c - '0';
scanf("%d", &col);
printf("row %d col %d", row, col);
}
return 0;
}
int row, col;
char cmd;
char *s = NULL;
int slen = 0;
if (getline(&s, &slen, stdin) != -1) {
if (sscanf(s, "%d %d", &row, &col) == 2) {
free(s);
// use row and col
}
else if (sscanf(s, "%c", &cmd) == 1) {
free(s);
// use cmd
}
else {
// error
}
}
P.S.: those who did not read and understand my answer carefully, please respect yourself, DO NOT VOTE-DOWN AT WILL!
Beside "get the whole line and then use sscanf", read char by char until '\n' was entered is also a better way. If the program encountered 'h' or 'q', it could do the relevant action immediately, meanwhile you cloud also provide a realtime analysis for the input stream.
example:
#define ROW_IDX 0
#define COL_IDX 1
int c;
int buffer[2] = {0,0};
int buff_pos;
while( (c = getchar())) {
if (c == '\n') {
//a line was finished
/*
row = buffer[ROW_IDX];
col = buffer[COL_IDX];
*/
buff_pos = 0;
memset(buffer , 0 , sizeof(buffer));//clear the buffer after do sth...
} else if (c == 'h') {
//help
} else if (c == 'q') {
//quit
} else {
//assume the input is valid number, u'd better verify whether input is between '0' and '9'
if (c == ' ') {
//meet whitespace, switch the buffer from 'row' to 'col'
++buff_pos;
} else {
buffer[buff_pos%2] *= 10;
buffer[buff_pos%2] += c - '0';
}
}
}

Resources