我试图解决这个问题:
创建文件stringhe.h stringhe.c,让您使用以下结构和功能"
struct stringa {
unsigned char length;
char *s;
};
struct stringa *read_stringhe_bin(const char *filename, unsigned int *pn);
该结构包含
length
字段,其中包含字符串(可能为0)和s
字段的长度,该字段指向以零结尾的字符串(长度为length
)。该函数将一个文件名作为参数,该文件名将以未翻译的读取模式打开(二进制),并指向一个unsigned int
变量的指针,您必须在该变量中输入文件中的字符串数。该文件由一系列长度元素组成 一个变量,其中一个字节表示字符串的长度
n
,下面有n
字节,包含字符串的字符。该函数必须返回指向新内存区域的指针(动态分配) heap)包含从文件中读取的所有字符串。字符串的数量不是先验的,不受限制。
它可以受代码约束。即使
s
字符串元素也必须动态分配堆。
这是我的代码:
stringhe.h
#include <stdio.h>
#include <stdlib.h>
struct stringa {
unsigned char length;
char *s;
};
#ifndef READ
#define READ
struct stringa *read_stringhe_bin(const char *filename, unsigned int *pn);
#endif // !READ
stringhe.c
#include "stringhe.h"
struct stringa *read_stringhe_bin(const char *filename, unsigned int *pn) {
FILE *f;
f = fopen(filename, "r+b");
if (f == NULL) exit(1);
struct stringa *lista;
lista = malloc(0);
lista->s = malloc(0);
for (int i = 0; ; i++) {
char a;
fseek(f, 1, SEEK_CUR);
if (fgetc(f) == EOF) break;
fseek(f, -2, SEEK_CUR);
fread(&a, 1, 1, f);
lista = (struct stringa *)realloc (lista, sizeof(struct stringa) * (size_t)(i + 1));
lista[i].length = a;
lista[i].s = malloc(sizeof(char) * (size_t)a);
fread(lista[i].s, 1, (size_t)a, f);
lista[i].s[a] = '\0';
(*pn)++;
}
fclose(f);
return lista;
}
我将以下二进制文件传递给函数:
05 43 69 61 6F 21 00 03 61 62 63 0E 50 72 6F 67
72 61 6D 6D 61 7A 69 6F 6E 65
被翻译成:
.Ciao!..abc.Prog
rammazione
所以...通过调试我的功能似乎完美无缺,但是当我将它上传到我们教授的网站上以确定它是否真的有效时,它会说main
(由教授创建,和我看不到)结果不正确。
所以我怀疑我在内存分配或其他类似方面做错了。你能不能帮我理解错误,并可能改进我的代码以使其更强大?
答案 0 :(得分:3)
您的代码存在多个问题:
您使用"r+b"
模式打开文件。更新无用且容易出错,只需使用"rb"
。
如果无法打开文件,您可能只返回NULL
而不是退出程序。
lista = malloc(0);
lista->s = malloc(0);
malloc(0)
可能会返回NULL
或您不应该写入的对象的地址。你应该这样做:
lista = NULL;
为字符串字符分配空间时:
lista[i].s = malloc(sizeof(char) * (size_t)a);
您应该从读取文件中的字节后为您设置的终止'\0'
分配一个额外字节。这样做:
lista[i].s = malloc(a + 1);
寻求检查文件结尾很麻烦,实际上可能不受流支持。只需将大小的一个字节读入int
,检查EOF
,然后为内容分配和读取指定的字节数:
int a;
a = fgetc(f);
if (a == EOF) break;
lista = realloc(lista, sizeof(*lista) * (size_t)(i + 1));
lista[i].length = a;
lista[i].s = malloc(a + 1);
lista[i].s[a] = '\0';
if (fread(lista[i].s, 1, a, f) != a) {
// file format error, ignore this incomplete string
break;
}
您还应检查malloc
和realloc
可能无法分配内存并正常返回NULL
。
最后,返回分配的字符串数的方式不正确:
(*pn)++;
进入您的函数时,您不知道*pn
是否为0
...它可能在main()
中未初始化。通过在解析循环结束时设置一次来解决此问题:
*pn = i;
另外,为什么要在stringe.h
中使用#ifndef READ
包围您的功能声明等。保护的目的是什么?