我正在尝试使用C语言编写寻路算法。我正在尝试扫描试图找到最短路径的地图,并将其放入2D动态数组中。
这是我的基本地图:
5 5
11111
01001
00101
00010
00001
5是行数,其他5是列数。 1是方式,0是墙。 这是我的代码:
#include <stdio.h>
#include <stdlib.h>
int row;
int column;
void main()
{
FILE *fp;
int **array;
fp = fopen("file.path", "r");
fscanf(fp, "%d", &row);
fgetc(fp);
fscanf(fp, "%d", &column);
array = (int **)malloc(row * sizeof(int));
for(int i=0; i<row; i++)
array[i] = malloc(column * sizeof(int));
for(int i=0; i<row; i++)
{
for(int j=0; j<column; j++)
{
char tmp = fgetc(fp);
array[i][j] = (tmp - '0');
}
}
}
此代码返回分段错误。
答案 0 :(得分:1)
此代码返回分段错误。
请参阅下面有关 malloc 的评论
代码顶部到底部的一些注释
在
int row; int column;
为什么这两个全局变量?它们可以在 main
中是本地的在
fp = fopen("file.path", "r"); fscanf(fp, "%d", &row); fgetc(fp); fscanf(fp, "%d", &column);
您需要检查 fp 不是NULL才能确保打开成功
您需要检查 fscanf 返回1以确保您能够读取数字
它们之间的 fgetc 是没有用的,第二个 fscanf
会绕过该空间请注意,您可以执行独特的 fscanf 来读取两个数字:
if (fscanf(fp, "%d %d", &row, &column) != 2) {
... manage error to not continue the execution
}
在
array = (int **)malloc(row * sizeof(int));
如前所述,您分配了int*
数组而不是 int 数组,这些数组解释了稍后执行中的分段错误(可见于64b),强制转换没有用,所以array = malloc(row * sizeof(int*));
您还需要检查malloc不返回NULL
在
char tmp = fgetc(fp);
array[i][j] = (tmp - '0');
tmp 必须是 int 才能检查EOF情况
请注意,您也可以读取字符串,而不是逐字符读取
警告当前 tmp 会获得换行符,因此您错误地初始化了数组
提案:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp;
int ** array;
int row;
int column;
fp = fopen("file.path", "r");
if (fp == NULL) {
puts("cannot open file.path");
return -1;
}
if (fscanf(fp, "%d %d", &row, &column) != 2) {
puts("cannot read row column");
fclose(fp);
return -1;
}
array = malloc(row * sizeof(int*));
if (array == NULL) {
puts("not enough memory");
fclose(fp);
return -1;
}
for (int i=0; i<row; i++) {
array[i] = malloc(column * sizeof(int));
if (array[i] == NULL) {
puts("not enough memory");
fclose(fp);
return -1;
}
}
for (int i=0; i<row; i++)
{
/* finish to read previous line */
int c;
while ((c = fgetc(fp)) != '\n') {
if (c == EOF) {
fclose(fp);
puts("unexpected EOF");
return -1;
}
}
for(int j=0; j<column; j++)
{
c = fgetc(fp);
if (c == EOF) {
puts("unexpected EOF");
fclose(fp);
return -1;
}
if ((c != '0') && (c != '1')) {
puts("invalid value");
fclose(fp);
}
array[i][j] = (c - '0');
}
}
fclose(fp);
/* show the content for at least debug */
puts("array is:");
for (int i=0; i<row; i++)
{
for (int j=0; j<column; j++)
printf("%d ", array[i][j]);
putchar('\n');
}
/* free resources */
for (int i=0; i<row; i++)
{
free(array[i]);
}
free(array);
}
编译和执行:
pi@raspberrypi:~ $ gcc -pedantic -Wextra b.c
pi@raspberrypi:~ $ cat file.path
5 5
11111
01001
00101
00010
00001
pi@raspberrypi:~ $ ./a.out
array is:
1 1 1 1 1
0 1 0 0 1
0 0 1 0 1
0 0 0 1 0
0 0 0 0 1
pi@raspberrypi:~ $
在 valgrind 下执行:
pi@raspberrypi:~ $ valgrind ./a.out
==4841== Memcheck, a memory error detector
==4841== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==4841== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==4841== Command: ./a.out
==4841==
array is:
1 1 1 1 1
0 1 0 0 1
0 0 1 0 1
0 0 0 1 0
0 0 0 0 1
==4841==
==4841== HEAP SUMMARY:
==4841== in use at exit: 0 bytes in 0 blocks
==4841== total heap usage: 9 allocs, 9 frees, 5,592 bytes allocated
==4841==
==4841== All heap blocks were freed -- no leaks are possible
==4841==
==4841== For counts of detected and suppressed errors, rerun with: -v
==4841== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
注意:我先使用 fscanf 然后使用 fgetc ,由于混合的原因,有必要管理换行符,另一种方法是始终使用 getline 读取每行的内容,让昏暗的人使用 sscanf
答案 1 :(得分:0)
它在没有segfault的情况下可以在我的测试中编译并运行(使用VC ++ 2017),您需要在调试器中运行它以确定目标失败的位置和原因。
但是,无论在任何情况下,您都应通过多种方式修改或使用不正确的代码。
sizeof(int) != sizeof(int*)
上分配正确的空间量。 5 5
之后的换行符,您的地图将被错误地加载。fgetc(fp);
之间的fscanf
毫无用处,因为在任何情况下fscanf()
都会丢弃前导空格。 row
和column
不一定是全局的。malloc()
。考虑:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int main()
{
FILE* fp = fopen("file.path", "r") ;
if( fp != 0 )
{
int row = 0;
int column = 0;
int check = fscanf( fp, "%d%d\n", &row, &column ) ;
if( check == 2 )
{
bool map_valid = false;
int** array = malloc( row * sizeof(*array) ) ;
if( array != NULL )
{
map_valid = true ;
for( int i = 0; map_valid && i < row ; i++ )
{
array[i] = malloc( column * sizeof(*array[i]) ) ;
map_valid = (array[i] != NULL) ;
}
}
for( int i = 0; map_valid && i < row; i++ )
{
int c = 0 ;
for( int j = 0; map_valid && j < column; j++ )
{
c = fgetc(fp);
map_valid = c != EOF ;
array[i][j] = (c - '0');
}
while( map_valid && (c = fgetc(fp)) != '\n' && c != EOF ){}
}
if( map_valid )
{
// ...
}
if( array != NULL )
{
for( int i = 0; i < row; i++ )
{
if( array[i] != NULL )
{
free( array[i] ) ;
}
}
free( array ) ;
}
}
}
return 0 ;
}