所以很重要我在C中写了一个基于文本的RPG,我想创建一个地图系统。基本上我遇到麻烦的功能是从一个看起来像这样的文件中读取“文本地图”:
----------\n
|c x [\n
| x |\n
] |\n
----------\0
它基本上是使用2d数组构建的。 * 编辑 我添加了实际数组中的地图。是因为我不喜欢终止每一行
这是我遇到问题的功能:
char** readMap(char* map_to_read,int h, int w){
FILE* fp;
int a = 0, b = 0;
char map_return[h][w];
char* c;
fp = fopen(map_to_read, "r");
for(a = 0; a < h; a++){
for(b = 0; b < w; b++){
c = (char*)malloc(sizeof(char) * w);
map_return[a][b] = fgets(c, w, fp);
printf("%s", c);
}
free(c);
}
fclose(fp);
return map_return;
}
所有内容都读到最后,因为fgets()不会读取EOL。这就是printf从内部看起来的样子:http://i.imgur.com/KojbjDm.png
我可以为此买第二双眼睛吗?
答案 0 :(得分:0)
w
的价值是多少?对于您显示的数据,获取换行符应该至少为12(10个字符,换行符和空值)。您以后会遇到问题,因为您无法(安全地)返回本地数组map_return
,但这是一个单独的错误。此外,您应该在map_return[a][b] = fgets(c, w, fp);
行上收到类型不匹配警告,因为map_return[a][b]
是char
而fgets()
返回char *
。如果您保存指针,则无法承担free(c)
。这里有很多问题......
您回答:
基本上它是
array[h][w]
,所以w
表示数组一行中的元素数。
得到了进一步的回应:
所以你需要两个独立的内存块。一个用于读取行并验证它。它可以简单地
char line[128];
。然后使用if (fgets(line, sizeof(line), fp) == 0) { ...process EOF/error...}
。假设通过,您验证该行以及它何时通过验证,那么您可以安排将该行中的w
个字符复制到map_return
数组中。您必须决定是否正在使用字符串(以'\ 0'结尾)。你可以为两者做个案。然后,您必须处理“不返回局部变量”的问题。
我建议您更改该函数的接口,以便调用者为其分配内存。
此代码编译(但尚未运行)。它在读取的行上没有做太多验证;你可以决定还要做什么。
#include <stdio.h>
#include <stdbool.h>
extern bool readMap(char* map_to_read, int h, int w, char map[h][w]);
bool readMap(char* map_to_read, int h, int w, char map[h][w])
{
FILE* fp;
if ((fp = fopen(map_to_read, "r")) == 0)
return false;
for (int a = 0; a < h; a++)
{
char line[128];
if (fgets(line, sizeof(line), fp) == 0)
{
fclose(fp);
return false;
}
for (int b = 0; b < w; b++)
{
// Validation
if (line[b] == '\n' || line[b] == '\0')
{
fclose(fp);
return false;
}
map[a][b] = line[b];
printf("%c", line[b]);
}
putchar('\n');
}
fclose(fp);
return true;
}
此代码假定您没有在map
数组中存储以空字符结尾的字符串。
示例电话:
int h = 5;
int w = 10;
char map[h][w];
if (mapRead("somefile", h, w, map))
...process initialized map...
else
...report failure...
该功能的错误报告很少;你可以根据需要改进它。
答案 1 :(得分:0)
不要指责fgets
,而是要看你的逻辑。您在内部循环中循环w
次,每次读取w
个字节...总共h*w*w
个字节。