cs50: pset1: credit: Stuck, all cards entered invalid - c

Been working on this problem set for the past few hours and I thought I was doing pretty well, but when I ran it, doesn't really work as expected.
Kinda stuck at the moment, can anyone offer some insight?
EDIT
Sorry guys, I'll provide a little more insight on the problem because too little info is provided for it in my post. So basically I have to implement the Luhn's algorithm. According to Luhn’s algorithm, you can determine if a credit card number is (syntactically) valid as follows:
Multiply every other digit by 2, starting with the number’s second-to-last digit, and then add those products’ digits together.
Add the sum to the sum of the digits that weren’t multiplied by 2.
If the total’s last digit is 0 (or, put more formally, if the total modulo 10 is congruent to 0), the number is valid!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
printf("type a credit card number: ");
char ccnum[17];
fgets(ccnum, 17, stdin);
int ccnumber[15];
int n = strlen(ccnum);
for (int i = 0; i<16; i++)
{
ccnumber[i] = ccnum[i] -'0';
}
int ccnumber_m[7];
for (int i = 0; i < 16; i+=2)
{
ccnumber_m[i] = ccnumber[i]*2;
}
int sum = 0;
for (int i = 0; i < 8; i++)
{
if (ccnumber_m[i] > 9)
{
sum += (ccnumber_m[i] % 10) + 1;
}
else
{
sum += ccnumber_m[i];
}
printf("%d\n", sum);
}
for (int i = 1; i < 16; i+=2)
{
sum += ccnumber[i];
}
if (sum%10 == 0)
{
if ( (n == 15) && (ccnumber[0] == 34 || ccnumber[0] == 37))
{
printf("AMEX\n");
}
else if ((n == 16) && (ccnumber[0] == 51 || ccnumber[0] == 52 ||ccnumber[0] == 53 || ccnumber[0] == 54 || ccnumber[0] == 55))
{
printf("MASTERCARD\n");
}
else if ((n == 13 || n == 16) && ccnumber[0] == 4)
{
printf("VISA\n");
}
}
else
{
printf("INVALID\n");
}
}
I've added a printf to my sum variable to see where the program is failing and that's where things seem to be screwing up. Every time I run it, different values of sum appear?!
Thanks in advance.

Okay guys, found the solution. Yes I messed up most of my loops and the array ranges and the conditions were all over the place. Did some tweaks to my code overall and after a few more hours, the code works as expected. Here's the updated code.
Pretty sure the code could be more succinct and could be solved much faster. Will take a look at it tomorrow again in order to brainstorm more ideas and find ways to solve it faster.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
printf("type a credit card number: ");
char ccnum[17];
fgets(ccnum, 17, stdin);
int ccnumber[15];
int n = strlen(ccnum);
int counter = 0;
for (int i = 0; i < n; i++)
{
ccnumber[i] = ccnum[i] -'0';
if (ccnumber[i] >= 0)
{
counter ++;
}
}
int sum = 0;
if (counter == 16)
{
int ccnumber_m[7];
int index = 0;
for (int i = counter - 2; i > -1 ; i-=2, index++)
{
ccnumber_m[index] = ccnumber[i]*2;
}
for (int i = 0; i < 8; i++)
{
if (ccnumber_m[i] > 9)
{
sum += (ccnumber_m[i] % 10) + 1;
}
else
{
sum += ccnumber_m[i];
}
}
for (int i = 1; i < counter + 1; i+=2)
{
sum += ccnumber[i];
}
}
else if (counter == 15)
{
int ccnumber_m[6];
int index = 0;
for (int i = counter-2; i > 0; i-=2, index++)
{
ccnumber_m[index] = ccnumber[i]*2;
}
for (int i = 0; i < 7; i++)
{
if (ccnumber_m[i] > 9)
{
sum += (ccnumber_m[i] % 10) + 1;
}
else
{
sum += ccnumber_m[i];
}
}
for (int i = 0; i < counter + 1; i+=2)
{
sum += ccnumber[i];
}
}
else if(counter == 13)
{
int ccnumber_m[5];
int index = 0;
for (int i = counter-2; i > 0; i-=2, index++)
{
ccnumber_m[index] = ccnumber[i]*2;
}
for (int i = 0; i < 6; i++)
{
if (ccnumber_m[i] > 9)
{
sum += (ccnumber_m[i] % 10) + 1;
}
else
{
sum += ccnumber_m[i];
}
}
for (int i = 0; i < counter + 1; i+=2)
{
sum += ccnumber[i];
}
}
else
{
printf("INVALID\n");
return 0;
}
if (sum%10 == 0)
{
if ((counter == 15) && ((ccnumber[0] == 3 && ccnumber[1] == 4) || (ccnumber[0] == 3 && ccnumber[1] == 7)))
{
printf("AMEX\n");
}
else if ((counter == 16) && ((ccnumber[0] == 5 && ccnumber[1] == 1) || (ccnumber[0] == 5 && ccnumber[1] == 2) || (ccnumber[0] == 5 && ccnumber[1] == 3) || (ccnumber[0] == 5 && ccnumber[1] == 4) || (ccnumber[0] == 5 && ccnumber[1] == 5)))
{
printf("MASTERCARD\n");
}
else if ((counter == 13 || counter == 16) && (ccnumber[0] == 4))
{
printf("VISA\n");
}
else
{
printf("INVALID\n");
return 0;
}
}
else
{
printf("INVALID\n");
return 0;
}
}

