Problem with functions in C (readability) - c

I am working on an exercise in cs50 pset2 readability, and I'm trying to count up how many sentences there are in a text. So far my code is this:
#include<stdio.h>
#include<cs50.h>
#include<string.h>
#include<stdbool.h>
#include<ctype.h>
int isdelim(char c, int sentences)
int main (void)
{
string text = get_string("Text: ");
int sentences = 0;
for(int i = 0; i < strlen(text);i++)
{
sentences = isdelim(text[i], sentences);
}
printf("Sentences: %i\n", sentences);
}
int isdelim(char c, int sentences)
{
return c == '.' || c == '!' || c == '?';
sentences++;
}
But when I do ./readability and I type the text: Hello, world! Beautiful day!, it gives an output of: Sentences:0.
I am new to C so I can't really understand all these functions. I tried searching the web and using other external sources, but nothing makes sense. If you show me the answer, please make sure to tell me why it works, so I can learn. I may need the knowledge in the future. Thanks a lot.

There's several problems.
When you execute a return statement, the function ends. Nothing after that will be executed. So sentences++ is never executed.
In C, function parameters are passed by value. So incrementing sentences in the isdelim() function will not affect the variable in main().
int delim(char c, int sentences); is a function declaration, not a function call. Function calls don't include the type declarations.
You can solve the first problem by using an if statement that checks the condition, rather than returning the result of the condition immediately.
You can solve the second problem by passing a pointer to the variable and dereferencing it, or by having the function return the new value of sentences.
#include<stdio.h>
#include<cs50.h>
#include<string.h>
#include<stdbool.h>
#include<ctype.h>
int isdelim(char c, int sentences);
int main (void)
{
string text = get_string("Text: ");
int sentences = 0;
for(int i = 0; i < strlen(text);i++)
{
sentences = isdelim(text[i], sentences);
}
printf("Sentences: %i\n", sentences);
}
int isdelim(char c, int sentences)
{
if (c == '.' || c == '!' || c == '?') {
sentences++;
}
return sentences;
}

#Baramar makes some good points but I think the code could use a refactoring. The isdelim function is confusing. It's named as a Boolean function, so it should return a bool. And that function shouldn't take a sentences parameter; rather, let the caller handle the incrementing. And I've taken the liberty to call strlen before the loop so it doesn't get recomputed on each iteration. So:
#include<stdio.h>
#include<cs50.h>
#include<string.h>
#include<stdbool.h>
#include<ctype.h>
bool isdelim(char c);
int main (void)
{
string text = get_string("Text: ");
int sentences = 0;
int length = strlen(text);
for (int i=0; i<length; i++)
{
if (isdelim(text[i]))
{
sentences++;
}
}
printf("Sentences: %i\n", sentences);
}
bool isdelim(char c)
{
return c == '.' || c == '!' || c == '?';
}

Related

how to take take variable from main and use it in a function?

So my goal for the moments it write some code that will count the amount of sentences, words, and letters in a set of string that is inputed by the user. My problem however is that when i try to use the user input for my functions that i will later call, it does not allow me to use the variable "text" which is the users input, within my functions.
#include <cs50.h>
#include<string.h>
#include <stdio.h>
#include<ctype.h>
int count_letters(string x);
int main(void)
{
string text= get_string("Text: ");
printf("%s", text);
}
int letters=0, words= 1, sentence=0; // Problem lays here I cannot use variable "text" in my functions how do iI make it so I can do that ??
int count_letters(string x) // counter for letters
{
for ( int i =0, t =strlen(text); i<t; i++)
{
if (isalpha(t[i]))
{
letters++;
}
}return letters;
}
int count_words (string x) //counter for words
{
for ( int s =0, y = strlen(text); s<y; s++ )
{
if(isspace(text[s]))
{
words++;
}
}return words;
}
int count_sentences(string x) // counter for sentences
{
for ( int s =0, y = strlen(text); s<y; s++ )
{
if (ispunct(text[s]))
{
sentence++;
}
}return sentence;
}
printf("%s", text);
}
int letters=0, words= 1, sentence=0; // Problem lays here I cannot use variable "text" in my functions how do iI make it so I can do that ??
Here you have a random closing curly bracket. As #Andreas Wenzel pointed out, there is no consistent indentation style. I would use an IDE of sorts, or at least only use tabs for indentation. It would make errors like this easier to spot. I don't even know how this code would compile.

