Wrong calculations - arrays

#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <math.h>
int letters = 0;
int words = 0;
int sentences = 0;
int main(void)
{
string text = get_string("Text: ");
printf("\n");
for(int j = 0; j < strlen(text); j++)
{
if((text[j] >= 'a' && text[j] <= 'z') || (text[j] >= 'A' && text[j] <= 'Z'))
{
letters++;
}
if(text[j] == ' ')
{
words++;
}
if(text[j] == '.' || text[j] == '?' || text[j] == '!')
{
sentences++;
}
}
printf("Letters: %i\n", letters);
printf("Words: %i\n", words + 1);
printf("Sentences: %i\n", sentences);
float L = ((float)letters / (float)words) * 100;
float S = ((float)sentences / (float)words) * 100;
float result = round(0.0588 * L - 0.296 * S - 15.8);
printf("%f\n", L);
printf("%f\n", S);
printf("%f\n", result);
if(result < 1)
{
printf("Before Grade 1");
}
if(result == 1)
{
printf("Grade 1");
}
if(result == 2)
{
printf("Grade 2");
}
if(result == 3)
{
printf("Grade 3");
}
if(result == 4)
{
printf("Grade 4");
}
if(result == 5)
{
printf("Grade 5");
}
if(result == 6)
{
printf("Grade 6");
}
if(result == 7)
{
printf("Grade 7");
}
if(result == 8)
{
printf("Grade 8");
}
if(result == 9)
{
printf("Grade 9");
}
if(result == 10)
{
printf("Grade 10");
}
if(result == 11)
{
printf("Grade 11");
}
if(result == 12)
{
printf("Grade 12");
}
if(result == 13)
{
printf("Grade 13");
}
if(result == 14)
{
printf("Grade 14");
}
if(result == 15)
{
printf("Grade 15");
}
if(result >= 16)
{
printf("Grade 16+");
}
printf("\n");
}
Text:
Congratulations! Today is your day. You're off to Great Places! You're off and away!
Result:
Letters: 65
Words: 14
Sentences: 4
500.000000
30.769232
4.000000
Grade 4
I need to calculate the '0.0588 * L - 0.296 * S - 15.8' formula in my code, but for some reason, it is giving me the wrong answer for some text and right for some text. in this particular example, it should give me 'Grade 3' but it is giving me 'Grade 4' instead and if I put a text for grade 10 it will give me 'Grade 10'. And the calculations for 'L' and 'S' are wrong, in this example, they should be L = 464.29 and S = 28.57. I really don't know where I am going wrong, can someone please help me?

The problem is that you count words by counting spaces, so you don't count the last word. You could solve the problem by initialising words to 1.
Also I saw you noticed that problem since you wrote printf("Words: %i\n", words + 1); so why in your calculations didn't you added 1? You print 14 as word count, but then you use 13 to calculate the average length of the words.
Anyway you should absolutely change the final prints with that
if(result < 16) {
printf("Grade %d\n", result);
}
else {
puts("Grade 16+");
}
Or even just
result < 16 ? printf("Grade %d\n", result) : puts("Grade 16+");

It appears you have counted words inadequately. You counted the number of spaces between words, which gives a number that is one fewer than the number of words. This is adjusted for when printing the number, in printf("Words: %i\n", words + 1);, and when calculating S, in printf("Words: %i\n", words + 1);, but not when calculating L, in float L = ((float)letters / (float)words) * 100;.
Changing that last line to float L = ((float)letters / (float)(words+1)) * 100; results in the answer you expect, “Grade 3”.
However, a better solution is likely to initialize words with int words = 1; instead of int words = 0; and change the printf and the calculation of S to use words instead of words + 1.
(Further, a more sophisticated program would consider what happens if spaces appear before any words, after the last word, or multiple times between words.)

Related

CS50 credit doesn't run for some numbers

