I'm having some trouble doing a Nim game program. So far I have a program that will show a pyramid of pipes. It looks like the "start position" pyramid on this picture.
http://www.mathsisfun.com/puzzles/images/b-nim.gif
Anyways, I'm having trouble moving around this, whenever I try moving around, my cursor will move in completely erratic ways. Thid will make the game totally unplayable. I'm not sure if it is a problem with my counting variables or even some smaller thing I'm totally missing, anyways here's what I have:
#include <stdlib.h>
int nim()
{
char *tab;
if ((tab = malloc(sizeof(char) * 20 + 4)) == NULL)
return (-1);
tab = " | \n ||| \n ||||| \n |||||||\n"; /* this is indeed a nasty way to do it :P */
putstr(tab);
}
int move_normally()
{
char bffr[10];
int x;
int y;
x = 0;
y = 0;
while (42 && x <= 6 && y <= 3)
{
read(0, bffr, 10);
putstr(tgoto(tgetstr("cm", NULL), x, y);
if (bffr[2] == 66 && y <= 3 && x <= 6)
y++
else if (bffr[2] == 65 && x <= 6 && y <= 3 && (y - 1) >= 0)
y = y - 1;
else if (bffr[2] == 67 && x <= 6 && y <= 3)
x++
else if (bffr[2] == 68 && x <= 6 && y <= 3 && (x - 1) >= 0)
x++
}
}
So, is there something I'm missing here? everything else works almost perfectly and I can't get my hands on why this is giving trouble. Also, are there any other ways to do this? I'm open to any alternative way.
Related
When I am trying to get the input for my variable, it is only meeting one of the requirements (ie: the < 1 requirement) and skips the other requirement even though im using the && operator.
#include <cs50.h>
#include <stdio.h>
int main(void)
{
int x;
do {
x = get_int("what is the height of the pyramid?:");
} while (x > 0 && x < 8);
printf("%i", x);
}
I tried just using the x < 8 for the requirement but it still went through when I entered 9, 10, 11 etc.
If you want x to be between 0 and 8 (both ends exclusive), then you need to repeatedly ask for input when this condition is not satisfied.
In other words, when x is outside this range it means x is less than or equal to 0 OR greater than or equal to 8.
That said, I believe the proper input range for that problem set is actually 1-8 (both ends inclusive):
do {
x = get_int("What is the height of the pyramid?: ")
} while (x < 1 || x > 8);
The test is exactly the opposite of your intent. The do/while condition should test a condition for repeating the input and write while (!(x > 0 && x < 8)); or equivalently: while (x < 1 || x >= 8);
It is unclear what your requirements are, but it seems the number should be between 1 and 7 inclusively. If 8 should be included, the test should be modified as while (!(x > 0 && x <= 8)); or equivalently: while (x < 1 || x > 8);
do/while loops are often confusing and error prone. I suggest using a for(;;) aka for ever loop and break statements when conditions are met:
#include <cs50.h>
#include <stdio.h>
int main(void)
{
int x;
for (;;) {
x = get_int("What is the height of the pyramid? ");
if (x == INT_MAX) {
printf("Input error or end of file\n");
return 1;
}
if (x > 0 && x < 8) {
break
}
printf("The height should be between 1 and 7\n");
}
printf("%i\n", x);
return 0;
}
So the main issue is that the addition of (-5 to 4) to the characters in the entered string is all messed up to show possible words that were encrypted. When the loop runs the enter characters are not the starting point thus throwing everything else off. Additionally, I cannot get the repeat = false statement to register.
#include<stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
int main()
{
char encrypted_string[100];
char z;
char stop[]="STOP";
int x=-5, y, len;
bool repeat = true;
while (repeat)
{
printf("Enter the encrypted word (type STOP to quit) : ");
fgets(encrypted_string, 100, stdin);
if (strcmp(encrypted_string, stop)== 0)
{
repeat = false;
}
//len=strlen(encrypted_string);
while (x < 5)
{
for (y = 0; encrypted_string[y] != '\0'; y++)
{
z = encrypted_string[y];
if (z >= 97 && z <= 122)
{
z=z+x;
if (z < 97)
{
z=z+(122-97)+1;
}
encrypted_string[y] = z;
}
else if (z >= 65 && z <= 90)
{
z=z+x;
if (z < 65)
{
z=z+(90-65)+1;
}
encrypted_string[y] = z;
}
}
printf("For shift of %d, decrypted word is %s\n", x++, encrypted_string);
}
}
return 0;
}
char stop[]="STOP";
fgets(encrypted_string, 100, stdin);
if (strcmp(encrypted_string, stop)== 0)
fgets() leaves the trailing newline in the buffer, so this will never be true if the user hit enter at the end of the line.
if (z >= 97 && z <= 122)
These look a bit like magic numbers, probably better to write 'a' and 'z' instead.
if (z >= 97 && z <= 122) {
z=z+x;
if (z < 97)
What if the increment x is positive? z could go over 122.
Actually, why is it named x? It's the shift offset, so call it that.
Similarly, y is an index, so perhaps i instead. Especially confusing is that you have x, y and z that are three totally different things.
while (x < 5) {
for (y = 0; encrypted_string[y] != '\0'; y++) {
...
encrypted_string[y] = z;
You're modifying the same string you read again on the next iteration. For the input foo, it does a shift of -5 giving ajj, then a shift of -4 from that, giving wff, etc.
any ideas why this is generating a floating point exception? Please ignore the bad coding. This is very rough and I am just trying to experiment different things on this assignment. Also, I trying to do this assignment with only the operations learned in class (I am awere there are others that would make this easier)
Thanks!
#include <stdio.h>
#include <cs50.h>
int main(void)
{ long c = get_long("What is your credit card number?\n");
long i = 10;
long j = 100;
long n = 0;
long m = 0;
long x = 2;
do
{ long a = (c % i - (c % i)/10)/(i/10);
n = a + n;
i = i*100;
}
while (c/i >= 0.1 || c/i == 0);
do
{ long b = (c%j - (c%j)/10)/(j/10);
m = b + m;
j = j*100;
}
while (c/j >= 0.1 || c/j == 0);
long sum = n + 2*m;
if (i > j)
{
x = i;
}
else
{
x = j;
}
if (sum % 10 == 0)
{ if((x == 10000000000000000) && ((c % (x/100) - c % (x/1000))/(x/100000) == (34)))
{
printf("Amercan Express\n");
}
else if((x == 100000000000000000) && ((c % (x/100) - c % (x/1000))/(x/100000) == (51)))
{
printf("MasterCard\n");
}
else if((x == 10000000000000) && ((c % (x/100) - c % (x/1000))/(x/100000) == 4))
{
printf("Visa\n");
}
else if((x == 10000000000000000) && ((c % (x/100) - c % (x/1000))/(x/100000) == 4))
{
printf("Visa\n");
}
else
{
printf("Invlid\n");
}
}
else
{
printf("Invlid\n");
}
}'''
This is the part that is the problem:
while (c/i >= 0.1 || c/i == 0);
in your first do while loop.
Your data types are long and so you are saying that as long as c/i is greater than 0.1 or == 0 then keep going. Unfortunately this will go on forever as a long will always be >= 0.1 or <= 0 because it cant hold decimal places.If you play around with debug50 by using debug50 ./filename you can place a red dot and step through. What you will see is the first do while loop will keep running increasing the value of i every cycle. Eventually the value of i is bigger than the memory limit for a long and so the code creates unexpected results.If you step through you find that it eventually assigns 0 to i and so you suffer a divide by 0 error.
You can fix this by changing data types or altering that while loop.
I hope that helps. Id suggest stepping through that do while loop using debug50 in the cs50 ide to see whats going on.
I'm a first time programmer trying to complete a simple command line program as part of the first assignment for an online course I am taking, but I seem to have hit a roadblock that I can't figure out with GDB or my own research.
After hours of rewrites, and hours of debugging, I finally got the code below to compile. The program is supposed to take a credit card number as an input, and then check whether it's valid per the specifications of the assignment. I used a test number from here: PayPal Test Credit Cards
The odd thing is, when I enter an AMEX card number, it correctly produces the text "AMEX", but when I try a Visa or a Master Card, it prints "INVALID".
In GDB I broke at the Verify function and it seems to incorrectly skip these two if/else if statements without proceeding to the Checksum function even though conditions appear to be met.
if (firstDigit == 4 && totalDigits == (13 | 16) && Checksum(cardNumber, totalDigits) == 0) // checks for a valid Visa.
...
else if (firstDigit == 5 && secondDigit == (1 | 2 | 3 | 4 | 5) && totalDigits == 16 && Checksum(cardNumber, totalDigits) == 0) // checks for a valid Mastercard.
...
The AMEX line of code that correctly executes is:
else if (firstDigit == 3 && secondDigit == (4 | 7) && totalDigits == 15 && Checksum(cardNumber, totalDigits) == 0) // checks for a valid American Express.
The arguments for all three lines seem to be formatted exactly the same. That is far as I could get in GDB though. I would print totalDigits, firstDigit, and secondDigit in GDB right before stepping through the above two non-executing lines and everything looked correct. So I'm stumped, why is the AMEX line executing, but not the others?
Thanks in advance everyone. This is the first program after hello.c that I've tried to write, so I am open to absolutely any criticism or suggestions if it looks like I'm doing something weird/wrong.
Full code:
checker.c
#include <stdio.h>
#include <stdlib.h>
int MAX = 16;
int* DigitSort(unsigned long long x, int* array);
int Verify(int* array);
int main (void)
{
int* output = malloc (sizeof(int) * (MAX + 2)); // creates a blank array for the individual digits of the card number.
unsigned long long userInput = 0;
do
{
printf("Please enter a credit card number:\n");
scanf("%lld", &userInput);
}
while (userInput <= 0); // checks to make sure the user entered a number.
switch(Verify(DigitSort(userInput, output))) // sorts the user's input into individual digits and verifies the card type and validity.
{
case 1 :
printf("VISA\n");
break;
case 2 :
printf("MASTERCARD\n");
break;
case 3 :
printf("AMEX\n");
break;
case 0 :
printf("INVALID\n");
break;
default :
printf("INVALID\n");
}
free(output);
return 0;
}
int Verify(int* array) // verifies whether or not a card number is valid. Must pass the function a sorted array of individual digits.
{
int* cardNumber = array;
int firstDigit = cardNumber[0];
int secondDigit = cardNumber[1];
int totalDigits = 0;
int Checksum(int* cardNumber, int totalDigits);
int i = 0;
while (firstDigit >= 1 && cardNumber[i] >= 0) // this step counts the number of digits in the array.
{
totalDigits = totalDigits + 1;
i++;
}
if (firstDigit == 4 && totalDigits == (13 | 16) && Checksum(cardNumber, totalDigits) == 0) // checks for a valid Visa.
{
return 1;
}
else if (firstDigit == 5 && secondDigit == (1 | 2 | 3 | 4 | 5) && totalDigits == 16 && Checksum(cardNumber, totalDigits) == 0) // checks for a valid Mastercard.
{
return 2;
}
else if (firstDigit == 3 && secondDigit == (4 | 7) && totalDigits == 15 && Checksum(cardNumber, totalDigits) == 0) // checks for a valid American Express.
{
return 3;
}
else // if the card number doesn't match any of the above conditions or fails the checksum, an 'I' for Invalid is returned.
{
return 0;
}
}
int* DigitSort(unsigned long long x, int* array) // takes a long long as input and sorts it into individual digits
{
int* arrayReversed = malloc (sizeof(int) * (MAX + 2)); // creates a new array to hold the reversed order of digits.
int i = 0;
arrayReversed[0] = 0;
if (i < (MAX - 1) && x >= 10)
{
do
{
arrayReversed[i] = x % 10;
x = x / 10;
i++;
}
while (i < (MAX -1) && x >= 10);
}
if (i < MAX && x >= 1 && x <= 9)
{
arrayReversed[i] = (int) x;
x = (x - x);
}
if (x == 0)
{
int j = 0;
do
{
array[j] = arrayReversed[i]; // sorts the digits from the reversed array and places them into the sorted array.
j++;
i--;
}
while (j < MAX && i >= 0);
array[j] = -1;
}
free(arrayReversed);
return array;
}
int Checksum(int* cardNumber, int totalDigits)
{
int sum1 = 0;
int sum2 = 0;
int i = (totalDigits - 2);
int j = (totalDigits - 1);
while (i >= 0)
{
sum1 = ((cardNumber[i] * 2)%10) + ((cardNumber[i] * 2)/10) + sum1;
i -= 2;
}
while (j >= 0)
{
sum2 = (cardNumber[j] + sum2);
j -= 2;
}
if (((sum1 + sum2) % 10) == 0)
{
return 0;
}
else
{
return 1;
}
}
Your first problem is here:
if (firstDigit == 4 && totalDigits == (13 | 16) && ...
You need to write:
if (firstDigit == 4 && (totalDigits == 13 || totalDigits == 16) && ...
Your first check is looking for 0x1D == 29 as the number of digits (because, as paisanco points out in a comment, the | operator is the bitwise OR operator), and no credit card needs 29 digits (yet, and not for a long time to come). Note the extra parentheses for clarity and accuracy. Don't mess around risking removing them — the code won't work properly again. And in general, be explicit if your condition has both && and || operators and use parentheses to group terms explicitly.
You have similar problems elsewhere. As it happens, (4 | 7) is the same value as 7, so the condition works when the second digit is 7 (but not when it is 4). But it doesn't mean what you intended it to mean.
Computer languages don't work the same as human languages. Get used to writing out the condition somewhat more verbosely. Some other languages provide shorthands for these conditions; C is not such a language.
I'm trying to solve the Adding Reversed Numbers problem (ADDREV) at the Sphere Online Judge but my submission keeps coming up wrong answer.
I've tried int, unsigned int, long, and unsigned long for my variables and they all work equally well on my computer with some test data (also below) but they all fail the SPOJ.
I'm hoping someone might be able to shed some insight into why my program would be failing on their system. I've also left a message on their forum but there doesn't seem to be a lot of traffic.
Here's my code:
#include <stdio.h>
#define FIRST 1
#define SECOND 2
int main()
{
int c, k, x, y, state, place, total, reverse = 0;
do
{
c = getchar();
if (c < 48 || c > 57)
{
continue;
}
else
{
k = k * 10;
k = k + (c - 48);
}
} while (c != '\n');
state = FIRST;
place = 1;
do
{
c = getchar();
if (c == ' ')
{
state = SECOND;
place = 1;
continue;
}
else if (c == '\n')
{
total = x + y;
place = 1;
while ((total / place) >= 10)
{
place = place * 10;
}
while (place > 0)
{
reverse = reverse + ((total % 10) * place);
total = total / 10;
place = place / 10;
}
printf("%d\n", reverse);
state = FIRST;
place = 1;
reverse = 0;
x = 0;
y = 0;
k--;
continue;
}
if (state == FIRST && (c >= 48 && c <= 57))
{
x = x + ( (c - 48) * place );
place = place * 10;
}
else if (state == SECOND && (c >= 48 && c <= 57))
{
y = y + ((c - 48) * place );
place = place * 10;
}
} while (k > 0);
return 0;
}
And... here's the test data I'm using:
12
24 1
4358 754
305 794
2762 2563
435 4320
0 0
123 456
20 20
10000 10000
999999 999999
321 583
9999999 999999
And here's the results my program gives on my computer:
34
1998
1
4236
867
0
579
4
2
8999991
805
89999901
Any help would be appreciated :)
At this point:
int c, k, x, y, state, place, total, reverse = 0;
you create a variable k but give it no value. Shortly after:
k = k * 10;
you use this variable. At that point, your program exhibits undefined behaviour - anything might happen.