new to c problem with simple game problem with function

im new to c i try to make a little and very simple game of hangedman and i dont know why doesent work get error in gcc "expected declaration or statement at the end of input"
im new to c and ii try very hard to learn it.
im missing something? my function is not right? some advice to learn alghorytmically thinking?
thanx in advance for the hel you gonna give me
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//function to find letter in string
int findletter(char y)
{
char c;
int i;
char secret[] = "outcast";
i = 0;
scanf("%c", &c);
while (c != secret[i] && i < strlen(secret))
i++;
if(c == secret[i])
return (1);
else
return (0);
}
//confirmation letter
int guessed(char a)
{
int z;
char guess [6] = {0};
z = 0;
while(findletter(guess[z]) != 1 && findletter(guess[z]) < 6)
{
z++;
if(findletter(guess[z]) == 1)
return 1;
else
return 0;
//word guessed
int tryguess(char v)
{
int x;
x = 0;
while(findletter(guess[x]) == 0)
{
x++;
if(findletter(guess[x] == 1))
return 1;
else
return 0;
}
}
int main()
{
char secret[] = "outcast";
char letter;
int lives;
char guess [6] = {0};
int i;
lives = 10;
i = 0;
printf("welcome to the hanged man\n");
while(i < 6)
{
if((findletter(secret[i] == 1)))
printf("%c", secret[i]);
else
printf("*\n");
i++;
}
return 0;
}
Correction to your code...
int guessed(char a)
{
int z;
char guess [6] = {0};
z = 0;
while(findletter(guess[z]) != 1 && findletter(guess[z]) < 6)
{
z++;
if(findletter(guess[z]) == 1)
return 1;
else
return 0;
} // you forgot closing while loop here
} // function closing parenthesis
//word guessed
Advice:
I don't know how much you had practice and how much you had learned yet..but on observing your mistake above I would like to suggest that whenever you create function or loop always write its prototype first, let's say you want to create a function for adding two numbers..
STEP 1: write prototype
int add(int x, int y)
{
//then do your stuff here...
return 0;
}
This will eliminate you chances of making error of parentheses...
There are a lot of issues with this program, from both a syntax standpoint and a logical one.
General issues include:
Function guessed and its while loop are not closed (missing }).
There is a lot of unused code (functions and variables).
The line if((findletter(secret[i] == 1))) compares the character value of secret[i] with 1 and passes that result to findletter. This doesn't matter though since you don't use this argument, and take user input within the function.
You have hardcoded strings and lengths, which makes your program less dynamic and harder to change in the future.
Using while loops as guards (in the unused functions tryguess and guessed), that are always exited on the first iteration.
findletter simply checks if secret contains the character c, returning on the first occurrence.
It could be more clearly expressed as:
int findletter(char unused) {
char secret[] = "secret",
c;
scanf(" %c", &c);
for (size_t i = 0; i < strlen(secret); i++)
if (secret[i] == c)
return 1;
return 0;
}
With that said, findletter would be better if you passed both the secret and c as arguments, so that you can use it more generically, and decouple user input from the function itself.
(Or you could simply use the standard library function strchr which achieves a very similar goal.)
The pattern of
if (a == b)
return 1;
else
return 0;
can simply be reduced to
return a == b;
Aside from the issues above, the structure of your program doesn't make much sense. If our program worked, you'd basically be asking the player to guess a word of unknown length, one character of the word at a time. They can also simply guess any letter to display the current one. One could 'solve' the entire word "secret" by simply inputting 's' repeatedly.
The structure of a very basic hangman program is:
Select the word to be guessed. Select number of lives.
Create a blanked version of word to track progress. Display this blanked version, which indicates the length to the player.
Ask the player to guess a letter. Skip those already guessed.
Update all positions in the blanked version where letter appears in the word.
Decrement lives on miss, end game if out of lives.
Check if the amount of characters changed in the blank version matches the length of word.
Win condition, or return to step 3.
There are many different ways to achieve this, and there are likely thousands of examples online.
Here is a rough program that is about as simple as it gets. This showcases the usual structure and flow of a game of hangman.
#include <stdio.h>
#include <string.h>
size_t update_all(char *to, const char *from, size_t len, char g) {
size_t changed = 0;
for (size_t i = 0; i < len; i++)
if (from[i] == g) {
to[i] = g;
changed++;
}
return changed;
}
void play_hangman(const char *word, unsigned lives) {
size_t word_length = strlen(word),
blanked_length = 0;
char blanked[word_length + 1],
guess = '\0';
for (size_t i = 0; i < word_length; i++)
blanked[i] = '*';
blanked[word_length] = '\0';
while (lives) {
printf("The word: [%s]\n"
"(Lives = %u) Enter a guess: ",
blanked,
lives);
scanf(" %c", &guess);
if (strchr(blanked, guess)) {
printf("[%c]: Already guessed!\n", guess);
continue;
}
size_t found = update_all(blanked, word, word_length, guess);
blanked_length += found;
if (!found) {
printf("[%c]: NOT FOUND!\n", guess);
lives--;
} else
printf("[%c]: FOUND!\n", guess);
if (!lives)
puts("Out of lives! You lose!");
else if (blanked_length == word_length) {
printf("You win! Word is [%s].\n", word);
return;
}
}
}
int main(void) {
play_hangman("secret", 10);
}
Note that this program is far from perfect, as it doesn't fully keep track of guessed letters, so the player can guess the same wrong letter multiple times, and lose a life every time. To fix this, we would need even more state, collecting each guess the player makes, and use that data instead of the naive if (strchr(blanked, guess)).
It also makes use of the '*' character as a sentinel value, which would cause confusion if our word contained '*'. To fix this, we could use an array of boolean values indicating the correctly guessed letters in the word thus far, and use this to print our word character-by-character. Or we could restrict character inputs with functions like isalpha.
This program simply serves as an example that for a proper approximation of the typical "Hangman" you need to handle more game state than you have.
(Error handling omitted for brevity throughout this answer.)

I am trying to find the scrabble value of a word using C program

I am always getting the value of each letter I enter as 1 whereas I should get the values as described in the code. Please help find the error in my code.
#include <stdio.h>
#include <ctype.h>
char c;
char num (char c);
int main () {
int sum;
printf("Enter a word:");
c=0;
while (c=getchar() != '\n') {
c=toupper(c);
sum+=c;
}
printf("Scrabble value : %d",sum);
return(0);
}
char num (char c) {
if (c=='A'||c=='E'||c=='I'||c=='L'||c=='N'||c=='O'||c=='R'||c=='S'||c=='T'||c=='U') c=1;
if (c=='D'||c=='G') c=2;
if (c=='B'||c=='C'||c=='M'||c=='P') c=3;
if (c=='F'||c=='H'||c=='V'||c=='W'||c=='Y') c=4;
if (c=='K') c=5;
if (c=='J'||c=='X') c=8;
if (c=='Q'||c=='Z') c=10;
return(c);
}
In short, this will work for you (call num; fixed getchar call in while; initialized sum to 0; no error handling):
#include <stdio.h>
#include <ctype.h>
char c;
char num (char c);
int main () {
int sum = 0;
printf("Enter a word:");
c=0;
while ((c=getchar()) != '\n') {
c=toupper(c);
sum+=num(c);
}
printf("Scrabble value : %d",sum);
return(0);
}
char num (char c) {
if (c=='A'||c=='E'||c=='I'||c=='L'||c=='N'||c=='O'||c=='R'||c=='S'||c=='T'||c=='U') c=1;
if (c=='D'||c=='G') c=2;
if (c=='B'||c=='C'||c=='M'||c=='P') c=3;
if (c=='F'||c=='H'||c=='V'||c=='W'||c=='Y') c=4;
if (c=='K') c=5;
if (c=='J'||c=='X') c=8;
if (c=='Q'||c=='Z') c=10;
return(c);
}
To get this clean, init sum:
int sum = 0;
The logic of your function for determining the value looks OK (maybe apart from the return value),
but you constantly change the parameter c. This does not actually break anything, but looks somewhat confusing. I recommend to change all c= something to return something;.
To have a default handling, change return(c); to return 0;.
Also you never call your function.
Change
sum+=c;
to
sum+=num(c);
Picking up from (absolutely necessary) comment by Some programmer dude (credits),
The expression c=getchar() != '\n' is, due to operator precedence, equal to c=(getchar() != '\n'). This means the value of c will be either 0 or 1, and nothing else. Also note that getchar returns an int, which is important to check for EOF. Lastly, you need to check for EOF or errors in general.
Others have already answered the question, but just for reference, this is how you write a better look-up function:
int get_val (char c)
{
const int VALUES ['Z' - 'A' + 1] =
{
['A' - 'A'] = 1,
['B' - 'A'] = 3,
['C' - 'A'] = 3,
...
};
return VALUES[c - 'A'];
}

Recursive way of display alphabet in c

I am quite newbie in c, so I just starting off with some code, experimenting some stuff, right now I am stuck with this problem in C, creating a function that displays the alphabet in lowercase, on a single line, by ascending order, starting from the letter ’a’.
This is where I am stuck:
#include <stdio.h>
int alfabet(unsigned int i) {
if(i <= 122) {
char litera = i;
return litera;
}
return alfabet(i+1);
}
int main() {
int i = 97;
printf(alfabet(i));
return 0;
}
Here, you won't print anything really interesting. In fact, your application will crash because printf() require at least a char * parameter (a string).
Your alfabet() function seems not so bad, but you should print the letter in it :
int alfabet(unsigned int i)
{
if (i > 'z') {
// Here is the stop condition.
// If the value is higher than 122 ('z' character), we stop recursivity)
return;
}
printf("%c ", i);
// Otherwise, let's call this function with another character
return alfabet(i+1);
}
Target simplicity
void alfabet(int c) {
printf("%c", c);
if (c < 'z') alfabet(c+1);
}
called from main as
alfabet('a');
You may add a printf("\n");
the function prints the character given as parameter
you only call recursively the function with the next character to be printed if necessary, i.e. if the current character is below z.
Something like that:
#include <stdio.h>
void alfabet(char i) {
if(i < 'z')
{
alfabet(i+1);
}
printf("%c", i);
}
int main() {
char i = 'a';
alfabet(i);
return 0;
}
to print zyxwvutsrqponmlkjihgfedcba. Or:
#include <stdio.h>
void alfabet(char i) {
printf("%c", i);
if(i < 'z')
{
alfabet(i+1);
}
}
int main() {
char i = 'a';
alfabet(i);
return 0;
}
to print abcdefghijklmnopqrstuvwxyz
As you are new in this language, the basic thing to know is that each and every character on the keyboard has its own ASCII value ranging from 000 to 127 (i.e. total 128).
Now if you want to print a to z in a single line, the ASCII value for 'a' is 97 and that for 'z' is 122.
So, for printing this on screen you need to learn the basic for loop structure.The syntax for basic for loop is as follows :-
for(expr1;expr2;expr3)
{
Body of the loop;
}
Here, expr1 refers to the initial value of the variable, expr2 refers to the exit condition of the loop and expr3 refers to the increment or decrement value.
So, the code to print a to z is as follows :-
#include<stdio.h>
#include<conio.h>
void main()
{
clrscr();
print_alpha();
getch();
}
void print_alpha()
{
int i;
for(i=97;i<+122;i++)
{
printf("%c",i);
}
}
int main() {
int i = 97;
printf("%c",alfabet(i));
return 0;
}
You Have to provide format specifier in printf (i.e. %c for character, %d for integer) Just check man printf in terminal.
And for printing a to z you can use for loop suggested by #Michel Jord, for printing in one line just put space in place of \n
#include <stdio.h>
void print_alphabets(char i) {
if(i>='a' && i<='z')
{
print_alphabets(i+1);
printf("%c ", i);
}
}
int main() {
char i;
scanf("%c",&i);
print_alphabets (i);
return 0;
}

Check vowels occurence in a string

This is the problem I'm trying to solve:
Input:
First line contains N, the size of the string.
Second line contains the letters (only lowercase).
Output:
Print YES if all vowels are found in the string, NO otherwise.
Constraints:
The size of the string will not be greater than 10,000. 1 ≤ N ≤ 10000
The following code I wrote is always showing NO.
#include <stdio.h>
#include<conio.h>
int main()
{
int a,b,c=0,d=0,e=0,f=0,g=0,i;
char string[10000];
scanf("%d",&a);
scanf("%s",string);
for(i=0;i<a;a++)
{
if(string[i]==('a'))
c=1;
if(string[i]==('e'))
d=1;
if(string[i]==('i'))
e=1;
if(string[i]==('o'))
f=1;
if(string[i]==('u'))
g=1;
}
if((c==1)&&(d==1)&&(e==1)&&(f==1)&&(g==1))
printf("YES");
else
printf("NO");
return 0;
getch ();
}
Here is an infinite loop that causes a problem:
for(i=0;i<a;a++)
You should increment i, instead of a (length of a string). If you fix this one char in loop statement, the program will run well at all. Anyway, I changed your code a bit to be more readable. Take a look if you want, just for your information, sir:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int len, a=0, e=0, i=0, o=0, u=0, it;
char string[10000];
scanf("%d", &len);
scanf("%s", string);
for(it=0;it<len;it++)
{
if(string[it]=='a') a = 1;
else if(string[it]=='e') e = 1;
else if(string[it]=='i') i = 1;
else if(string[it]=='o') o = 1;
else if(string[it]=='u') u = 1;
}
if(a && e && i && o && u) printf("YES\n");
else printf("NO\n");
system("PAUSE");
return 0;
}
I assume you are running your program under Windows, so instead of conio's getch() try to use system("PAUSE") or just even better way to do this (for both Windows for UNIX): getchar()
I've renamed all of your variables, but otherwise left the code the same.
#include <stdio.h>
#include<conio.h>
int main()
{
int foundA = 0, foundE = 0, foundI = 0, foundO = 0, foundU = 0;
int i, length;
char string[10000];
scanf("%d", &length);
scanf("%s", string);
for(i=0; i<length; length++)
{
if(string[i]==('a'))
foundA=1;
else if(string[i]==('e'))
foundE=1;
else if(string[i]==('i'))
foundI=1;
else if(string[i]==('o'))
foundO=1;
else if(string[i]==('u'))
foundU=1;
}
if((foundA==1)&&(foundE==1)&&(foundI==1)&&(foundO==1)&&(foundU==1))
printf("YES");
else
printf("NO");
return 0;
getch ();
}
Looking the the for-loop condition for(i=0; i<length; length++), I think it's pretty clear what's wrong. Instead of incrementing the counter, you're incrementing the length of the string. Eventually, the counter overflows to a negative number, and the loop terminates without ever looking at a character besides the first one. The lesson here is to name your variables properly.
If you want to be picky, then signed integer overflow is undefined behavior, but for most systems, INT_MAX + 1 will be INT_MIN.
This program can be done in more simpler way other as below.
#include <stdio.h>
#include<conio.h>
int main()
{
int i, flag = 0;
char string[10000], *ptr;
char cmp[] = "aeiou";
printf("Please enter string = " );
scanf("%s", string);
i = 0;
while(cmp[i])
{
ptr = string;
while(*ptr)
{
if(cmp[i] == *ptr)
break;
ptr++;
}
if(*ptr != cmp[i++])
{
flag = 1;
break;
}
}
if(flag == 1)
printf("NO");
else
printf("YES");
}
In this program I have used just one flag instead of 5 flags. Always try to write simple code rather then using unnecessary variable and flags.

Resources