Programm funktioniert nur mit printf()-Anweisung



  • Hallo zusammen!

    Folgendes Problem: ich habe eine kleine Anwendung geschrieben, die über eine Rekursion einen Weg in einem 20x20-großen Feld findet. Zwischendurch habe ich hin und wieder an manchen Stellen mir Debuginformationen anzeigen lassen, ganz normal über eine printf()-Anweisung. Als das Programm fertig war, habe ich dann alle Anweisungen entfernt, und nun läuft's nicht mehr. 😃 Habe die Stelle auch isolieren können. Es handelt sich um das printf() in 'find_way()'.

    Als Compiler benutze ich den GCC 3.4.5 (über MinGW) unter Windows. Wer das ausprobieren will, kann das printf() einfach mal auskommentieren und wieder zurück, um das Verhalten zu beobachten. Ich stehe mit meinem Latein am Ende. Weiß nicht, woran es liegen könnte. Habe ganz unten noch eine Textdatei angehangen, die ein Feld beinhaltet. Einfach als "feld.txt" im selben Verzeichnis speichern.

    #include <stdio.h>
    #define SIZE 20
    #define FIELD_BLOCK 0
    #define FIELD_FREE 1
    #define FIELD_WALK 2
    
    struct BOARD {
    	unsigned char field[SIZE][SIZE];
    };
    
    struct POS {
    	int x, y;
    };
    
    char load_board( BOARD *brd, char *filename );
    void print_board( BOARD *brd );
    int find_way( BOARD *brd, POS *cur, POS *dest, int step = 0 );
    char valid_pos( BOARD *brd, int x, int y );
    
    POS move_matrix[4] = { {1,0}, {0,1}, {-1,0}, {0,-1} };
    
    int main( int argc, char **argv ) {
    	BOARD brd;
    	POS start, dest;
    
    	if( !load_board( &brd, "feld.txt" ) ) {
    		printf( "Fehler beim Laden von \"feld.txt\"!\n" );
    		return 1;
    	}
    
    	start.x = 0;
    	start.y = 0;
    	dest.x = 19;
    	dest.y = 19;
    	find_way( &brd, &start, &dest );
    
    	print_board( &brd );
    
    	return 0;
    }
    
    int find_way( BOARD *brd, POS *cur, POS *dest, int step ) {
    	char movestep;
    	int steps;
    	POS newpos;
    
    	++step;
    	brd->field[cur->x][cur->y] = FIELD_WALK;
    
    	if( dest->x == cur->x && dest->y == cur->y ) {
    		return step;
    	}
    
    	newpos = *cur;
    
    	for( movestep = 0; movestep < 4; ++movestep ) {
    		newpos.x += move_matrix[movestep].x;
    		newpos.y += move_matrix[movestep].y;
    
    		printf( "" );
    
    		if( valid_pos( brd, newpos.x, newpos.y ) ) {
    			steps = find_way( brd, &newpos, dest, step );
    			if( steps != -1 ) {
    				return steps;
    			}
    		}
    
    		newpos.x -= move_matrix[movestep].x;
    		newpos.y -= move_matrix[movestep].y;
    	}
    
    	brd->field[cur->x][cur->y] = FIELD_FREE;
    	return -1;
    }
    
    char valid_pos( BOARD *brd, int x, int y ) {
    	if( x < 0 || y < 0 || x >= SIZE || y >= SIZE ) {
    		return 0;
    	}
    
    	if( brd->field[x][y] != FIELD_FREE ) {
    		return 0;
    	}
    }
    
    char load_board( BOARD *brd, char *filename ) {
    	FILE *fin;
    	int x, y;
    
    	fin = fopen( filename, "r" );
    	if( !fin ) {
    		return 0;
    	}
    
    	for( y = 0; y < SIZE; ++y ) {
    		for( x = 0; x < SIZE; ++x ) {
    			fread( &brd->field[x][y], 1, 1, fin );
    			brd->field[x][y] -= '0';
    
    			if( brd->field[x][y] > 1 ) {
    				fclose( fin );
    				return 0;
    			}
    		}
    
    		fseek( fin, 2, SEEK_CUR );
    	}
    
    	fclose( fin );
    	return 1;
    }
    
    void print_board( BOARD *brd ) {
    	char legend[3] = {'X', '.', '*'};
    	int x, y;
    
    	printf( "(%c = begehbar, %c = blockierend)\n\n",
    			legend[1], legend[0] );
    
    	for( y = 0; y < SIZE; ++y ) {
    		for( x = 0; x < SIZE; ++x ) {
    			printf( "%c", legend[brd->field[x][y]] );
    		}
    		printf( "\n" );
    	}
    }
    
    11111111111011111111
    11111111111011111111
    11111111111011111111
    11111111111011111111
    11111111111001111111
    11111111111101111111
    11111111111101111111
    11111111111101111111
    11111111111101111111
    11111111111100111111
    11111100000000111111
    11111101111111111111
    11111101111111111111
    11111101110111111111
    11110001110111111111
    11011111110111111111
    11000000000111111111
    11111111111111111111
    11111111111111111111
    11111111111111111111
    

    Vielleicht ist's ja auch nur ein Compilerflag oder sonstwas. Für Tipps wäre ich dankbar. 🙂



  • Hi,

    der gcc hat die Möglichkeit deinen Code ziemlich streng zu testen.
    Versuch mal: -W -Wall -pedantic mit anzugeben und du bekommst eine
    Menge von Warnings angezeigt.

    Ich glaube, der gravierenste Fehler ist in der Funktion valid_pos():
    Hier gibts du nie eine 1 zurück. 😉

    Deine Load-Funktion weißt auch ein paar Schwächen auf. Z.B. gehst
    du am Ende einer Zeile mit fseek(.., 2, ..) zwei Zeichen vor.
    Unter Linux ist das dann aber falsch. Hier müßte eine 1 stehen.
    Unter Windows muss es aber 2 sein. Das hängt damit zusammen, dass
    unter Linux ein '\n' steht und bei Windows noch ein zusätzliches
    Zeichen.

    Außerdem solltest du in find_way movestep als int und nicht als char
    definieren.

    Na dann.. viel spaß weiter.
    Gruß mcr



  • Merkwürdig, in der Regel nutze ich den Switch '-Wall'. Danke für den Hinweis, auch für valid_pos(). In der Tat lag es daran, dass es kein Return außerhalb der Bedingungen gab -- endete wohl in willkürlichem Verhalten. 🙂

    Das mit der Load-Funktion ist nicht so tragisch. Bin zwar auch jemand, der normal auf Portabilität achtet, aber da dieser Kram für die Uni ist und sonst keinen wirklichen Mehrwert hat, war mir die Beschränkung auf das '\r\n' wurscht. 😉 Dennoch Danke für den Tipp.

    'int movestep' habe ich mir zu Herzen genommen, danke. 🙂


Anmelden zum Antworten