fgets没有阅读EOL?

时间:2013-04-01 04:23:07

标签: c fgets

所以很重要我在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

我可以为此买第二双眼睛吗?

2 个答案:

答案 0 :(得分:0)

分析

  

w的价值是多少?对于您显示的数据,获取换行符应该至少为12(10个字符,换行符和空值)。您以后会遇到问题,因为您无法(安全地)返回本地数组map_return,但这是一个单独的错误。此外,您应该在map_return[a][b] = fgets(c, w, fp);行上收到类型不匹配警告,因为map_return[a][b]charfgets()返回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个字节。