Related

(CS50x Credit) expected "INVALID\n", not "VISA\n"

Task: the user enters the card number and needs to determine whether the card is valid and, if so, determine the type of card (Visa, MasterCard, American Express). We have [https://cs50.harvard.edu/college/2021/spring/psets/1/credit/#luhns-algorithm][Luhn's Algorithm] to determine the validation of card number.
Problem: sometimes programm identifies invalid card as Visa(for example: 4111111111111113, 4222222222223). I really don't know how to solve this problem( I've already seen other solutions of this CS50 Credit task, but since I'm a beginner, I want to know what's wrong exactly with this code. I would be grateful for any hints on this problem and the code as a whole. Appreciate your help!
#include <cs50.h>
#include <stdio.h>
#include <math.h>
int main(void)
{
long credit;
do
{
credit = get_long("Number of card:\n");
}
while (credit < 0);
long number = credit;
int digits;
for (digits = 0; number > 0; digits++)
{
number /= 10;
}
int checksum = 0;
int i;
for (i = 0; number > 0; i++, number /= 10)
{
if (i % 2 == 0)
{
checksum += (number % 10);
}
else
{
int n = (number % 10) * 2;
if (n > 9)
{
n = (n / 10) + (n % 10);
}
checksum += n;
}
}
checksum = checksum % 10;
if ((checksum == 0) && ((credit >= 34e13 && credit < 35e13) || (credit >= 37e13 && credit < 38e13)))
{
printf("AMEX\n");
}
else if ((checksum == 0) && (credit >= 51e14 && credit < 56e14))
{
printf("MASTERCARD\n");
}
else if ((checksum == 0) && ((credit >= 4e12 && credit < 5e12) || (credit >= 4e15 && credit < 5e15)))
{
printf("VISA\n");
}
else
{
printf("INVALID\n");
}
}
Code changes number
for (digits = 0; number > 0; digits++) {
number /= 10;
}
int checksum = 0;
int i;
Consider the value of number after the above loop. Certainly 0. Next loop does not iterate.
for (i = 0; number > 0; i++, number /= 10)
Code needs to preserve number.

Why does writing this program output me weird strings?

I am trying to code minesweeper in C. I started out with assigning the values to a 2D array then print it. I tried everything but it didn't work.
This happens in my sample output:
The code is:
#include <stdio.h>
#include <stdlib.h>
struct Tile {
unsigned char isMine : 1;
char status;
};
int main() {
struct Tile arr[9][9];
unsigned char i;
unsigned char c;
unsigned char count = 10;
srand((unsigned)time(0));
for (i = 0; i < 9; i++) {
for (c = 0; i < 9; i++) {
if(rand() % 81 + 1 < count && arr[i][c].isMine == 0 && count > 0) {
arr[i][c].isMine = 1;
arr[i][c].status = 'X';
count--;
} else if (arr[i][c].isMine == 0) {
arr[i][c].status = '.';
}
}
if (count == 0) {
break;
} else {
continue;
}
}
for (i = 0; i < 9; i++) {
for (c = 0; c < 9; c++) {
printf("%c", arr[i][c].status);
}
printf("\n");
}
return 0;
}
Please help.
You never visit any fields in your loops except the 1st column due to incorrect loop header:
for (i = 0; i < 9; i++) {
for (c = 0; i < 9; i++) {
if(rand() % 81 + 1 < count && arr[i][c].isMine == 0 && count > 0) {
arr[i][c].isMine = 1;
arr[i][c].status = 'X';
count--;
} else if (arr[i][c].isMine == 0) {
arr[i][c].status = '.';
}
}
if (count == 0) {
break;
} else {
continue;
}
}
This will leave all other fields uninitialized and when you try to print it, strange things may appear.
Also as you only visit each field once (or at least that seems to be your intention), there is no need to check isMine at all. If you initialize properly, it must be 0 anyway.
Which of course requires that you intitialize properly as already mentioned in David's answer.
The condition can be reduced a bit more as the first part (..+1<count) already implies that count>0. No need to check again.
Finally, continue as last instruction of a loop is not really useful.
Your code could look like this:
struct Tile arr[9][9] = {{0}};;
...
for (i = 0; i < 9; i++) {
for (c = 0; c < 9; c++) {
if(rand() % 81 + 1 < count) {
arr[i][c].isMine = 1;
arr[i][c].status = 'X';
count--;
} else {
arr[i][c].status = '.';
}
}
if (count == 0) {
break;
}
}
Initialize the array:
struct Tile arr[9][9] = {{0}};
otherwise you read an uninitialized value (leading to undefined behaviour) in:
} else if (arr[i][c].isMine == 0) {
arr[i][c].status = '.';
}

