I am trying to make a simple program to read a config file in C. But the data in my struct members isn't staying where I put it.
Code at the bottom.
This is what I think I am doing:
When I try to access the members, I can only get the data from the last row in the config file.
Thanks!
Edit: I expected it to populate the struct with key / values from the config file. Instead it only had the value of the last line in the config file.
expected output
example.com
actual output
food.txt
Problem is with:
conf->key[i] = key;
conf->value[i] = value;
main.c
/*
* Goal is to make simple key value storage with struct and pointers
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXLEN 100
#define CONFIG_MAX_BUF 1024
#define DELIM "="
struct config_s {
char *key[MAXLEN];
char *value[MAXLEN];
};
void read_config_file(struct config_s *conf, char *filename, int *size_of_array);
int main() {
int i = 0, size_of_array;
// type config_s has key and value members
struct config_s c;
read_config_file(&c, "test.cfg", &size_of_array);
printf("size of array: %i\n", size_of_array);
// if i want to print them all out, i can use this, but i'll have
// a function to search for a certain key and return the value.
int l = 0, e = 1;
printf("********** TEST 1 ***********\n");
printf("key: [%s] value: [%s] i: [%i]\n", c.key[l], c.value[l], l);
printf("key: [%s] value: [%s] i: [%i]\n", c.key[e], c.value[e], e);
printf("********** TEST 2 ***********\n");
return 0;
}
void read_config_file(struct config_s *conf, char *filename, int *size_of_array) {
FILE *file;
file = fopen(filename, "r");
char line[CONFIG_MAX_BUF];
int i = 0;
char *cfline;
char *key;
char *value;
while(fgets(line, sizeof(line), file) != NULL) {
cfline = strstr((char *)line, DELIM);
value = cfline + strlen(DELIM);
value[strlen(value) - 1] = '\0';
key = strtok((char *)line, DELIM);
printf("%i %s %s\n", i, key, value);
conf->key[i] = key;
conf->value[i] = value;
printf("%i %s %s\n", i, (*conf).key[i], (*conf).value[i]);
i++;
}
printf("%s %s\n", (*conf).key[0], (*conf).value[0]);
fclose(file);
*size_of_array = i;
return;
}
test.cfg
server=example.com
port=443
file=food.txt
In your newest version of read_config_file
, you're saving pointers to the values that point within the buffer line
, which is on the stack, so these pointers will be invalid upon return.
Even if the buffer were global, the pointers would be colliding with one another for each line because the buffer gets overwritten with each fgets
call.
Change:
conf->key[i] = key;
conf->value[i] = value;
Into:
conf->key[i] = strdup(key);
conf->value[i] = strdup(value);