What's new

Human-readable config file

bcrew1375

New member
Anyone have any good tips for writing code in C(Not C++) to read and write a human-readable config file? I've been trying some different methods, but they all seem very crude. Any advice?
 

smcd

Active member
The "best" way would probably be to use a tool like lex or yacc and define a "language" for your config file, it'll make your job easy. Here's a poor, quick, and dirty method I whipped up in a few:
Code:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define LINE_MAX 256

void parse_line(char *line) {
	char *p = NULL;
	char var[LINE_MAX] = {'\0'}; // zero-out the memory for easy use memcpy
	char val[LINE_MAX] = {'\0'}; // ditto
	size_t len =0;
	p = strchr(line, '\n'); // assumes unix line ending
	if(p != NULL) {
		*p = '\0';
	}
	len = strlen(line);
	p = strchr(line, '=');
	if(p == NULL) {
		fprintf(stderr, "\'%s\' is a parse error\n", line);
		return;
	}
	// get the part before the first =
	memcpy(var, line, p - line);
	// skip the actual '=' sign
	p++;
	// get the value of the var
	memcpy(val, p, (line+len)-p);
	printf("\'%s\' = \'%s\'\n", var, val); // print they were parsed OK
	// you probably want to store them in a hash table or something
	// do it here. parse numbers to numbers, etc etc etc...
}

void read_config(char *file) {
	char line[LINE_MAX];
	FILE *config = NULL;
	config = fopen("./config.txt", "r");
	if(config == NULL) {
		fprintf(stderr, "%s", "Error opening ./config.txt\n");
		exit(EXIT_FAILURE);
	}
	while(fgets(line, LINE_MAX, config)) {
		if(line[0] == '#') { // skip comment line
			continue;
		}
		parse_line(line);
	}
	fclose(config);
}

int main() {
	read_config("./config.txt");
	return 0;
}

It does not support comments in the data, but supports single-line comments. Sample config.txt:
Code:
# comment 1
var1=true
# comment 2
var2=1.4
# comment 3
var3=test
# comment 4
var4=this = a long test
 
Last edited:
OP
B

bcrew1375

New member
Thanks, but it seems like this is aimed at Unix systems. Is it possible to use it on Windows platforms? Also, if possible I would like a method that doesn't require external programs. I've tried reading the config file into a buffer and going through it byte-by-byte, I've also tried reading it line by line. Maybe the problem is I don't have a strong grasp of parsing and how to do it in a C program. Thanks again for any help.
 

Cyberman

Moderator
Moderator
I think you might want to ask yourself a few questions
  1. why does the file need to be human readable
  2. what formats exist that one can GET a parser for and provide syntax checking for
  3. what type of configuration information is needed?
  4. Does this need to be fast?
Those are the kinds of questions you should ask before driving yourself nuts reinventing the wheel. You can for example get C code to read XML data. The later I've found to be good for INI files. A lot of compilers now use XML for storing information they use to create make files. There are C libraries for that too somewhere. Hmmm I'll put them in the big "programing resouces" sticky if I have time.

Cyb
 

aprentice

Moderator
http://www.cplusplus.com/reference/clibrary/cstdio/sscanf.html

sscanf is your best friend when it comes to parsing, it has some undocumented features too :p

Usage example, you want to put the name of the user and the times they logged into vars. The line below is stored in strTemp.

"Hello bccrew, you have tried logging in 10 times."

sscanf(strTemp,"%*[^' '] %s, %*[^0-9]%d",name,&number);

Parsing in just 1 line. Hope this helps :p
 

Garstyciuks

New member
I have never seen such usage. Do you have a link where these undocumented features are documented? :) And do those undocumented features work well on Windows as well as on UNIX based OSes?
 

Cyberman

Moderator
Moderator
I have never seen such usage. Do you have a link where these undocumented features are documented? :) And do those undocumented features work well on Windows as well as on UNIX based OSes?
Are you refering to sscanf?
Or what? Might be good to clarify that. :)

Cyb
 

Top