1

I'm having a problem parsing an .ini file. I know there are lots of post on this topic, and I have read many of them. my ini file have only one entry:

font=tahoma.ttf

Source Code:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

static FILE *ini_file;
char font[20];

void LoadConfig()
{
    char Setting[20],Value[20];
    int EndOfFile = 0;
    if ((ini_file = fopen("config.ini", "r")))
    {
        EndOfFile = fscanf(ini_file, "%[^=]=%s", Setting, &Value);
        while (EndOfFile != EOF)
        {
            if(strcmp(Setting,"font") == 0)
            {
                strcpy(font,Value);
            }
            EndOfFile = fscanf(ini_file, "%[^=]=%s", Setting, &Value);
        }
        fclose(ini_file);
    }
}

The problem is that, the value is not never read into the font variable.

hitman.star
  • 73
  • 10
  • There are only one line "font=tahoma.ttf" in my ini file. – hitman.star May 25 '16 at 17:35
  • 2
    Have you used a debugger to go through your code line-by-line? – Random Davis May 25 '16 at 17:38
  • Sorry, I don't know how to debug the source code, so I used printf("OK"); – hitman.star May 25 '16 at 17:42
  • the algo is simple, split by line -> split by `=` -> shift the result, you get the key, shift again you get the value – Ryan May 25 '16 at 17:43
  • But after compile the source code, I can see the message: "Segmentation fault (core dumped)". – hitman.star May 25 '16 at 17:45
  • It's all very well saying your ini file has only one entry, so why have a field definition? Tomorrow, you'll need another definition in it, and another. [Try this SO question](http://stackoverflow.com/questions/2280352/use-ini-file-in-c-on-linux). – Weather Vane May 25 '16 at 17:48
  • I want to insert some new lines in my ini file. – hitman.star May 25 '16 at 17:55
  • Step 1: `while (EndOfFile != EOF)` --> `while (EndOfFile == 2)` Step 2 `"%[^=]=%s"` -----------> into `" %19[^=]=%19s"` (add space and 19s) Step 3 Do not use `fscanf()`. Use `fgets()`. – chux - Reinstate Monica May 25 '16 at 18:09
  • Well, there is no changes.. – hitman.star May 25 '16 at 18:16
  • 2
    1) *LEARN TO USE YOUR DEBUGGER*! There's no time like the present ;). 2) Your code has many potential problems, including (but not limited to) `char Setting[20],Value[20]`. 3) SUGGESTION: Use `fgets()` and ' `strpbrk ( line, "=")`, like user3121023 suggests. – paulsm4 May 25 '16 at 19:42
  • If your platform supports `getline()` [(link)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getdelim.html), that's even better than `fgets()`. `fgets()` won't return an arbitrarily-long line (to be overly pedantic, neither will `getline()` - but `getline` is limited by how much memory it can allocate, while `fgets()` is limited to how much memory the caller supplies.) – Andrew Henle May 25 '16 at 19:42

2 Answers2

3

SefFault could be caused by the & before Value, but even after removing if, you could still read a value longer than 20 characters. And some ini files can contain comment lines that does not follow the pattern and will break you progran

You really should:

  • read line by line with fgets into a buffer of at least 255 characters - repeat until end of file : while (NULL != fgets(line, sizeof(line), stdin)) { ...}
  • use sscanf to parse each line and ignore every non conformant one:

    if (2 == sscanf(line, "%19[^=]=%19s", Setting, Value) { ... }
    
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
2

Use fgets to read each line in the file. strpbrk could be used to locate the equal and the newline and copy that span of characters to the variables.

void LoadConfig()
{
    char Setting[100] = {'\0'},Value[100] = {'\0'}, line[300] = {'\0'};
    size_t span = 0;
    if ((ini_file = fopen("config.ini", "r")))
    {
        while ( fgets ( line, sizeof ( line), ini_file))//read each line
        {
            char *equal = strpbrk ( line, "=");//find the equal
            if ( equal)//found the equal
            {
                span = equal - line;
                memcpy ( Setting, line, span);
                Setting[span] = '\0';
                if(strcmp(Setting,"font") == 0)
                {
                    equal++;//advance past the =
                    char *nl = strpbrk ( equal, "\n");//fine the newline
                    if ( nl)//found the newline
                    {
                        span = nl - equal;
                        memcpy ( font, nl, span);
                        font[span] = '\0';
                    }
                }
            }
        }
        fclose(ini_file);
    }
}
user3121023
  • 8,181
  • 5
  • 18
  • 16