tags:

views:

74

answers:

5

in the configuration file i have entries similar to this one:

filepath = c:\Program Files\some value

Where the path can contain spaces and there are no quotes on that string. I tried parsing this with strtok like:

char *option;
char *value;

value = strtok(line, " =");
strcpy(option, value);
value = strtok(NULL, " =");

where line is the line I am reading from the file, option will contain the left side of the equal (filepath) and value will contain the right side (c:\program files\some value). I know, it's poor coding, but I haven't found something better. sorry... In any case, for those options where there's no space in the right side it works great, but in those containing spaces it only return the string until the 1st space: c:\Program.

Is there any other way to do this?

Code is appreciated. Jessica

A: 

Remove the space in the delimiter:

value = strtok(line, "=");
Khnle
then it crashes.
Jessica
oops, sorry my bad. It was crashing somewhere else.
Jessica
A: 

Here: strtok(line, " =")

You are saying to split on space AND =. Lose the space and trim your results if need be.

Serapth
A: 

You could use strtok_r(), and use the pointer it gives you for the rest of the string.

char *rightside;
char *leftside;

leftside = strtok_r(line, "=", &rightside);

Note that this will trash your "line" buffer, but normally that isn't a big deal if you just read new data into it anyway.

bde
A: 

Use sscanf():

char * conf = "filepath = c:\\Program Files\\some value";
char key[20];
char value[40];
sscanf(conf, "%s = %40c", key, value);
printf("key: %s value: %s\n", key, value); 
Sjoerd
`sscanf` is dangerous and should be avoided! (http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/dangers-c.html)
the_void
I've specified that `value` may be maximum 40 characters, so it doesn't overflow. I think the same is possible for `key`. This makes is safe against buffer overflows.
Sjoerd
A: 

This should do it:

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

#define INPUT_FILE "test.txt"
#define BUF_SIZE 1024
#define SEP " = "

#define CHECK(x) \
    do { \
        if (!(x)) { \
            fprintf(stderr, "%s:%d: ", __func__, __LINE__); \
            perror(#x); \
            exit(-1); \
        } \
    } while (0) \

void trim(char *s) {
    // Trim spaces and tabs from beginning:
    int i = 0, j;
    while((s[i]==' ') || (s[i]=='\t')) {
        i++;
    }
    if(i > 0) {
        for(j = 0; j < strlen(s); j++) {
            s[j] = s[j+i];
        }
    s[j] = '\0';
    }

    // Trim spaces and tabs from end:
    i = strlen(s) - 1;
    while((s[i]==' ') || (s[i]=='\t') || (s[i]=='\r')  || (s[i]=='\n')) {
        i--;
    }
    if(i < (strlen(s) - 1)) {
        s[i+1] = '\0';
    }
}

int main() {
    FILE *f;
    char line[BUF_SIZE + 1];
    char *opt, *val;

    line[BUF_SIZE] = '\0';

    f = fopen(INPUT_FILE, "rt");
    CHECK(f != NULL);

    while (NULL != fgets(line, sizeof(line), f)) {
        printf("%s", line);

        opt = strstr(line, SEP);
        if (!opt) {
            continue;
        }

        *opt = '\0';
        val = opt + strlen(SEP);
        opt = line;

        trim(opt);
        trim(val);

        printf("opt=<%s> val=<%s>\n", opt, val);
    }
    fclose (f);

    return 0;
}

The trim function was taken from here

the_void