CS50 Credit Problem is skipping "else if" part

I am really stuck here. The programm gives right answer to invald credit card numbers but never say if its VISA, AMEX or MASTERCARD.
I need to post the complete code because I do not have so much experience wit the C language.
The checksum part in the end could also have been "bool" but I always got error messages with that.
#include <cs50.h>
#include <stdio.h>
int main(void)
{
long long card;
int checksum = 0;
do
{
card = get_long_long("Number: ");
}while (card <= 0);
int count = 0;
while (card != 0) {
card /= 10; // n = n/10
++count;
}
if(count != 16 && count != 13 && count != 15){
printf("INVALID\n");
}
else if(checksum != 0){
printf("INVALID\n");
}
else if(card >= 34e13 || card >= 37e13){
printf("AMEX\n");
}
else if(card >= 51e14 || card >= 52e14 || card >= 53e14 || card >= 54e14 || card >= 55e15) {
printf("MASTERCARD\n");
}
else if(card >= 4e15 || card >=4e12) {
printf("VISA\n");
}
else {
printf("INVALID\n");
}
}
int checksum(long long card_nr)
{
int sum = 0;
for (int i=0;card_nr !=0; i++, card_nr/=10 )
{
if(i % 2 == 0)
sum += card_nr % 10;
else
{
int digit = 2 * (card_nr % 10);
sum += digit / 10 + digit % 10;
}
}
return (sum % 10) == 0;
}
There may be major issue or only some parenthesis, the programm is compiling. Thanks for any help.
There are many errors with the logic:
#include <cs50.h>
#include <stdio.h>
int main(void)
{
long long card;
int checksum = 0;
do
{
card = get_long_long("Number: ");
}while (card <= 0);
int count = 0;
// ** In here you destroy card, so later card whill allways be 0
while (card != 0) {
card /= 10; // n = n/10
++count;
}
if(count != 16 && count != 13 && count != 15){
printf("INVALID\n");
}
else if(checksum != 0){
printf("INVALID\n");
}
//** here it is the same as if(card >= 34e13)
else if(card >= 34e13 || card >= 37e13){
printf("AMEX\n");
}
//** here it is the same as if(card >= 51e14)
//** also these values are already covered by last check
else if(card >= 51e14 || card >= 52e14 || card >= 53e14 || card >= 54e14 || card >= 55e15) {
printf("MASTERCARD\n");
}
//** here it is the same as if(card >= 4e15)
//** also these values are already covered by previous check
else if(card >= 4e15 || card >=4e12) {
printf("VISA\n");
}
else {
printf("INVALID\n");
}
}
int checksum(long long card_nr)
{
int sum = 0;
for (int i=0;card_nr !=0; i++, card_nr/=10 )
{
if(i % 2 == 0)
sum += card_nr % 10;
else
{
int digit = 2 * (card_nr % 10);
sum += digit / 10 + digit % 10;
}
}
return (sum % 10) == 0;
}```
After loop:
while (card != 0) {
card /= 10; // n = n/10
++count;
}
card = 0 and original card number is lost.
You can save original card number to another variable and then compare it.
Also it is better to use integer constants like 54LL << 14 instead of float 54e14

Why am I still getting the "expected identifier" error?

I'm new to programming (currently learning C and working alongside the cs50x course). I'm doing the Problem Set 1, Card. I'm supposed to make a program where you type a credit card number and it gives you the type of credit card (AMEX, VISA, etc). I need help with this error: "Error: expected identifier or '('"
Here is the code:
#include <stdio.h>
#include <cs50.h>
void print_credit_card_brand(long long ccn);
bool check_validity(long long credit_card_number);
int find_lenght(long long n);
bool checksum(long long ccn);
int main(void)
{
long long credit_card_number;
do
{
credit_card_number = get_long_long("Number: \n");
}
while (credit_card_number < 0);
if (check_validity(credit_card_number) == true)
print_credit_card_brand(credit_card_number);
else
printf ("INVALID\n");
}
bool check_validity(long long credit_card_number);
{
int len = find_lenght(credit_card_number);
return (len = 13 || len = 15 || len = 16) && checksum(credit_card_number);
}
int find_lenght(long long n);
{
int len;
for (int len = 0; n ! = 0; n/=10, len++)
return len;
}
bool checksum(long long ccn);
{
int sum = 0;
for (int i = 0; ccn!= 0; i++; ccn/= 10)
{
if(i % 2 == 0)
sum += ccn % 10;
else
{
int digit = 2 * (ccn % 10);
sum += digit / 10 + digit % 10;
}
return (sum % 10) == 0;
}
}
void print_credit_card_brand(long long ccn);
{
if ((ccn >= 34e13 && ccn < 32e13) || (ccn >= 37e13 && ccn < 38e13))
printf ("AMEX\n");
else if (ccn >= 51e14 && ccn < 56e14)
printf("MASTERCARD\n");
else if ((ccn >= 4e12 && ccn < 5e12) || (ccn >= 4e15 && ccn < 5e15))
printf("VISA\n");
else printf("INVALID\n");
}
Remove semicolon here. :D
bool check_validity(long long credit_card_number); <--------
{
int len = find_lenght(credit_card_number);
return (len = 13 || len = 15 || len = 16) && checksum(credit_card_number);
}
int find_lenght(long long n); <---------
.
.
.
You have some typos in your code:
Every function definition has an extra ; at the end, remove them all.
bool checksum(long long cc);
{ ^
//...
}
This:
return (len = 13 || len = 15 || len = 16) && checksum(credit_card_number);`
^ ^ ^
You probably want ==.
This:
for (int i = 0; ccn!= 0; i++; ccn/= 10)
^
You probably want:
for (int i = 0; ccn!= 0; i++, ccn/= 10)
This:
for (int len = 0; n ! = 0; n/=10, len++)
^
You'll want to remove that space and make it !=.

