Not sure why it exits the loop (in C) - c

I have my code to run until the user inputs "0 0 0" to stop the program
but my program stops after one loop. I tried adding a print in the inner loop to see what the values were and maybe they were all getting set 0.
my example input
5 10 6
5 3 4 2 4
output
p = 4, s = 9, c = 6
p = 3, s = 6, c = 6
p = 2, s = 4, c = 6
p = 1, s = 0, c = 6
Scenario #1: MHR rides coaster #4, using the single rider line.
I can see that p, s, and c are not all 0 so I don't know why it breaks out of the outer loop when it should just go back to asking for the 3 user input values
#include <stdio.h>
#include <stdlib.h>
int main(){
int p,s,c,h,x=1,coaster;
while(p != 0 && s != 0 && c != 0){
//number of parties, single riders, capacity of ride
scanf("%d%d%d",&p,&s,&c);
//allocate memory
int* parties = malloc(sizeof(int)*p);
for(h=0;h<p;h++){
//get size of each party in line
scanf("%d",&parties[h]);
}
//find the faster line for each scenario
int t = 0;
while(p != 0 || s > 0){
coaster = c - parties[t];
s = s - coaster;
p--;
printf("p = %d, s = %d, c = %d\n",p,s,c);
if(p == 0 && s != 0){
printf("Scenario #%d: MHR rides coaster #%d, using the regular line.\n",x,t+1);
break;
}
if(s <= 0 && p != 0){
printf("Scenario #%d: MHR rides coaster #%d, using the single rider line.\n",x,t+1);
break;
}
if(s <= 0 && p == 0){
printf("Scenario #%d: MHR rides coaster #%d, using either line.\n",x,t+1);
break;
}
t++;
}
x++;
free(parties);
}
return 0;
}

The loop condition you are using is effectively: p not zero AND c not zero AND s not zero. So when s is zero, the condition is false and the loop exits.
The condition you are looking for is NOT (p is zero AND c is zero AND s is zero):
!(p == 0 && c == 0 && s == 0)
There is another bug in the program, you don't initialise p, c or s before checking their value.