My code seems to work on some credit card numbers but for others it doesn't even run. I've tried to use long long for the credit card number but it didn't worked. I've spent like 2 hours trying to solve this issue but I can't figure it out. All help is welcomed :)
int main(void)
{
// Get credit card number
long num = get_cc_number();
// Check if the credit card number is valid
valid = check_sum(num);
// Check the length of the credit card number
length = check_length(num);
// Get the first two digits of the credit card number and first number of VISA
digits = get_first_digits(num);
digit_visa = digits / 10;
// Check if the card is American Express, Mastercard, Visa or Invalid
if (valid == 1)
{
if (length == 16)
{
if (digits <= 55 && digits >= 51)
{
printf("MASTERCARD\n");
}
else if (digit_visa == 4)
{
printf("VISA\n");
}
else
{
printf("INVALID\n");
}
}
else if (length == 15)
{
if (digits == 34 || digits == 37)
{
printf("AMEX\n");
}
else
{
printf("INVALID\n");
}
}
else if (length == 13)
{
if (digit_visa == 4)
{
printf("VISA\n");
}
else
{
printf("INVALID\n");
}
}
}
else
{
printf("INVALID\n");
}
}
long get_cc_number(void)
{
long cc_number;
cc_number = get_long("Credit Card Number: ");
return cc_number;
}
int check_sum(int num)
{
int num1 = num;
while (num1 >= 10)
{
sec_to_last = num1 % 100;
double_sec_to_last = sec_to_last * 2;
if (double_sec_to_last >= 10)
{
first_dig = double_sec_to_last / 10;
sec_dig = double_sec_to_last % 10;
first_sum += first_dig;
first_sum += sec_dig;
}
else
{
first_sum += double_sec_to_last;
}
num1 = num1 / 100;
}
int num2 = num;
while (num2 >= 10)
{
last = num2 % 10;
second_sum += last;
}
second_sum += first_sum;
if (second_sum % 10 == 0)
{
return 1;
}
else
{
return 0;
}
}
long check_length(long num)
{
long num_length = floor(log10(labs(num))) + 1;
return num_length;
}
long get_first_digits(long num)
{
long i = num;
while (i >= 100)
{
i /= 10;
}
return i;
}
A while back, I reviewed an issue like this where the user was getting tripped up on acquiring a credit card check digit. With that, I wrote a small proof-of-principle test program that allows validation of credit card numbers using the Luhn algorithm. Following, is that code snippet.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int check_valid(char * num)
{
int sum = 0;
int work = 0;
char card[20];
if ((strlen(num) %2 == 0)) /* Even numbers - do not need a leading zero */
{
strcpy(card, num);
}
else /* Odd numbers - add a leading zero to evaluate */
{
strcpy(card, "0");
strcat(card, num);
}
printf("Length of number is: %d\n", (int)strlen(num));
for (int i = 0; i < strlen(card); i++)
{
work = card[i] - '0';
if ((i %2) == 0)
{
work = (card[i] - '0') * 2;
if (work > 9)
{
work = work - 9;
}
}
sum = sum + work;
printf("Digit is: %d Value is: %d Sum is %d\n", (card[i]- '0'), work, sum);
}
return ((sum % 10) == 0);
}
int main()
{
char number[20];
int x = -1;
printf("Enter a number: ");
x = scanf("%s", number);
x = check_valid(number);
if (x == 0)
printf("Invalid\n");
else
printf("Valid\n");
return 0;
}
It doesn't identify the card issuer, just verifies that the number is valid.
As noted in the comments, one probably would want to utilize a string entry as this code snippet does rather than trying to utilize a very large integer. You might try going that route with a string as well. Give this a try and see if it allows you to progress.

Printing a calendar for a given year and month