Segfault on disease simulator

I am trying to program a disease simulator in C. For some reason after around 20-25 iterations of the while(1) loop, it segfaults. It is completely random. I have been trying to fix this problem for several hours, so any help would be much appreciated.
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
typedef struct space {
int type;
int x, y;
} space_t;
space_t space[40][40];
int main(){
bool infected = false;
int i = 0;
int x = 0;
int y = 0;
srand(time(NULL));
while(i < 1600){
space[x][y].x = x;
space[x][y].y = y;
if(rand() % 9 == 0 && !infected){
space[x][y].type = 1;
infected = true;
}
if(rand() % 20 == 8){
space[x][y].type = 2;
}
x++;
i++;
if(x == 40){
x = 0;
y++;
}
}
system("clear");
int count;
int inf = 0;
while(1){
x = 0;
y = 0;
i = 0;
while(i < 1600){
if(space[x][y].type == 1){
inf++;
}
if(space[x][y].type == 1 && rand() % 9 > 4){
if(rand() % 9 > 4){
space[x+(rand() % 3)][y].type = 1;
} else {
space[x+(-(rand() % 3))][y].type = 1;
}
} else if(space[x][y].type == 1 && rand() & 9 > 4){
if(rand() % 9 > 4){
space[x][y+(rand() % 3)].type = 1;
} else {
space[x][y+(-(rand() % 3))].type = 1;
}
}
if(space[x][y].type == 1){
printf("[I]");
} else if(space[x][y].type == 2){
printf("[D]");
} else printf("[ ]");
x++;
i++;
if(x == 40){
printf("\n");
x = 0;
y++;
}
}
count++;
printf("%d\n", count);
printf("%d\n", inf);
sleep(1);
system("clear");
}
return 0;
}
Code generates random offsets for an index but does not insure in proper range.
if(space[x][y].type == 1 && rand() % 9 > 4){
if(rand() % 9 > 4){
// Nothing forces `x+(rand() % 3)` in legal index range.
space[x+(rand() % 3)][y].type = 1;
} else {
space[x+(-(rand() % 3))][y].type = 1;
}
}
Instead
if(space[x][y].type == 1 && rand() % 9 > 4) {
int r = rand();
if(r % 9 > 4) {
int offset = x + r%3;
if (offset < 40) space[offset][y].type = 1;
} else {
int offset = x - r%3;
if (offset >= 0) space[offset][y].type = 1;
}
}
... // similar change for next block
Note: later on code, certainly rand() & 9 should be rand() % 9 (% not &).

Resources