Well, you have:
int p,s,c,h,x=1,coaster;
while(p != 0 && s != 0 && c != 0){
which is not good. You check for the values of p, s and c, but they are uninitialized variables!

if you want to quit if everything becomes zero, Change:
while(p != 0 && s != 0 && c != 0)
to:
while(!(p == 0 && s == 0 && c == 0))

Related

Connect Four Check Winner

So to change my question. It refuses to recognize that there are four twos in a row. It recognizes that there are four ones in a row but that happens after the four twos. Why is this happening?
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 1 1 1 1 0 0
1 2 2 2 2 0 0
int checkFour(int a, int b, int c, int d){
if (a == b == c == d){
return 1;
}
else{
return 0;
}
return 0;
}
//check for the horizontal win
int checkHorizontal(){
for(int i=0; i < rows; i++){
for(int j=0; j < column - 3; j++){
if ((board[i][j] != 0) && (board[i][j+1] != 0) && (board[i][j+2]!= 0) && (board[i][j+3] != 0)){
if (checkFour(board[i][j],board[i][j+1],board[i][j+2],board[i][j+3]) == 1){
printf("Game Over\n");
exit(0);
}
}
}
}
}
What am I doing wrong?
if (a == b == c == d){ does not work the way you might think. The result of a comparison in C is a boolean value of 0 or 1. Given that == operator has left-to-right associativity, your statement can be re-written as:
if ((((a == b) == c) == d)
This appears to give correct results when they are all 1. This is because it ends up comparing the values (1) to the result of the comparison operation, also (1).
(((a == b) == c) == d) a == b -> 1
((1 == c) == d) 1 == c -> 1
(1 == d) 1 == d -> 1
The correct way is to use logical AND.
if (a == b && a == c && a == d)
All three comparisons need to evaluate to true for the entire statement to be true.
Note that there are other combinations that work. Ex:
if (a == b && b == c && c == d)
By the way, you can shorten the entire function to
int checkFour(int a, int b, int c, int d){
return a == b && b == c && c == d;
}
The problem is that you misunderstood the mechanism of C. the code if (a == b == c == d) wouldn't take if abcd are all values equal then return 1. because C computes from left to right(same priority), so it would compute a == b first, the result is 1 or 0, then take this result to compare with c, the second result also is 1 or 0, finally take second result to compare with d and the final result is come out.
The right code is like this:
if ((a == b) && (d == c) && (b == c))
return 1;
else
return 0;

Finding certain combination in a text file

I have a text file of combinations without repetition of 6 number ranging from 1 to 10, like this:
2 3 8 9 6 4
8 3 1 4 7 9
1 3 5 7 6 9
1 5 7 9 8 4
1 3 5 4 8 7
2 4 6 8 7 1
6 7 8 3 5 9
3 1 6 2 7 9
1 7 4 2 5 8
3 4 9 2 1 7
...
and I have a gold combination, let's say: 2, 1, 3, 9, 8, 5
I want to check how many times I have a combination in my text file that matches 5 numbers of the gold combination. This is my code attempt:
// Including C Standard Libraries
#include <stdint.h>
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
// Gold Combination
int n1 = 2;
int n2 = 1;
int n3 = 3;
int n4 = 9;
int n5 = 8;
int n6 = 5;
// Numbers of Matching Combinations
int match_comb = 0;
// Creating a file to see combinations content
char ch, file_name[25];
FILE *fp;
fp = fopen("combinations.txt", "r"); // Read Mode
if (fp == NULL)
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
int j = 0;
int mn = 0; // Number of matched numbers
int x[6] = {0,0,0,0,0,0};
char c;
while((c = fgetc(fp)) != EOF)
{
if(c == ' ' || c == '\n')
{
}
else
{
x[j] = c;
if (j == 5)
{
if(x[0]==n1 || x[0]==n2 || x[0]==n3 || x[0]==n5 || x[0]==n6){
mn += 1;
}if(x[1]==n1 || x[1]==n2 || x[1]==n3 || x[1]==n5 || x[1]==n6){
mn += 1;
}if(x[2]==n1 || x[2]==n2 || x[2]==n3 || x[2]==n5 || x[2]==n6){
mn += 1;
}if(x[3]==n1 || x[3]==n2 || x[3]==n3 || x[3]==n5 || x[3]==n6){
mn += 1;
}if(x[4]==n1 || x[4]==n2 || x[4]==n3 || x[4]==n5 || x[4]==n6){
mn += 1;
}if(x[5]==n1 || x[5]==n2 || x[5]==n3 || x[5]==n5 || x[5]==n6){
mn += 1;
}
if ( mn == 5)
{
match_comb += 1; // Adding One the the Match Combinantions counter
}
for (int i = 0; i < 6; ++i) // Resetting x array
{
x[i] = 0;
}
mn = 0; // Resetting
j = -1; // Resetting j
}
j += 1;
}
}
printf("Number of Matching Combinations:");
printf("%d", match_comb);
printf("\n");
fclose(fp);
return 0;
}
But, I think the code is not working, because it always says that there are 0 matched combinations .. Are there ways to simplify or make my code work?
also, this only works for the case of numbers with one digit, but in the case I have bigger range, let's say 1-20, I am not really sure how to gather the numbers from the text file .. I was thinking in a condition where there was a counter after every space, if the counter is one, take the character as a number of one digit, if the counter is two, gather the two characters and do something to tell the code to gather the two characters and use the resulted number, but I don't know how to do that ..
Edit:
int main()
{
// Gold Combination
int n1 = 20;
int n2 = 1;
int n3 = 35;
int n4 = 9;
int n5 = 18;
int n6 = 5;
// Numbers of Matching Combinations
int match_comb = 0;
// Creating a file to see combinations content
char ch, file_name[25];
FILE *fp;
fp = fopen("combinations.txt", "r"); // Read Mode
if (fp == NULL)
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
int j = 0;
int mn = 0; // Number of matched numbers
int x[6] = {0,0,0,0,0,0};
int c;
while((c = fgetc(fp)) != EOF)
{
//x[j] = fscanf(fp, "%d", &c);
fscanf(fp, "%d %d %d %d %d %d", &x[0], &x[1], &x[2], &x[3], &x[4], &x[5]);
printf("%d", x[0]);
printf(" ");
printf("%d", x[1]);
printf(" ");
printf("%d", x[2]);
printf(" ");
printf("%d", x[3]);
printf(" ");
printf("%d", x[4]);
printf(" ");
printf("%d", x[5]);
if(x[0]==n1 || x[0]==n2 || x[0]==n3 || x[0]==n5 || x[0]==n6){
mn += 1;
}if(x[1]==n1 || x[1]==n2 || x[1]==n3 || x[1]==n5 || x[1]==n6){
mn += 1;
}if(x[2]==n1 || x[2]==n2 || x[2]==n3 || x[2]==n5 || x[2]==n6){
mn += 1;
}if(x[3]==n1 || x[3]==n2 || x[3]==n3 || x[3]==n5 || x[3]==n6){
mn += 1;
}if(x[4]==n1 || x[4]==n2 || x[4]==n3 || x[4]==n5 || x[4]==n6){
mn += 1;
}if(x[5]==n1 || x[5]==n2 || x[5]==n3 || x[5]==n5 || x[5]==n6){
mn += 1;
}
if ( mn == 5)
{
match_comb += 1; // Adding One the the Match Combinantions counter
}
for (int i = 0; i < 6; ++i) // Resetting x array
{
x[i] = 0;
}
mn = 0; // Resetting
printf("\n");
}
printf("Number of Matching Combinations:");
printf("%d", match_comb);
printf("\n");
fclose(fp);
return 0;
}
The problem lies with:
x[j] = c;
This assigns a char to an integer. You need to convert c to an integer. For example by subtracting the character code of zero:
x[j] = c-'0';
You can use isdigit(c) to check whether c is really a digit.
Either with the help of the debugger or by using printf to show the exact values of the x[0], x[1], ... you get a clearer view of what was going wrong.
As for reading numbers of more than 1 digit, the best idea is to use a function such as fscanf(fp, "%d", &c) which automatically converts the read characters to a number. Note that if you use &c here, c needs to be an int, not a char.
If you want to work with fscanf, you need to remove the calls to fgetc (in your while-loop), because otherwise fgetc everytime removes a character. Removing a character is no problem when that's a space or a newline, but it is a problem for the first digit in the line. When fgetc can not be used anymore for checking end-of-file, use the return value of fscanf as explained in this post. For example:
while (true) // endless loop, but will end via a 'break'
{
// remove if(c == ' ' || c == '\n')
if (fscanf(fp, "%d", &c) != 1) // check whether fscanf found 1 input
break; // this jumps out of the while loop
.... // rest of your code
}
If you really want to use fgetc for reading the numbers, you need something like:
if (isdigit(c))
num = num * 10 + (c - '0');
and not yet putting num in the X-array until you encounter a non-digit. num needs to be reset to 0 thereafter.
As for the code you use for calculating the number of matches, it looks quite clever if you're fully new to programming. An improvement would be to also put the n values in an array and to use for-loops to check the number of matches.

Cannot break c loop

Whenever I run this (part of a much larger file), when I get asked for inputs, if they are not numbers (letters or words) the code seems to loop and I'm not sure why.
while(rembox>=1){
printf("%c> ", p );
s=scanf("%d %d %c",&r , &k, &orin);
if (r = 5 || k =10){
*statement*
rembox --;
}
else{
rembox --;
continue;
}
At this line :
if (r = 5 || k =10){
You are assigning values 5 and 10 to r and k variables.
What you wanted to do :
if (r == 5 || k ==10){

What is the order in a for loop? [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
I'm trying to solve Problem 5 of project euler and I the answer I keep getting is wrong:
#include <stdio.h>
main()
{
int num;
int x = 0;
for (num = 20; x == 0; num++)
{
if ((num%1) == 0 && (num%2) == 0 && (num%3) == 0 && (num%4) == 0 && (num%5) == 0 && (num%6) == 0 && (num%7) == 0 && (num%8) == 0 && (num%9) == 0 && (num%10) == 0 && (num%11) == 0 && (num%12) == 0 && (num%13) == 0 && (num%14) == 0 && (num%15) == 0 && (num%16) == 0 && (num%17) == 0 && (num%18) == 0 && (num%19) == 0 && (num%20) == 0)
x = 1;
}
printf("%d %d", num, x);
}
My program keeps printing out 232792561 (I am aware that I'm printing x, this is simply for troubleshooting purposes).
The verbatim output I'm getting is: 232792561 1.
I did some research and I found that the correct answer to the problem is 232792560.
I am now beginning to believe that the problem lies in the for loop.
What does the loop do first, the iteration (num++) or the test (x == 0)?
A for loop can be converted to an equivalent while loop:
for (num = 20; x == 0; num++) {
// do stuff
}
is the same as
num = 20;
while (x == 0) {
// do stuff, then
num++;
}
So first the condition is checked, then the loop body is executed, then the increment.
(And yes, as others suggested, if you break; out of the loop when you need, you'll need the correct result, since break; immediately jumps out of the loop, thus the incrementing statement isn't executed for the last time.)
After the loop body has been executed (if at all, because first the initialisation code is run, then the condition checked to see whether the body is entered),
first the update code is run
then the condition is checked.
So after you set x to 1, num is incremented once more.
Instead of setting x to 1 to end the loop, you could simply break;, that would exit the loop without running the update code.
Your loop is needlessly complex and can be simplified using the while loop construct if you prefer. You can also get rid of the unnecessary variable x
int main() {
int num = 20;
while (!((num%1) == 0 && (num%2) == 0 && (num%3) == 0 && (num%4) == 0 && (num%5) == 0 && (num%6) == 0 && (num%7) == 0 && (num%8) == 0 && (num%9) == 0 && (num%10) == 0 && (num%11) == 0 && (num%12) == 0 && (num%13) == 0 && (num%14) == 0 && (num%15) == 0 && (num%16) == 0 && (num%17) == 0 && (num%18) == 0 && (num%19) == 0 && (num%20) == 0))
{
++num;
}
printf("%d\n", num);
return 0;
}
To answer why your for loop was giving incorrect answer:
Although you were setting x = 1 for the correct value of num, you were checking the condition of the for loop ONLY in the next iteration of the loop (i.e. after the num++ statement is executed), and hence your value of num was offset by 1.
As many people suggested, you could use the break statement to terminate the for loop execution so that the value of num is what you want it to be when the control reaches outside the loop.
Step 1: Initialization (num = 20)
Step 2: Test
Step 3: Iteration
Step 4: Test
Step 5: Iteration
and so on.
If I were you, I would choose while loop with condition as yours (I mean the long one inside for loop) with body of incrementing.

Random walk on 10x10 Array

i am having a problem figuring out an algorithm for this problem,been trying for few days without success,here is a pic of what im trying to obtain:
http://i.stack.imgur.com/X70nX.png
Here is my code tried many differents solutions but always get stuck at the same point:(Sorry for mixed language the important part is in english)
ps
im not supposed to use functions to solve this problem only loops and array.
EDIT
after much fixing it does the walk but seldomly crashes
any idea?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void){
char box[10][10];
int i,j;
int move,row,col;
char letter='A';
srand(time(NULL));
printf("\n\tSTART\n\n");
for(i=0;i < 10 ;i++)/* righe */
{
for(j=0;j < 10;j++) /* colonne */
{
box[i][j] = '.'; /* assegno . a tutti gli elementi dell array */
if(j == 9)
printf("%c%c\n", box[i][j]); /* giustifico ogni 10 elementi dell array j(0-9) */
else
printf("%c%c", box[i][j]);
}
}
/* LETS START */
printf("\n\n Inizia il gioco\n\n");
/* random place to start */
row = rand() % 9;
col = rand() % 9;
box[row][col]= 'A';
while(letter <= 'Z')
{
if(box[row+1][col] == '.' || box[row-1][col] == '.' || box[row][col+1] == '.' || box[row][col-1] == '.' )
{
move=rand() % 4;
switch(move){
case 0: /* Going UP */
if((row != 0) && (box[row-1][col] == '.'))
{
box[row-1][col]=++letter;
box[row--][col];
}else{
move=rand() % 4;
}
case 1:/* Going Down */
if((row != 9) && (box[row+1][col] == '.'))
{
box[row+1][col]=++letter;
box[row++][col];
}else{
move=rand() % 4;
}
case 2: /*Going Left */
if((col != 0) && (box[row][col-1] == '.'))
{
box[row][col-1]=++letter;
box[row][col--];
}else{
move=rand() % 4;
}
case 3: /* Going Right */
if((col != 9) && (box[row][col+1] == '.') )
{
box[row][col+1]=++letter;
box[row][col++];
}else{
move=rand() % 4;
}
}
}else{
printf("\n\nBloccato a %c\n\n", letter);
break;
}
}
/* FINE */
for(i=0;i<10;i++)/* righe */
{
for(j=0;j<10;j++) /* colonne */
{
if(j == 9)
printf("%c%c\n", box[i][j]); /* giustifico ogni 10 elementi dell array j(0-9) */
else
printf("%c%c", box[i][j]);
}
}
return 0;
}
You need to update row and col inside the loop.
Otherwise you'll always attempt to walk from the position of the 'A'.
... and once all 4 directions are filled, you're stuck in a infinite loop
. . . . .
. . B . .
. E A C .
. . D . .
Even when you update row and col inside the loop (and correct the == mistake), you have to handle a problem: suppose the first spot (the 'A') is the top left corner and the next random directions are East, South, South, West, and North. ... now what? :)
A B .
F C .
E D .
. . .
It's not a good idea to "reroll" the random number when you discover that you cannot go in some direction, because if you have bad luck, you get the same number twice (or even 3 or 4 or more times) - so even if you generated 4 random numbers and they all failed, that doesn't mean that you're stuck.
You can solve this problem by generating one number, and trying all 4 possible directions starting from it:
If the random number generator returned 0: check 0, 1, 2, 3
If the random number generator returned 1: check 1, 2, 3, 0
If the random number generator returned 2: check 2, 3, 0, 1
If the random number generator returned 3: check 3, 0, 1, 2
Implemented by the following code:
desired_move = rand();
success = 0;
for (i = 0; i < 4 && !success; ++i)
{
move = (desired_move + i) % 4;
switch (move)
{
case 0: // Go up
if (row > 0 && box[row - 1][col] == '.')
{
row = row - 1;
success = 1;
}
break;
case 1: // Go down
...
}
}
if (!success) // Tried all 4 directions but failed! You are stuck!
{
goto START_OVER; // or whatever else
}
Note that this algorithm is not very random: if you cannot go up, there is a greater chance that you go down than right or left. If you want to fix it, you can pick a random permutation of 4 directions instead of checking the directions sequentially:
const int permutation_table[24][4] = {
{0, 1, 2, 3},
{0, 1, 3, 2},
{0, 2, 1, 3},
...
{3, 2, 1, 0}
};
index = rand() % 24;
for (i = 0; i < 4; ++i)
{
move = permutation_table[index][i];
switch (move) {
... // As above
}
}
When you're in for loop.
Draw a possible direction
int direction = rand()%4;
Check all possible directions if the drawed one is invalid (not in array or not a ".")
int i=-1;
while( ++i < 4 )
{
switch(direction)
{
case 0:
if( row-1 >= 0 && box[row-1][col] == '.' ) {
--row;
i = -1;
}
break;
case 1:
if( col+1 < 10 && box[row][col+1] == '.' ) {
++col;
i = -1;
}
break;
case 2:
if( row+1 < 10 && box[row+1][col] == '.' ) {
++row;
i = -1;
}
break;
case 3:
if( col-1 >= 0 && box[row][col-1] == '.' ) {
--col;
i = -1;
}
break;
}
if( i != -1 ) {
direction = (direction+1)%4;
}
else {
break;
}
}
If there's no valid move end the for loop>
if( i == 4 ) {
break;
}
Otherwise write a letter to the table cell and update row/col position.
box[row][col] = letter;
And... that's all I guess. This is greedy algorithm so you don't need any optimizations (at least I don't see any in exercise requirements.
It looks like you are breaking out of your switch statement if you try to go in a direction that isn't valid, but you increment your counter anyway. Try to check another random direction if that happens.
where exactly does it break?
from what I can see at a glance is that you have a chance that It_that_walks gets in position from witch it cant go anywhere:
A B C D .
. I J E .
. H G F .
where after J?
There is no need for the && (box[row][col-1]= '.')
Allso, it is wrong (assignment instead of comparison), it should be: && (box[row][col-1]== '.') (but you dont need it alltogether)

Resources