Link to question.
I am new to implementing different functions other than main of course. I am having trouble wrapping my head around how to do that because it is not working out for me.
This would be a rather easy solution to put everything into main but I avoided that due to the instructions hinting it's best to create separate functions and overall I think it's cleaner to have the main function just implement your various functions, right?
The problem I was having was getting the respective functions to be able to use other variables so I set some globals up. For some reason I also figured out I could not use a placeholder for the variable when I wanted to test if everything is working fine, instead I had to print the placeholder for the function itself, for e.g printf("%d\n", letter_counter(text) instead of printf("%d\n", letter).
The issue I'm running into now is getting my coleman index function to work, I find that it is not able to print the S value but the L is working fine. Morover, if I call the the letter, word, & sentence function in main (which are commented out right now), this alters my results as well.
I am happy to receive other general pointers you might realize that needs some work. I think I'm just overall confused about getting different functions to work with one another.
#include <stdio.h>
#include <cs50.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
int letter_counter(string text);
int word_counter(string text);
int sentence_counter(string text);
void coleman_liau_formula(string text);
int letter;
int spaces;
int sentences;
int main(void)
{
string text = get_string("Text: ");
//letter_counter(text);
//word_counter(text);
//sentence_counter(text);
coleman_liau_formula(text);
}
// letter counter
int letter_counter(string text)
{
int i; //variable for looping through the string
for (i = 0; i < strlen(text); i++)
{
if (isalpha(text[i]) != 0)
{
letter++;
}
}
return letter;
}
// word counter
int word_counter(string text)
{
int i;
for (i = 0; i < strlen(text); i++)
{
if (isspace(text[i]) != 0)
{
spaces++;
}
}
if (letter == 0)
{
spaces = 0; // by default the program will output 1 word if no letters are inputted. this statement counters that.
return spaces;
}
else
{
return spaces + 1;
}
}
// sentence counter
int sentence_counter(string text)
{
int i = 0;
for (i = 0; i < strlen(text); i++)
{
if (text[i] == '.' || text[i] == '!' || text[i] == '?') //one flaw is that an occurence such as ellipsis would increase the sentence counter
{
sentences++;
}
}
return sentences;
}
void coleman_liau_formula(string text)
{
//float L = ((float) letter_counter(text) / (float) word_counter(text)) * 100;
//float S = ((float) sentence_counter(text) / (float) word_counter(text)) * 100;
//int index = round((0.0588 * L) - (0.296 * S) - 15.8);
/*if (index >=16)
{
printf("Grade 16+\n");
}
else if (index < 1)
{
printf("Before Grade 1\n");
}
else
{
printf("Grade %i\n", index);
}*/
printf("%i\n%i\n%i\n", letter_counter(text), word_counter(text), sentence_counter(text));
}
The counter functions are cumulative. That is if word_counter is called 2 times, it will double the result. That should be all you need to know to make progress.
Related
I'm going to make a palindrome which should ignore spaces and special characters and should convert all uppercase letters in the string to lowercase. I have done everything, but when I run my program, neither of these two functions work. Convert uppercase to lowercase and ignore all non-uppercase letters. Could any of you help me to solve what is the problem?
#include<stdio.h>
#define SIZE 1000
#include <ctype.h>
#include<string.h>
// function that checks if it is a palindrome
int isPalindrome(char inputString[]) {
int l = 0;
int r = strlen(inputString) - 1;
while (r > l)
{
// will check all letters are equal to each other
if (inputString[l++] != inputString[r--]) {
return 0;
}// return 0 if not palindrome
}
// palindrome
return 1;
}
// function that ignores all non - letters
int no_special_characters(char inputString[])
{
char temp[SIZE];
int temp_index = 0;
int abc = 0;
int r = strlen(inputString);
for (int i = 0; i < r; i++)
{
char abc = inputString[i];
if (isalpha(abc) != 0)
{
temp[temp_index++] = abc;
}
}
temp[temp_index] = '\0';
return isPalindrome(temp);
}
// function that converts uppercase letters to lowercase
void to_lower(char inputstring[]) {
int length = strlen(inputstring);
for (int i = 0; i < length; i++)
{
if (isupper(inputstring[i]))
inputstring[i] = tolower(inputstring[i]);
else if (islower(inputstring[i]))
inputstring[i] = toupper(inputstring[i]);
}
return 0;
}
int main(void) {
int try_again = 1;
int end_run = 0;
while (try_again == 1) {
int try_again;
char inputString[SIZE] = "";
printf("Enter a string to check if it is a palindrome!\n");
//Scans the input string.
scanf_s("%s", &inputString, SIZE);
//Sends the string to the isPalindrome function. //If the return value is 1(true), the if statement is executed, otherwise the else statement.
if (isPalindrome(inputString)) {
printf("That is a palindrome!\n");
}
else {
printf("This is not a palindrome!\n");
}
printf("Do you want to try again: 1 for yes 0 for No?");
scanf_s("%d", &try_again);
//Changes the value of running depending on whether you want to continue or not.
if (try_again != 1) {
end_run = 0;
}
}
return 0;
}
1 - Don't use scanf
You shouldn't use scanf to read input from the console, especially in a loop. I'm not an expert in scanf_s in particular, but that whole family of functions can cause weird bugs if you don't know how they work. I recommend you read this article, it explains it better that I can.
2 - Your loop doesn't work
You are defining try_again in function scope and then redefining it in block scope: they are two different variables.
Your code is essentially this:
int main(void) {
int try_again = 1;
while (try_again == 1) {
int try_again;
scanf_s("%d", &try_again);
}
}
Which will run forever, since the while loop is checking the first variable, while you are assigning to the second one. It should look more like this:
int main(void) {
int try_again = 1;
while (try_again == 1) {
// int try_again;
// ^^ Don't refefine - use the one already defined
try_again = some_function_to_read_input();
}
}
3 - to_lower doesn't actually convert to lowercase
It converts uppercase to lowercase and lowercase to uppercase. This means "Aa" becomes "aA", which is not a palindrome even though it should be by your definition.
The function doesn't need to return anything, since it changes the string in place. You can simply call it like this:
int isPalindrome(char inputString[]) {
to_lower(inputString);
// Rest of code
}
4 - You aren't calling no_special_characters
You simply aren't calling it. Either you do it in your main, something like:
// main
if (no_special_characters(inputString)) {
// Rest of code
}
Or you change it to return the modified string and call it from inside isPalindrome:
void no_special_characters(char inputString[]) {
// Remove all special characters, in place
}
int isPalindrome(char inputString[]) {
no_special_characters(inputString);
to_lower(inputString);
// Rest of code
}
I am taking CS50x Harvard on edX, and I'm currently working on problem set 2, readability. I've compiled my code, and it should work to determine the reading level like it's supposed to. However, every time I run the program, no matter what I put in it gives back the answer before grade 1.
Where is the error?
Here's the code.
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
int main(void)
{
// Get text from user
string text = get_string("Text: ");
// Start words on 1 because theres always 1 less space then words
int letters = 0;
int words = 1;
int sentences = 0;
// Count characters
for (int i = 0; i < strlen(text); i++)
{
// Check for letters
if (isalpha(text[i]))
{
letters++;
}
// Check for spaces
else if (text[i] == ' ')
{
words++;
}
else if (text[i] == '.' || text[i] == '?' || text[i] == '!')
{
sentences++;
}
}
float L = (float)letters / (float)words * 100;
float S = (float)words / (float)sentences * 100;
int index = (int)round(0.0588 * L - 0.296 * S - 15.8);
if (index > 16)
{
printf ("Grade 16+\n");
}
else if (index < 1)
{
printf ("Before Grade 1\n");
}
else
{
printf ("Grade %i\n", index);
}
}
You got your formulae for L and S incorrect
Here's the correct formulae
float L = ((float)letters*100) / (float)words;
float S = ((float)sentences*100) / (float)words;
L is the average number of letters per 100 words and S is the average number of sentences per 100 words, reference here.
If you had only printed out the intermediate values of L and S and compared them to your expectations then you would have seen the error immediately. Learning how to debug your own code is a vital skill for a programmer.
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 can't get my head around this problem, I'm doing the CS50 class on edX and try to solve the Week 2 task, being my first time doing some C coding.
I write this script to return the number of letters in a given input by user, but it seems that the functions are not connecting to each others.
What I'm trying to do here its get an input text from getText function and pass the return value to validChars function and two more funtions that I did not write yet. Then get the return values from validChars sentences and wholeText functions to the main function to perform a Math problem.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
string getText(string text);
int validChars(int vch);
int main(void)
{
int mainchars = validChars(vc);
printf("Letras : %i", mainchars);
printf("\n");
}
string getText(string ctext)
{
string text = get_string("Text: ");
return text;
}
int validChars(int vch)
{
string text = getText(text);
int vc;
int n;
n = strlen(text);
for (int i = 0; i < n; i++)
{
if (text[i] >= 'a' && text[i] <= 'z')
{
vc++;
}
else if (text[i] >= 'A' && text[i] <= 'Z')
{
vc++;
}
}
return vc;
}
I get the error: use of undeclared identifier 'vc' on line 11. I been stuck on this for the last hours today trying to solve it myself but without any luck.
Thanks in advance.
You're passing vc as an argument when you call validChars, but you never declared this variable, so you get an error due to using an undeclared variable. The variable is local to the validChars function, but that doesn't make it available in main.
There's no need for that to be a parameter to the function, it never uses the parameter. The function should take text as a parameter, and you should call getText() in main().
You shouldn't test character ranges, use the built-in isalpha() function.
You need to initialize vc to 0 before you can use it as a counter.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
string getText(string text);
int validChars(void);
int main(void)
{
string text = getText(text);
int mainchars = validChars(vc);
printf("Letras : %i", mainchars);
printf("\n");
}
string getText(string ctext)
{
string text = get_string("Text: ");
return text;
}
int validChars(string text)
{
int vc = 0;
int n = strlen(text);
for (int i = 0; i < n; i++)
{
if (isalpha(text[i]))
{
vc++;
}
}
return vc;
}
You call the function with parameter vc. vc is not defined in main or in the global scope.
Parameter vch is not needed as you do not pass any information from the called to the function.
Amended code:
int validChars(void);
int main(void)
{
int mainchars = validChars();
printf("Letras : %i", mainchars);
printf("\n");
}
string getText(string ctext)
{
string text = get_string("Text: ");
return text;
}
int validChars()
{
string text = getText(text);
int vc=0;
int n;
n = strlen(text);
for (int i = 0; i < n; i++)
{
if (text[i] >= 'a' && text[i] <= 'z')
{
vc++;
}
else if (text[i] >= 'A' && text[i] <= 'Z')
{
vc++;
}
}
return vc;
}
I could not readily find your CS50 problem set.
The compiler error you are receiving is telling you the variable vc has not yet been declared (defined) before trying to use it. The computer starts executing the lines of code within main() and hasn't been told what value vc represents.
int main(void)
{
int mainchars = validChars(vc);
printf("Letras : %i", mainchars);
printf("\n");
}
I have a kind of logical assignment here in my class. So my question is when I try to strcpy() a string into another string, There's a (like space) in my new string. I don't know how to delete that, perhaps my mistake. Please help me, thank you.
This program let's you type whatever letters or symbol on your keyboard and try to capture it and count the symbol. Then, return it.
Here's my code in C
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <string.h>
#define N 25
typedef char string[N];
int main(int argc, char *argv[])
{
int i,j;
int jumlah[10];
string inputan;
string temp;
int counter;
//Init
for(i=0;i<10;i++) {
jumlah[i]=0;
}
for(i=0;i<10;i++) {
temp[i]='-';
}
for(i=0;i<10;i++) {
inputan[i]='-';
}
do {
system("cls");
printf("\nMasukan kalimat: ");fflush(stdin);gets(inputan);
if(strcmpi(inputan,"0")!=0) {
strcpy(temp,inputan);
}
getch();
}while(strcmpi(inputan,"0")!=0);
printf("Hasil Analisa:\n\n");
for(i=0;i<10;i++) {
if(temp[i]!='-') {
char c = temp[i];
for(j=0;j<10;j++) {
if(temp[j]!='-') {
if(c == temp[j])
counter+=1;
}
}
jumlah[i] = counter;
counter = 0;
}
}
for(i=0;i<10;i++) {
if(temp[i]!=' ' && temp[i]!='-' && temp) {
printf("\t%c terdapat %d\n",temp[i],jumlah[i]);
}
}
getch();
}
And here's my console result:
So that's make the program will show the space symbol and count it.
And if I can ask again, how to display only one char if there's a symbol again in another index that have same symbol. Thx, forgive me if my English is not fluent.
The space(s) showing up at the end of your printout are because the list of test conditions you include:
if(temp[i]!=' ' && temp[i]!='-' && temp)
May be missing some additional conditions that need to be excluded:
1) added additional test: test[i] != 0
2) changed temp[i] != ' ' to !isspace(temp[i]), which will test against all white space.
Once these are added:
if(!isspace(temp[i]) && temp[i]!='-' && temp && (temp[i] != 0))
The text entered is printed only down to the last non-whitespace character.
Code modifications:
I added some other minor modifications to the following code that allowed the code to be compiled in my environment. Because my modifications use functions that are part of the C standard libraries, this should compile for you as well.
Changes also include expanding for(...) loops to accommodate the array sizes you created, enabling input up to N-1 characters as opposed to only 10. Most of what I did includes commented explanations.
int main(int argc, char *argv[])
{
int i,j;
//int jumlah[10];
int jumlah[N]; // probably meant to use N here?
string inputan = {0};
string temp = {0};
int counter = 0;// initialize
for(i=0;i<N;i++) {
jumlah[i]=0;
}
for(i=0;i<N-1;i++) {
temp[i]='-';
}
for(i=0;i<N-1;i++) {
inputan[i]='-';
}
do {
//system("cls"); This is fine, just does not work in my environment, so commented.
//printf("\nMasukan kalimat: ");fflush(stdin);gets(inputan);
printf("\nPut Sentence (or \"0\" to process): ");fflush(stdin);gets(inputan);// clarified instructions.
if(stricmp(inputan,"0")!=0) { //strcmpi
strcpy(temp,inputan);
}
//getch(); this (or getchar()) is really not necessary here to support
// the flow of your application.
}while(stricmp(inputan,"0")!=0);
printf("Hasil Analisa:\n\n");
for(i=0;i<N;i++) { //replace 10 with N
if(temp[i]!='-') {
char c = temp[i];
for(j=0;j<N;j++) { //replace 10 with N
if(temp[j]!='-') {
if(c == temp[j])
//counter+=1;
counter++; // var++ equivalent var += 1
}
}
jumlah[i] = counter;
counter = 0;
}
}
for(i=0;i<N;i++) {
//if(temp[i]!=' ' && temp[i]!='-' && temp) { // only spaces ?
if(!isspace(temp[i]) && temp[i]!='-' && temp && (temp[i] != 0)) { // temp[i] != 0, and exclude all white space
printf("\t%c terdapat %d\n",temp[i],jumlah[i]);
}
}
getchar(); //orig getch() not standard
}
Addressing your question: how to display only one char if there's a symbol again in another index that have same symbol.
Displaying a list of the characters used, and the number of times used might be better handled in a separate function. The one below can be adapted to be called in your original main function by inserting the following lines:
char *res = letterCounter("this is the string");
printf(res);
free(res);
Just under your existing line: printf("Hasil Analisa:\n\n");
(i.e. replace all your code under that line down to the getch(); function;
char * letterCounter(const char *string)
{
int i, j;
int len = strlen(string);
char *dup = StrDup(string);
if(!dup) return NULL;
int viewableAscii = '~' - '!'; /// range of ASCII from ! to ~ (33 - 126)
char buf[20];
char * results = calloc(100*strlen(string), 1);//ensure enough room
if(!results) return NULL;
/// caps 'A' == 65, 'Z' == 90
/// lowr 'a' == 97, 'z' == 122
/// all visable printables: 33 - 126
unsigned char characterUsageCounter[viewableAscii];
memset(characterUsageCounter, 0,viewableAscii);
for(i=0;i<len;i++)
{
for(j=0;j<viewableAscii;j++)
{
if(dup[i] == 33 + j)
{
characterUsageCounter[j]++;
}
}
}
for(i=0;i<viewableAscii;i++)
{
if(characterUsageCounter[i] > 0)
{
if(characterUsageCounter[i] == 1) sprintf(buf, "%c occurs %d time\n", i+33, characterUsageCounter[i]);
else sprintf(buf, "%c occurs %d times\n", i+33, characterUsageCounter[i]);
strcat(results, buf);
}
}
return results;
}
For example, if the string "this is the string" were passed as the argument to that function, the following would be output: