C - Reading file and putting text into char pointer with dynamic memory allocation

609 Views Asked by At

I'm trying to read a basic Shader line by line from an external file I wrote for a C program. In the file there are two shaders: Vertex and Fragment. I created this function to read it line by line and also determine which shader it is reading and return the struct 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;
}

The problem is I have not been able to put text in the vert and frag variables because of memory. I know it must be done using the malloc and realloc functions, but just couldn't make it work. I already created a function which frees the memory:

static DeleteShader(ParsedShader* shader) {
    if (shader) {
        free(shader->vertex);
        free(shader->fragment);
    }
}
2

There are 2 best solutions below

0
On BEST ANSWER

Initialiation:

vert = calloc(1, sizeof(char));

This will allocate one element and initialize it to zero (end of string).

Adding strings:

vert = realloc(vert, strlen(vert) + strlen(line) + 1);
strcat(vert, line);

This will re-allocate buffer to have the concatenated string (including end-of-string mark) and then concatenate strings.

You can do the same things for frag.

This code is ineffective because it will scan strings many times to measure their length, but it should work for files whose sizes is upto a few KB.

Adding error checks for calloc and realloc will make the code safer.

1
On

set the *vert variable to null and use realloc function integrated with some sort of counter.

int vertCount = 0;

Then every time you wan to add char do something like this:

vert = (char*)realloc(vert,sizeof(char)*(vertCount+1));
vert[vertCount++] =  char

Note: using realloc this often is not advised as it can result in memory leaks. Better idea would have some int maxCount;int current;

You would hardcode the value of maxCount to lets say 10 , and use malloc function, then only after current reaches the maxCount you would increase maxCount and do for example realloc, then you would have more chance of creating overlaod.

Edit: I thought you are going character by character. Same logic with realloc can be applied just realloc with strlen(string) + 1 ( cause of '\0' char), and then use strcat to copy entireline. But set your variables to emptry string ("") so you don't have to use strcpy for the first time.