I have developed the following C program to find all possible paths out off a maze. And it has to go through each room in the maze. That is why the '54' is hard coded at the minute because for the 8*7 array I am passing in there are 54 open rooms. I will work this out and pass it dynamically when I am re-writing. However I am looking for some help in how to make the code more efficient - it finds over 300,000 possible paths to complete the maze I am passing in but it ran for almost an hour.
#include <stdio.h>
#define FALSE 0
#define TRUE 1
#define NROWS 8
#define MCOLS 7
// Symbols:
// 0 = open
// 1 = blocked
// 2 = start
// 3 = goal
// '+' = path
char maze[NROWS][MCOLS] = {
"2000000",
"0000000",
"0000000",
"0000000",
"0000000",
"0000000",
"0000000",
"3000011"
};
int find_path(int x, int y, int c, int *t);
int main(void)
{
int t = 0;
if ( find_path(0, 0, 0, &t) == TRUE )
printf("Success!\n");
else
printf("Failed\n");
return 0;
}
int find_path(int x, int y, int c, int *t)
{
if ( x < 0 || x > MCOLS - 1 || y < 0 || y > NROWS - 1 ) return FALSE;
c++;
char oldMaze = maze[y][x];
if ( maze[y][x] == '3' && c == 54)
{
*t = *t+1;
printf("Possible Paths are %i\n", *t);
return FALSE;
}
if ( maze[y][x] != '0' && maze[y][x] != '2' ) return FALSE;
maze[y][x] = '+';
if ( find_path(x, y - 1, c, t) == TRUE ) return TRUE;
if ( find_path(x + 1, y, c, t) == TRUE ) return TRUE;
if ( find_path(x - 1, y, c, t) == TRUE ) return TRUE;
if ( find_path(x, y + 1, c, t) == TRUE ) return TRUE;
maze[y][x] = oldMaze;
return FALSE;
}
First of all I don't see any base condition for the function to return TRUE, it only returns TRUE on calling itself recursively witch is to say it will the result will allways print Failed (I thought recursion had to have a base condition that when finding success will propagate upwards..)
Secondly can you please explain the values in the boxes? as in 0,1,2 and 3? Is 3 the end of the maze or?...
Related
I'm a complete newbie, so please excuse me.
I tried using online compiler but they unresponsive, and I get no return value (or return 0 for whatever I enter)
I tried to write a function that check if triangle is right, isosceles or both, and return 1,2,3 respectively, all other cases should return 0.
int main() {
int TriangleType(unsigned angle1, unsigned angle2) {
unsigned angleSum = angle1 + angle2;
if (angleSum >= 180) {
return 0;
}
/* if triangle is right ---> */
if (angle1==90 || angle2==90 || angleSum==90) {
/*if it is also an isosceles --->*/
if (angle2==45 || angle1==45) {
return 3;
}
return 1;
}
/*check if it only a isosceles*/
if (angle1==(180-angle2)/2 ||
angle2== (180-angle1)/2 ||
angle1==angle2) {
return 2;
}
return 0;
}
TriangleType(110, 111);
}
First, don't try to use nested functions in C. Pulling that function out of main.
int TriangleType(unsigned angle1, unsigned angle2) {
unsigned angleSum = angle1 + angle2;
if (angleSum >= 180) {
return 0;
}
/* if triangle is right ---> */
if (angle1==90 || angle2==90 || angleSum==90) {
/*if it is also an isosceles --->*/
if (angle2==45 || angle1==45) {
return 3;
}
return 1;
}
/*check if it only a isosceles*/
if (angle1==(180-angle2)/2 ||
angle2== (180-angle1)/2 ||
angle1==angle2) {
return 2;
}
return 0;
}
int main() {
TriangleType(110, 111);
}
Second, this doesn't do anything with the return value from the function, so of course you see no output.
int main(void) {
switch (TriangleType(110, 111)) {
case 1:
printf("Right triangle\n");
break;
case 2:
printf("Isosceles triangle\n");
break;
case 3:
printf("Both types\n");
break;
default:
printf("None of the above\n");
}
return 0;
}
Code is functionally wrong
Even after re-organizing and moving the nested function, code attempts to be clever and not perform simple tests.
if (angle1 == (180 - angle2) / 2 || angle2 == (180 - angle1) / 2 || angle1 == angle2) fails in cases like TriangleType(45,89) --> 2 as (180 - angle2) / 2 rounds down. angle1 * 2 == (180 - angle2) would make more sense.
TriangleType(90, 90), where the 3rd angle is 0, returns 0. That is asymmetric. TriangleType(0, 90), TriangleType(90, 0) do not return 0.
TriangleType(0, 0) returns 2. I would expect that to return 0, a rejected triangle.
Below is a test harness for OP to use and test TriangleType().
#include <stdio.h>
int TriangleType(unsigned angle1, unsigned angle2) {
unsigned angleSum = angle1 + angle2;
if (angleSum >= 180) {
return 0;
}
/* if triangle is right ---> */
if (angle1 == 90 || angle2 == 90 || angleSum == 90) {
/*if it is also an isosceles --->*/
if (angle2 == 45 || angle1 == 45) {
return 3;
}
return 1;
}
/*check if it only a isosceles */
if (angle1 == (180 - angle2) / 2 || angle2 == (180 - angle1) / 2
|| angle1 == angle2) {
return 2;
}
return 0;
}
int my_TriangleType(unsigned angle1, unsigned angle2) {
unsigned angle3 = 180 - angle1 - angle2;
if (angle1 >= 180 || angle2 >= 180 || angle3 >= 180) {
return 0;
}
if (angle1 == 0 || angle2 == 0 || angle3 == 0) {
return 0;
}
int retval = angle1 == 90 || angle2 == 90 || angle3 == 90 ? 1 : 0;
if (angle1 == angle2 || angle2 == angle3 || angle3 == angle1)
retval += 2;
return retval;
}
#include <string.h>
#define MAX_LIMIT 127
int main() {
printf("score:%d my_score:%d\n", TriangleType(45,89), my_TriangleType(45,89));
int error_count = 0;
int flags[4][4] = {0};
for (unsigned angle1 = 0; angle1 <= 181; angle1++) {
for (unsigned angle2 = 0; angle2 <= 181; angle2++) {
int score = TriangleType(angle1, angle2);
int my_score = my_TriangleType(angle1, angle2);
if (score != my_score) {
error_count++;
if (flags[score][my_score] == 0) {
flags[score][my_score] = 1;
printf("%3d angle1:%2u angle2:%2u score:%d my_score:%d\n", //
error_count, angle1, angle2, score, my_score);
}
}
}
}
printf("total errors:%d\n", error_count);
return 0;
}
Output:
score:2 my_score:0
1 angle1: 0 angle2: 0 score:2 my_score:0
2 angle1: 0 angle2:90 score:1 my_score:0
total errors:181
another_TriangleType() could be made that is more efficient than my_TriangleType(), yet it would needed to functionally match.
Well your questions is lacking some information, but I assume you got as inputs of your program, two angles.
THe fisrt thing we need to think is:
If you got a right triangle, than there is one of those values equals 90 degrees, instead the sum of them must be 90.
On the other hand, if you got an isosceles triangle you should have 2 equal values, instead you must have the 180 deg - sum of both angles should result in one of those two.
Let's try to code this out:
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
#define RIGHT 0x01
#define ISOSCELES 0x02
#define BOTH 0x03
// If you got a right triangle, than there is one of those values equals 90 degrees, instead the sum of them must be 90.
int bIsRightTriangle(int iAngDeg1, int iAngDeg2){
if ( iAngDeg1 == 90 || iAngDeg2 == 90 )
return TRUE;
if ( (iAngDeg1 + iAngDeg2) == 90 )
return TRUE;
return FALSE;
}
// On the other hand, if you got an isosceles triangle you should have 2 equal values,
// instead you must have the 180 deg - sum of both angles should result in one of those two.
int bIs_IsoscelesTriangle(int iAngDeg1, int iAngDeg2){
int iAngDeg3 = 180 - iAngDeg1 + iAngDeg2;
if ( iAngDeg1 == iAngDeg2 )
return TRUE;
if ( (iAngDeg3 == iAngDeg1) || (iAngDeg3 == iAngDeg2) )
return TRUE;
return FALSE;
}
int iGetTriangleTypeByAngles(int iAngDeg1, int iAngDeg2){
int iReturnType = 0;
iReturnType = bIsRightTriangle(iAngDeg1, iAngDeg2) ? (iReturnType | RIGHT) : iReturnType;
iReturnType = bIs_IsoscelesTriangle(iAngDeg1, iAngDeg2) ? (iReturnType | ISOSCELES) : iReturnType;
return iReturnType;
}
int main(int argc, char *argv[]){
if ( argc < 3 ){
return -1;
}
// In case you want an output
// printf("%d\n", iGetTriangleTypeByAngles(atoi(argv[1]), atoi(argv[2])));
return iGetTriangleTypeByAngles(atoi(argv[1]), atoi(argv[2]));
}
I need to write a recursive function that returns 1 if digits of a whole number are ascending (left to right), return -1 if descending or return 0 if neither.
My solution attempt returns 0 every time and I know why but I don't know how to get around it.
Here's my code:
#include <stdio.h>
int check_order(int n)
{
if (n % 10 > n / 10 % 10)
{
return check_order(n / 10);
if (n == 0)
{
return 1;
}
}
else if (n % 10 < n / 10 % 10)
{
return check_order(n / 10);
if (n == 0)
{
return -1;
}
}
else
{
return 0;
}
}
int main()
{
int n;
printf("enter a whole number (n > 9):");
scanf_s("%d", &n);
printf("function returned: %d\n", check_order(n));
}
Here's a simple recursion:
int f(int n){
if (n < 10)
return 0;
int dr = n % 10; // rightmost digit
n = n / 10;
int dl = n % 10; // second digit from the right
int curr = dl < dr ? 1 : -1; // current comparison
if (dl == dr) curr = 0; // keep strict order
if (n < 10)
return curr;
return curr == f(n) ? curr : 0; // are the comparisons consistent?
}
Explain your algorithm?
Suppose you use the following:
You are given a number.
You need to turn that number into a sequence of digits.
If you are given a number, you can convert that number to a sequence of digits.
If you are given a sequence of digits, use
that.
Compare each pair of digits -> ascending, descending, or neither.
Combine the results from each pair, sequentially/recursively.
We can use a string to make the digit comparisons easier, and accept very long sequences of digits.
We can use an enum(erated) type to represent the ordering.
How do you combine the results? Define a function that combines the order of two adjacent, overlapping pairs, then you can combine results.
#include <stdio.h>
#include <string.h>
typedef enum { descending=-1, other=0, ascending=1 } order_t;
order_t pair_order(int a, int b) {
if( a < b ) return ascending;
if( a > b ) return descending;
return other;
}
//strict (increasing/decreasing)
order_t strict_order( order_t x, order_t y ) {
if( x == y ) return x;
return other;
}
//monotone (increasing/decreasing)
order_t monotone_order( order_t x, order_t y ) {
if( x == y ) return x;
if( other == x ) return y;
if( other == y ) return x;
return other;
}
order_t check_order( char* p, int remain ) {
//printf("p:%s\n",p); //uncomment to watch progress
if( remain<2 ) return other;
if( remain==2 ) return pair_order(p[0], p[1]);
return strict_order( pair_order(p[0], p[1]), check_order(p+1, remain-1) );
//return monotone_order( pair_order(p[0], p[1]), check_order(p+1, remain-1) );
}
char* order_name[] = {
"descending",
"other",
"ascending"
""
};
int main()
{
char line[666] = "none";
while ( strlen(line) > 0 ) {
printf("enter a number (at least 2 digits):");
fgets(stdin,line,sizeof(line)-1);
if( strlen(line) > 0 && line[strlen(line)-1] == '\n' )
line[strlen(line)-1] = '\0';
order_t order = check_order(line);
printf("function returned: (%d)%s\n", order, order_name[order+1]);
}
}
I think you were started on the right track but need to flesh out your code more. My solution borrows on that of #ChuckCottrill as I like his enum but I don't like that he doesn't play the ball as it lays (i.e. converts to a string instead of dealing with the int.) I also borrow the nice test examples of #ggorlen but I don't like that solution either as it can take multiple passes through the number to figure out the answer when only one pass should be needed:
#include <stdio.h>
typedef enum { descending=-1, other=0, ascending=1 } order_t; // a la #ChuckCottrill
order_t check_order(int n)
{
if (n > 9) {
int right = n % 10;
int left = n / 10 % 10;
if (right > left) {
n /= 10;
if (n > 9) {
return (ascending == check_order(n)) ? ascending : other;
}
return ascending;
}
if (right < left) {
n /= 10;
if (n > 9) {
return (descending == check_order(n)) ? descending : other;
}
return descending;
}
}
return other;
}
int main() { // a la #ggorlen
printf("12345: %d\n", check_order(12345));
printf("54321: %d\n", check_order(54321));
printf("54323: %d\n", check_order(54323));
printf("454321: %d\n", check_order(454321));
printf("1: %d\n", check_order(1));
printf("12: %d\n", check_order(12));
printf("21: %d\n", check_order(21));
}
OUTPUT
> ./a.out
12345: 1
54321: -1
54323: 0
454321: 0
1: 0
12: 1
21: -1
>
A version that works for any length since it takes the string as parameter.
And feeding the recursive function with previous status (ascending or descending) allows for some shorter code and less functions.
int check_order(char *str, int index, int previous) {
char current = str[index]; // char at index
char next = str[index+1]; // char at index+1
if (current == 0 || next == 0) {
return previous; // End of string
}
// Ascending or descending?
int status = next > current ? 1 : (next < current ? -1 : 0);
if (status == 0 || index > 0 && status != previous) {
// If neither -1/1 nor status == previous (while not initial call)
return 0;
}
return check_order(str, index+1, status); // Check from next index
}
The main function must ensure the string is at least 2 chars
int main(int argc, char **argv) {
char *str = *++argv;
// Some optional checks on str here... (like this is a number)
int status = 0; // Default value if string length < 2
if (strlen(str) >= 2) {
status = check_order(str, 0, 0);
}
printf("Check order for %s is %d\n", str, status);
return 0;
}
Code after a return statement like this is unreachable:
return check_order(n / 10);
if (n == 0)
{
return -1;
}
Beyond this, you're on the right track of checking the current digit against the next digit, but I don't see a clear base case (when n < 10, that is, a single digit).
Trying to check ascending and descending in one recursive function is difficult to manage. In particular, communicating state between stack frames and determining which cases are still valid at a given call suggests that the return value is overworked.
To save having to return a struct or use an enum or magic numbers as flags, I'd write two general helper functions, ascending_digits and descending_digits.
#include <stdbool.h>
#include <stdio.h>
bool ascending_digits(int n) {
if (n < 10) return true;
if (n % 10 < n / 10 % 10) return false;
return ascending_digits(n / 10);
}
bool descending_digits(int n) {
if (n < 10) return true;
if (n % 10 > n / 10 % 10) return false;
return descending_digits(n / 10);
}
int check_order(int n) {
if (ascending_digits(n)) return 1;
if (descending_digits(n)) return -1;
return 0;
}
int main() {
printf("12345: %d\n", check_order(12345));
printf("54321: %d\n", check_order(54321));
printf("54323: %d\n", check_order(54323));
printf("454321: %d\n", check_order(454321));
printf("1: %d\n", check_order(1));
printf("12: %d\n", check_order(12));
printf("21: %d\n", check_order(21));
return 0;
}
Output:
12345: 1
54321: -1
54323: 0
454321: 0
1: 1
12: 1
21: -1
Not only are these functions easier to understand and maintain individually, they're also more reusable than if they were inseparably tied together.
This doesn't handle negative numbers--you could apply abs and go from there if you want. Same goes for handling equal values; this implementation accepts numbers such as 1223 but you could use <= to enforce strict ordering.
I'd like to ask the following misunderstandings of C language, which I see I'm having.
I'm sorry if the code is not properly indented, I tried as much as I could but there are not so many guides on the internet.
The program asked given a starting number 'val' and a Even-Odd or Odd-Even alternating sequence (which stops whenever this rules is violated) to print the greater prime number with 'val'.
I tried with two functions and the main: one to control the GCD between two given numbers and the other to keep tracks of the greatest one, but I think I miss something in the code or in the conception of C function,
Because when compiled it returns me 0 or great number which I'm not entering.
One example to understand what I should do:
If my sequence was 10, 7, 8, 23 and my val was 3, I had to print 23, because it is the greatest integer prime with 3.
Here's the code :
#include <stdio.h>
int mcd(int a, int b)
{ // Gcd function
if (a == 0)
return b;
else
return mcd(b % a, b);
}
int valuta(int val, int h) // Valuing Max function
{
int temp = 0;
if (mcd(val, h) == 1 && h > temp)
temp = h;
return temp;
}
int main()
{
int val, d, x, y, z, t, contatore = 1;
scanf("%d", &val);
scanf("%d%d", &x, &y);
if (x > y && mcd(val, x) == 1)
{ // Two options
t = x;
}
else if (y > x && mcd(val, y) == 1)
{
t = y;
}
if ((x % 2 == 0 && y % 2 == 0) || (x % 2 == 1 && y % 2 == 1))
{ // Bad case
if (x > y && mcd(val, x) == 1)
{
t = x;
contatore = 0;
}
else if (y > x && mcd(val, y) == 1)
{
t = y;
contatore = 0;
}
}
else
{
while (contatore == 1)
{
scanf("%d", &z);
t = valuta(val, z);
if (x % 2 == 0 && z % 2 == 0)
{ // Even- Odd - Even
scanf("%d", &d);
t = valuta(val, d);
if (d % 2 == 0)
{
contatore = 0;
}
else
{
contatore = 0;
}
}
if (x % 2 == 1 && z % 2 == 1)
{ //Odd- Even- Odd
scanf("%d", &d);
t = valuta(val, d);
if (d % 2 == 1)
{
contatore = 0;
}
else
{
contatore = 0;
}
}
}
}
printf("%d\n", t);
return 0;
}
PS. Is there any way to reduce the number of lines of code or to reduce the effort in coding? I mean, a straightforward solution will be helpful.
Your valuta() function is flawed in that it needs to return the maximum qualifying value so far but has no knowledge of the previous maximum - temp is always zero. The following takes the previous maximum as an argument:
int valuta(int val, int h, int previous )
{
return ( mcd(val, h) == 1 && h > previous ) ? h : previous ;
}
And is called from main() thus:
t = valuta( val, x, t ) ;
The test mcd(val, h) == 1 is flawed, because mcd() only ever returns the value of parameter b which is not modified in the recursion, so will never return 1, unless the argument b is 1. Since I have no real idea what mcd() is intended to do, I cannot tell you how to fix it. It appear to be a broken implementation of Euclid's greatest common divisor algorithm, which correctly implemented would be:
int mcd(int a, int b)
{
if(b == 0)
return a;
else
return mcd(b, a % b);
}
But I cannot see how that relates to:
"[...] he greatest integer prime with 3 [...]
The odd/even even/odd sequence handling can be drastically simplified to the extent that it is shorter and simpler than your method (as requested) - and so that it works!
The following is a clearer starting point, but may not be a solution since it is unclear what it is it is supposed to do.
#include <stdio.h>
#include <stdbool.h>
int mcd(int a, int b)
{
if(b == 0)
return a;
else
return mcd(b, a % b);
}
int valuta(int val, int h, int previous )
{
return ( mcd(val, h) && h > previous ) ? h : previous ;
}
int main()
{
int val, x, t ;
printf( "Enter value:") ;
scanf("%d", &val);
typedef enum
{
EVEN = 0,
ODD = 1,
UNDEFINED
} eOddEven ;
eOddEven expect = UNDEFINED ;
bool sequence_valid = true ;
printf( "Enter sequence in odd/even or even/odd order (break sequence to exit):\n") ;
while( sequence_valid )
{
scanf("%d", &x);
if( expect == UNDEFINED )
{
// Sequence order determined by first value
expect = (x & 1) == 0 ? EVEN : ODD ;
}
else
{
// Switch expected odd/even
expect = (expect == ODD) ? EVEN : ODD ;
// Is new value in the expected sequence?
sequence_valid = (expect == ((x & 1) == 0 ? EVEN : ODD)) ;
}
// If the sequence is valid...
if( sequence_valid )
{
// Test if input is largest qualifying value
t = valuta( val, x, t ) ;
}
}
// Result
printf("Result: %d\n", t);
return 0;
}
I am writing maze generator and at the some point I have to choose random unvisited neighbour of a cell. The first idea was just to enumerate neighbours such as left = 0, top = 1, right = 2, bottom = 3 and use rand() % 4 to generate random number and choose appropriate cell. However, not all cells features 4 neighbours, so that I had to write following code:
Cell* getRandomNeighbour(const Maze* const maze, const Cell* const currentCell) {
int randomNumb = rand() % 4;
int timer = 1;
while(timer > 0) {
if (randomNumb == 0 && currentCell->x < maze->width-1 && maze->map[currentCell->y][currentCell->x+1].isUnvisited)
return &maze->map[currentCell->y][currentCell->x+1];
if (randomNumb == 1 && currentCell->x > 0 && maze->map[currentCell->y][currentCell->x-1].isUnvisited)
return &maze->map[currentCell->y][currentCell->x-1];
if (randomNumb == 2 && currentCell->y < maze->height-1 && maze->map[currentCell->y+1][currentCell->x].isUnvisited)
return &maze->map[currentCell->y+1][currentCell->x];
if (randomNumb == 3 && currentCell->y > 0 && maze->map[currentCell->y-1][currentCell->x].isUnvisited)
return &maze->map[currentCell->y-1][currentCell->x];
timer--;
randomNumb = rand() % 4;
}
if (currentCell->x < maze->width-1 && maze->map[currentCell->y][currentCell->x+1].isUnvisited)
return &maze->map[currentCell->y][currentCell->x+1];
if (currentCell->x > 0 && maze->map[currentCell->y][currentCell->x-1].isUnvisited)
return &maze->map[currentCell->y][currentCell->x-1];
if (currentCell->y < maze->height-1 && maze->map[currentCell->y+1][currentCell->x].isUnvisited)
return &maze->map[currentCell->y+1][currentCell->x];
if (currentCell->y > 0 && maze->map[currentCell->y-1][currentCell->x].isUnvisited)
return &maze->map[currentCell->y-1][currentCell->x];
return NULL;
}
So, if after 10 iterations the right decision isn't chosen, it will be picked by brute force. This approach seems to be good for the reason that varying of variable timer changes the complexity of maze: the less timer is, the more straightforward maze is. Nevertheless, if my only purpose is to generate completely random maze, it takes a lot of execution time and look a little bit ugly. Is there any pattern(in C language) or way of refactoring that could enable me to deal with this situation without long switches and a lot of if-else constructions?
As #pat and #Ivan Gritsenko suggested, you can limit your random choice to the valid cells only, like this:
Cell* getRandomNeighbour(const Maze* const maze, const Cell* const currentCell)
{
Cell *neighbours[4] = {NULL};
int count = 0;
// first select the valid neighbours
if ( currentCell->x < maze->width - 1
&& maze->map[currentCell->y][currentCell->x + 1].isUnvisited ) {
neighbours[count++] = &maze->map[currentCell->y][currentCell->x + 1];
}
if ( currentCell->x > 0
&& maze->map[currentCell->y][currentCell->x - 1].isUnvisited ) {
neighbours[count++] = &maze->map[currentCell->y][currentCell->x - 1];
}
if ( currentCell->y < maze->height - 1
&& maze->map[currentCell->y + 1][currentCell->x].isUnvisited ) {
neighbours[count++] = &maze->map[currentCell->y + 1][currentCell->x];
}
if ( currentCell->y > 0
&& maze->map[currentCell->y - 1][currentCell->x].isUnvisited ) {
neighbours[count++] = &maze->map[currentCell->y - 1][currentCell->x];
}
// then choose one of them (if any)
int chosen = 0;
if ( count > 1 )
{
int divisor = RAND_MAX / count;
do {
chosen = rand() / divisor;
} while (chosen >= count);
}
return neighbours[chosen];
}
The rationale behind the random number generation part (as opposed to the more common rand() % count) is well explained in this answer.
Factoring repeated code, and a more disciplined way of picking the order of directions to try yields this:
// in_maze returns whether x, y is a valid maze coodinate.
int in_maze(const Maze* const maze, int x, int y) {
return 0 <= x && x < maze->width && 0 <= y && y < maze->height;
}
Cell *get_random_neighbour(const Maze* const maze, const Cell* const c) {
int dirs[] = {0, 1, 2, 3};
// Randomly shuffle dirs.
for (int i = 0; i < 4; i++) {
int r = i + rand() % (4 - i);
int t = dirs[i];
dirs[i] = dirs[r];
dirs[r] = t;
}
// Iterate through the shuffled dirs, returning the first one that's valid.
for (int trial=0; trial<4; trial++) {
int dx = (dirs[trial] == 0) - (dirs[trial] == 2);
int dy = (dirs[trial] == 1) - (dirs[trial] == 3);
if (in_maze(maze, c->x + dx, c->y + dy)) {
const Cell * const ret = &maze->map[c->y + dy][c->x + dx];
if (ret->isUnvisited) return ret;
}
}
return NULL;
}
(Disclaimer: untested -- it probably has a few minor issues, for example const correctness).
Hello I am new here and programming in C. I didn't want to ask something that you may consider simple but I have asked my classmates and even my programming teacher to see if they can find the error but until today they couldn't find it (them).
But first let me describe what I know, it says:
"Run-Time Check Failure #2 - Stack variable "d" (and sometimes m and
other y) was corrupted ".
I made my job trying to debug it but the problem is always showed on the last codeline (of the main body), so I couldn't find exactly where the problem is, here I attach the code, and I would be very happy if you find the problem and explain me the reason why I get it (to don't repeat the same mistakes in future) =D.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/* Type Declaration */
#define true 1
#define false 0
typedef char boolean;
/* Functions declaration */
boolean test( short int d, short int m, long int y );
boolean nextday( short int d, short int m , long int y );
int main( void )
{
/* Variables initialization */
short int d = 0, m = 0;
long int y = 0;
do {
/* Data by user*/
printf( "Ingrese el numero de año: " );
scanf( "%ld", &y );
} while ( y < 0 );
do {
printf( "Ingrese el numero de mes: " );
scanf( "%d", &m );
} while ( m < 1 || m > 12 );
do {
printf( "Ingrese el numero de dia: " );
scanf( "%d", &d );
} while ( d < 01 || ( test( d, m, y ) == false ) ); // If the data is wrong then re-type the data
// If the nextday function return value is true then the next day is 01, if not just sum a day
if ( nextday ( d, m, y ) == true ) {
d = 01;
// If we start a new year the new month must be 01-01-01.
if ( m == 12 ) {
m = 01;
y++;
}
// Just increase the month for any other month
else {
m++;
}
}
else {
d++;
}
printf( "Mañana será: %d-%d-%ld\n", d, m, y );
return 0;
}
boolean test( short int d, short int m, long int y ){
int max;
switch(m) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
max = 31;
break;
case 4:
case 6:
case 9:
case 11:
max = 30;
break;
case 2:
if ( y % 400 == 0 ){
max = 29;
}
else if ( y % 100 == 0 ){
max = 28;
}
else if ( y % 4 == 0 ){
max = 29;
}
else {
max = 28;
}
break;
}
if ( d <= max ){
return true;
}
else {
return false;
}
}
boolean nextday( short int d, short int m, long int y ) {
boolean x;
// If it's 28-02 in a secular year * 4 then it's a leap-year. (so it has 29 days)
if ( m == 2 && d == 28 && y % 400 == 0 ) {
x = false;
}
// If it is an end of century but it isn't 4 multiply then it only has 28 days.
else if ( m == 2 && d == 28 && y % 100 == 0 ) {
x = true;
}
// If it just a leap year it has 29 days.
else if ( m == 2 && d == 28 && y % 4 == 0 ) {
x = false;
}
//If it's the last day of February and it's a leap year.
else if ( m == 2 && d == 29 && y % 4 == 0 ){
x = true;
}
// If we are in the end of the month.
else if ( ( d == 30 && ( m == 4 || m == 6 || m == 9 || m == 11 ) ) ||
d == 31 ) {
x = true;
}
// Then if it is another day just sum a day
else {
x = false;
}
return x;
}
You need to use:
scanf( "%hd", &m );
scanf( "%hd", &d );
since they are short int's.
Using "%d" you are basically loading an int size variable in a small int storage space.
An int is usually 4 bytes while small int is 2 bytes.
scanf( "%d", &m );
%d means "this argument points to an int." You are providing a pointer to a short int. Either use %hd (for short int) or, preferably, change m to type int (why bother with short int here?).