I'm trying to build a program that will print out the month and year that the user inputs. What I have so far ends up with the year having 5 digits and inputting "2020 2" results in 28 days for the month of February.
The code I have so far in this assignment:
#include <stdio.h>
#include<stdlib.h>
int is_leapyear(int y)
{
if ((y % 100 == 0 && y % 100 != 0) || y % 400 == 0)
return 1;
else
return 0;
}
int main()
{
int i, j, year, month;
printf("Please enter the year and month:");
scanf("%d", &year);
scanf("%d", &month);
int a[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
int la[13] = { 0,31,29,31,30,31,30,31,31,30,31,30,31 };
int c = 1;
int flag = 0;
if (is_leapyear(year))
flag = 1;
for (i = 0; i<month; i++)
{
if (flag == 1)
c += la[i];
else
c += a[i];
}
int s = (year - 1) + ((year - 1) / 4) + ((year - 1) / 400) - ((year - 1) / 100) + c;
int week = s % 7;
printf("Calendar " );
printf("%-d", year);
if (month < 10)
printf("0");
printf(" %d\n", month);
printf("----------------------\n");
printf("Su Mo Tu We Th Fr Sa \n");
printf("----------------------\n");
if (flag == 1) {
for (j = 0; j < week; j++)
{
printf(" ");
}
for (i = 1; i <= la[month]; i++)
{
if ((week + i - 1) % 7 == 0)
{
printf("\n");
}
if (i < 10)
{
printf(" ");
}
printf("%d", i);
printf(" ");
}
}
else {
for (j = 0; j < week; j++)
{
printf(" ");
}
for (i = 1; i <= a[month]; i++)
{
if ((week + i - 1) % 7 == 0)
{
printf("\n");
}
if (i < 10)
{
printf(" ");
}
printf("%d", i);
printf(" ");
}
}
printf("\n");
printf("---------------------\n");
}
The output:
Any help would be greatly appreciated.
Edit: It seems like I was too careless in reviewing my code, minor mistakes observed and problem solved!
The century check on your isleapyear()
if ((y % 100 == 0 && y % 100 != 0) || y % 400 == 0)
is flawed. It checked if the year is divisible by 100 and not divisible by 100, which is a logical impossibility. I think you actually mean
if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0)
So check if the year is divisible by 4 and not divisible by 100.
As for the 20200, it's because your leading zero for the month is printed before the space is printed. Just change it to
printf("%-d", year);
printf(" "); //put space right away
if (month < 10)
printf("0");
printf("%d\n", month); //no need to print space here
or even better as pointed out by #JonathanLeffler in the comment
printf(" %.2d\n", month);
It deals with space, the leading zero, and the new line in just one call, or just
printf("Calendar %.4d %.2d\n", year, month);
to handle those three parts at once
OP's is_leapyear(int y) fails with various multiples of 4.
Instead:
// Alternative for Gregorian calendar
int is_leapyear(int y) {
if (y % 4 == 0) {
if (y % 100 == 0) { // A century year?
return (y % 400 == 0);
}
return 1;
}
return 0;
}
Deeper: Leap year.

Readability for cs50. There valuable changes for no reason at "if" line

