C - 使用动态内存分配读取文件并将文本放入字符指针
C - Reading file and putting text into char pointer with dynamic memory allocation
我试图从我为 C 程序编写的外部文件中逐行读取基本着色器。文件中有两个着色器:顶点和片段。我创建了这个函数来逐行读取它并确定它正在读取哪个着色器和 return 结构 ParsedShader
.
typedef struct {
char* vertex;
char* fragment;
} ParsedShader;
static ParsedShader ParseShader(char *filepath) {
char* vert;
char* frag;
vert = "\n";
frag = "\n";
char line[128];
enum ShaderType {
NONE = -1,
VERTEX = 0,
FRAGMENT = 1
};
enum ShaderType type = NONE;
FILE* file;
fopen_s(&file, filepath, "r");
while (fgets(line, sizeof(line), file)) {
if (strstr(line, "#shader")) {
if (strstr(line, "vertex")) type = VERTEX;
else if (strstr(line, "fragment")) type = FRAGMENT;
}
else {
if (type == VERTEX) {
//Put Lines into vert char *
//Here is where I don't know what to do
}
else if (type == FRAGMENT) {
//Put Lines into frag char *
//Here I don't know what to do either
}
}
}
fclose(file);
ParsedShader result;
result.vertex = vert;
result.fragment = vert;
return result;
}
问题是由于内存不足,我无法将文本放入 vert
和 frag
变量中。我知道它必须使用 malloc
和 realloc
函数来完成,但就是无法让它工作。我已经创建了一个释放内存的函数:
static DeleteShader(ParsedShader* shader) {
if (shader) {
free(shader->vertex);
free(shader->fragment);
}
}
初始化:
vert = calloc(1, sizeof(char));
这将分配一个元素并将其初始化为零(字符串结尾)。
添加字符串:
vert = realloc(vert, strlen(vert) + strlen(line) + 1);
strcat(vert, line);
这将重新分配缓冲区以包含连接的字符串(包括字符串结束标记),然后连接字符串。
您可以为 frag
做同样的事情。
此代码无效,因为它会多次扫描字符串以测量它们的长度,但它应该适用于大小不超过几 KB 的文件。
为 calloc
和 realloc
添加错误检查将使代码更安全。
将 *vert
变量设置为 null 并使用 realloc
与某种计数器集成的函数。
int vertCount = 0;
然后每次你想要添加 char 时,做这样的事情:
vert = (char*)realloc(vert,sizeof(char)*(vertCount+1));
vert[vertCount++] = char
注意:通常不建议使用 realloc,因为它会导致内存泄漏。
更好的主意是 int maxCount;int current;
您可以将 maxCount 的值硬编码为 10 ,并使用 malloc 函数,然后只有在电流达到 maxCount 之后,您才会增加 maxCount 并执行例如 realloc,这样您就有更多机会创建覆盖。
编辑:
我以为你会一个字一个字地讲。可以应用与 realloc 相同的逻辑,只需使用 strlen(string) + 1('\0' 字符的原因)重新分配,然后使用 strcat 复制整行。
但是将您的变量设置为空字符串 ("") 这样您就不必第一次使用 strcpy。
我试图从我为 C 程序编写的外部文件中逐行读取基本着色器。文件中有两个着色器:顶点和片段。我创建了这个函数来逐行读取它并确定它正在读取哪个着色器和 return 结构 ParsedShader
.
typedef struct {
char* vertex;
char* fragment;
} ParsedShader;
static ParsedShader ParseShader(char *filepath) {
char* vert;
char* frag;
vert = "\n";
frag = "\n";
char line[128];
enum ShaderType {
NONE = -1,
VERTEX = 0,
FRAGMENT = 1
};
enum ShaderType type = NONE;
FILE* file;
fopen_s(&file, filepath, "r");
while (fgets(line, sizeof(line), file)) {
if (strstr(line, "#shader")) {
if (strstr(line, "vertex")) type = VERTEX;
else if (strstr(line, "fragment")) type = FRAGMENT;
}
else {
if (type == VERTEX) {
//Put Lines into vert char *
//Here is where I don't know what to do
}
else if (type == FRAGMENT) {
//Put Lines into frag char *
//Here I don't know what to do either
}
}
}
fclose(file);
ParsedShader result;
result.vertex = vert;
result.fragment = vert;
return result;
}
问题是由于内存不足,我无法将文本放入 vert
和 frag
变量中。我知道它必须使用 malloc
和 realloc
函数来完成,但就是无法让它工作。我已经创建了一个释放内存的函数:
static DeleteShader(ParsedShader* shader) {
if (shader) {
free(shader->vertex);
free(shader->fragment);
}
}
初始化:
vert = calloc(1, sizeof(char));
这将分配一个元素并将其初始化为零(字符串结尾)。
添加字符串:
vert = realloc(vert, strlen(vert) + strlen(line) + 1);
strcat(vert, line);
这将重新分配缓冲区以包含连接的字符串(包括字符串结束标记),然后连接字符串。
您可以为 frag
做同样的事情。
此代码无效,因为它会多次扫描字符串以测量它们的长度,但它应该适用于大小不超过几 KB 的文件。
为 calloc
和 realloc
添加错误检查将使代码更安全。
将 *vert
变量设置为 null 并使用 realloc
与某种计数器集成的函数。
int vertCount = 0;
然后每次你想要添加 char 时,做这样的事情:
vert = (char*)realloc(vert,sizeof(char)*(vertCount+1));
vert[vertCount++] = char
注意:通常不建议使用 realloc,因为它会导致内存泄漏。
更好的主意是 int maxCount;int current;
您可以将 maxCount 的值硬编码为 10 ,并使用 malloc 函数,然后只有在电流达到 maxCount 之后,您才会增加 maxCount 并执行例如 realloc,这样您就有更多机会创建覆盖。
编辑: 我以为你会一个字一个字地讲。可以应用与 realloc 相同的逻辑,只需使用 strlen(string) + 1('\0' 字符的原因)重新分配,然后使用 strcat 复制整行。 但是将您的变量设置为空字符串 ("") 这样您就不必第一次使用 strcpy。