So I started programming 5 days ago. I'm going through course cs50. There is a task (see https://cs50.harvard.edu/x/2020/psets/2/readability/) to make a program which evaluates grade of text. I did it.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
int main(void) {
int ln = 0;
int wn = 1;
int sn = 0;
string text = get_string("write your text:\n");
int l = strlen(text);
for (int i = 0; i < l; i++) {
if (isalpha(text[i])) {
ln++;
}
if ((char) (text[i]) == (char) (' ')) {
wn++;
}
if ((char) (text[i]) == (char) ('.') | (char) (text[i]) == ('!')
| (char) (text[i]) == ('?')) {
sn++;
}
}
float grade = ((float) ((ln / wn * 100) * 0.0588)
- ((float) ((sn / wn * 100) * 0.296)) - 15.8);
if (grade > 1 && grade < 16) {
printf("Grade %f\n", grade);
} else if (grade < 1) {
printf("Before grade 1\n");
} else if (grade > 16) {
printf("grade 16+\n");
}
printf("%i, %i, %i", ln, wn, sn);
}
And when I uses debugger, I can see that at that long line, where I do all the math, float grade is equal just to the number I need, everything is fine. But right after it, where "if" starts, it becomes 1.8 for no reason. I tried to change different parameters, and the math is still right till the if line. What do I do wrong?
Code at least has this problem: Nothing printed when grade is 1 or 16
// Nothing printed when grade is 1 or 16
if (grade > 1 && grade < 16) {
printf("Grade %f\n", grade);
} else if (grade < 1) {
printf("Before grade 1\n");
} else if (grade > 16) {
printf("grade 16+\n");
}
Suggest
// >= <=
if (grade >= 1 && grade <= 16) {
printf("Grade %f\n", grade);
} else if (grade < 1) {
printf("Before grade 1\n");
} else {
printf("grade 16+\n");
}
Integer division likely wrong. Use FP division.
// vvvvvvv vvvvvvv
// float grade = ((float) ((ln / wn * 100) * 0.0588) - ((float) ((sn / wn * 100) * 0.296)) - 15.8);
float grade = 0.0588 * ln / wn * 100 - 0.296 * sn / wn * 100 - 15.8;
Improvements
// if ((char) (text[i]) == (char) (' ')) {
if (text[i] == ' ') {
// if ((char) (text[i]) == (char) ('.') | (char) (text[i]) == ('!') | (char) (text[i]) == ('?')) {
if (text[i] == '.' || text[i] == '!' || text[i] == '?') {

How to Fix the Logic Errors in My "Guess the Movie" Game as a C Program

I have written a Guess the Movie game in the C programming language. My logic seems to be correct but whenever I run the program, it doesn't work as expected.
Here is my code
#include <stdio.h>
#include <stdlib.h>
int main()
{
int ran = 1;
int l, j = 0, i = 0, total = 0, d = 0;
char b;
char a[20];
char s[1000];
int z;
FILE *my;
printf("Enter your name:\n ");
scanf("%s", s);
ran = rand() % 6;
if (ran == 1)
{
my = fopen("my1.txt", "r");
}
else if (ran == 2)
{
my = fopen("my.txt", "r");
}
else if (ran == 3)
{
my = fopen("my2.txt", "r");
}
else if (ran == 4)
{
my = fopen("my3.txt", "r");
}
else if (ran == 5)
{
my = fopen("my4.txt", "r");
}
for (d = 0; d < 20; d++)
fscanf(my, "%c", &a[d]);
fclose(my);
printf("GUESS THE MOVIE GAME\n");
for (j = 0; j < 7; j++)
{
if (a[j] == 'm')
{
printf("M ");
}
else
{
printf("_ ");
}
}
printf("\n");
printf("Let's begin the game\n");
for (i = 0; i < 7;)
{
if (a[i] != 'm')
{
printf("enter character number %d\n",i+1);
scanf("%c", &b);
if (b == a[i])
{
printf("its a right guess\n");
total = total + 4;
i++;
}
else if (b != a[i])
{
printf("Wrong choice\n");
if (total == 1 || total == 0)
{
total=0;
}
else
{
total = total - 2;
}
}
}
}
printf("You have guessd the movie\n");
printf("The movie name is: ");
for (i = 0; i < 7; i++)
{
printf("%c",a[i]);
}
printf("Your score is %d\n",total);
}
This is the program output that I get each time I run the above code:
Enter your name:
raj
GUESS THE MOVIE GAME
_ _ _ _ M _ _
Let's begin the game
Enter character number 1
Wrong choice
Enter character number 1
I
Wrong choice
Enter character number 1
Wrong choice
Enter character number 1
Besides the deficiencies pointed out in comments, there's this major logic error:
for (i = 0; i < 7;)
{
if (a[i] != 'm')
{
…
}
}
If the loop encounters an m, it repeats endlessly. Eliminate the if (a[i] != 'm') or add an else ++i.

C1075: end of file found before the left brace '{' was matched - can't resolve this.

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <iostream>
#include <cstdlib>
using namespace std;
#include "bcio2.h"
int error, x;
char totalimpulse[80], averageimpulse[80], ejection[50], emptymass[50], enginemass[50], fuelmass[50];
char launch[50];
void validate_number();
int main(void)
{
clrscr();
do{
printf("\nTotal Impulse delivered: ");
gets(totalimpulse);
validate_number();
} while (error != 0);
do{
printf("\nAverage Impulse delivered: ");
gets(averageimpulse);
validate_number();
} while (error != 0);
do{
printf("\nTime that ejection charge fires: ");
gets(ejection);
validate_number();
} while (error != 0);
do{
printf("\nThe mass of the empty vehicle: ");
gets(emptymass);
validate_number();
} while (error != 0);
do{
printf("\nThe mass of the engine: ");
gets(enginemass);
validate_number();
} while (error != 0);
do{
printf("\nThe mass of fuel: ");
gets(fuelmass);
validate_number();
} while (error != 0);
printf("\nRocket parameters entered: \n");
printf("\nTotal Impulse delivered: %s\n", totalimpulse);
printf("Average Impulse delivered: %s\n", averageimpulse);
printf("Time that ejection charge fires: %s\n", ejection);
printf("The mass of the empty vehicle: %sg\n", emptymass);
printf("The mass of the engine: %sg\n", enginemass);
printf("The mass of fuel: %sg\n", fuelmass);
char ans;
do
{
cout<< "\nLaunch simulation? (Y/N) : \n";
cout<< "You must type a 'Y' or an 'N'.\n";
cin >> ans;
}
while((ans !='Y')&&(ans !='N')&&(ans !='y')&&(ans !='n'));
if (ans == 'N')
{
getchar();
return 0;
}
else if (ans == 'Y')
{
// do something, calculations display page
return 0;
}
}
/************ Test all input in range 0 to 9 ****************/
void validate_number()
{
int errange = 0, numonly = 0, errlength = 0;
/********* validate numbers ********/
error = 0;
for (x = 0; x<strlen(totalimpulse); x++){
if (totalimpulse[x] >= '0' && totalimpulse[x] <= '9'); else{
numonly++;
error++;
}
for (x = 0; x<strlen(averageimpulse); x++){
if (averageimpulse[x] >= '0' && averageimpulse[x] <= '9'); else{
numonly++;
error++;
}
for (x = 0; x<strlen(ejection); x++){
if (ejection[x] >= '0' && ejection[x] <= '9'); else{
numonly++;
error++;
}
for (x = 0; x<strlen(emptymass); x++){
if (emptymass[x] >= '0' && emptymass[x] <= '9'); else{
numonly++;
error++;
}
for (x = 0; x<strlen(enginemass); x++){
if (enginemass[x] >= '0' && enginemass[x] <= '9'); else{
numonly++;
error++;
}
for (x = 0; x<strlen(fuelmass); x++){
if (fuelmass[x] >= '0' && fuelmass[x] <= '9'); else{
numonly++;
error++;
}
}
/********* validate range ********/
if (strlen(totalimpulse) <= 3){
x = atoi(totalimpulse);
if (x >= 0 && x <= 256)
;
else{
errange++;
error++;
}
}
else{
errlength++;
error++;
}
/**************** Report errors ******************/
if (error != 0){
if (numonly>0)
printf("\nOnly values in the range 0 to 9 are valid ");
if (errange>0)
printf("\nValue must be in the range 0 to 255");
if (errlength>0)
printf("\nMore than three values were entered");
}
I've counted 21 open braces and 21 closed braces which all seem to be positioned correctly yet I'm still getting the error, anything a fresh pair of eyes can help me with? I've counted the brackets so many times over that I'm going crazy.
It's a basic error for a basic problem but I'm just clueless as to what to change or add.
You have 27 open braces in the code.
[11:05am][wlynch#watermelon ~] fgrep -o '{' /tmp/asd.cc | wc -l
27
[11:05am][wlynch#watermelon ~] fgrep -o '}' /tmp/asd.cc | wc -l
21
Notably, there are two open braces in this piece of code, but only 1 closing brace:
for (x = 0; x<strlen(totalimpulse); x++){
if (totalimpulse[x] >= '0' && totalimpulse[x] <= '9'); else{
numonly++;
error++;
}
Additionally, this isn't invalid, but is awfully written:
if (averageimpulse[x] >= '0' && averageimpulse[x] <= '9'); else{
Please write it as:
if (not (averageimpulse[x] >= '0' && averageimpulse[x] <= '9')) {
or:
if (averageimpulse[x] < '0' || averageimpulse[x] > '9')) {

Resources