#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2003
    Posts
    217
    Rep Power
    0

    strtok() problem


    I've got a simple config parser here but I don't know an easy way to assign the data in the config file to the appropriate variables.

    Code:
    int main( void )
    {
    	if((fp = fopen(FILENAME, "r")) == NULL)
    	{
    		printf("\n\tconfig file couldn't be found.");
    		exit(1);
    	}
    
    	while (fgets(input, MAX_LINE_LENGTH, fp))
    	{
    		if (input[0] == '#')
    			continue;
    
    		char separator[] = "\""; 
    		char *token;
    		char tokenn[40];
    
    		token = strtok( input, separator );
    		
    		tokenn = token;
    
    		while( token != NULL ) 
    		{ 
    			printf( " %s\n", token );
    			token = strtok( NULL, separator );
    		}
        }
    
    	return 0;
    
    }
    Lets say config.txt contains...

    Code:
    #config file
    
    name "chris"
    ip "127.0.0.1"
    What is an easy way to assign the variables "name" and "ip" in my program to "chris" and "127.0.0.1" ?
  2. #2
  3. Contributing User

    Join Date
    Aug 2003
    Location
    UK
    Posts
    5,075
    Rep Power
    1802
    An almost identical question was answered here: Parse a config file on linux

    Clifford
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2003
    Posts
    217
    Rep Power
    0

    Unhappy


    All the code examples do parse the config but they don't assign variables... thats what i'm looking for.

    thanks though
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2003
    Posts
    88
    Rep Power
    11
    Why not make a 3D array.

    char variables[/*number of variables you plan to have*/100][/*array of char's for variable name*/50][/*array of char's for values*/100];

    Not a proven method, just a hunch. :) Hope it helps :p
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2003
    Posts
    217
    Rep Power
    0

    Question


    Cool idea, but I still don't know how i'll take the inputed info and assign it to the right variable or array index number(s) :(
  10. #6
  11. I'm Baaaaaaack!
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Jul 2003
    Location
    Maryland
    Posts
    5,538
    Rep Power
    243
    What do you mean 'assign variables'? If you go with my example clifford is referring to, you would do something like this (after the rest of the code had run):

    Code:
        std::string ip;
        if (myMap.find("ip") == myMap.end()){
            printf("Did not find variable 'ip' in the config file\n");
        }else{
            ip = myMap["ip"];
            printf("Found this '%s' for the value 'ip' in the config file\n", ip.c_str());
        }

    My blog, The Fount of Useless Information http://sol-biotech.com/wordpress/
    Free code: http://sol-biotech.com/code/.
    Secure Programming: http://sol-biotech.com/code/SecProgFAQ.html.
    Performance Programming: http://sol-biotech.com/code/PerformanceProgramming.html.
    LinkedIn Profile: http://www.linkedin.com/in/keithoxenrider

    It is not that old programmers are any smarter or code better, it is just that they have made the same stupid mistake so many times that it is second nature to fix it.
    --Me, I just made it up

    The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore, all progress depends on the unreasonable man.
    --George Bernard Shaw
  12. #7
  13. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2003
    Posts
    217
    Rep Power
    0

    o_o


    ahh cool so thats how you do it... but yeah that's what I meant; taking the info you got from the config and assigning it to the right variables so you can run the program according to the users config.

    I'm using your code atm but what would be the solution (how you would assign the variables) using the code a posted above ? Is it any harder ?
  14. #8
  15. I'm Baaaaaaack!
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Jul 2003
    Location
    Maryland
    Posts
    5,538
    Rep Power
    243
    I am cornfused by your question. Are you referring to where it would go in my code from the URL?

    My blog, The Fount of Useless Information http://sol-biotech.com/wordpress/
    Free code: http://sol-biotech.com/code/.
    Secure Programming: http://sol-biotech.com/code/SecProgFAQ.html.
    Performance Programming: http://sol-biotech.com/code/PerformanceProgramming.html.
    LinkedIn Profile: http://www.linkedin.com/in/keithoxenrider

    It is not that old programmers are any smarter or code better, it is just that they have made the same stupid mistake so many times that it is second nature to fix it.
    --Me, I just made it up

    The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore, all progress depends on the unreasonable man.
    --George Bernard Shaw
  16. #9
  17. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2003
    Posts
    217
    Rep Power
    0

    question


    mitakeet, this is about your parsing code;

    when I compile it I get 127 warnings... here is a bit of it

    Code:
    d:\program files\microsoft visual studio 6\vc98\include\xtree(120) : warning C4786: 'std::_Tree<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const
     ,std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,std::map<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::less<std::basic_string<c
    har,std::char_traits<char>,std::allocator<char> > >,std::allocator<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > >::_Kfn,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,std::allocator<std::ba
    sic_string<char,std::char_traits<char>,std::allocator<char> > > >' : identifier was truncated to '255' characters in the debug information
  18. #10
  19. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2003
    Posts
    217
    Rep Power
    0
    to clearify my previous question:

    I posted code above, and it parses a cfg with this kinda of format:

    Code:
    port "666"
    name "chris"
    it seems to work fine, but I can't figure out a way to assign "666" to the variable "int port" in my program and "chris" to my char array "char name[20]"
  20. #11
  21. I'm Baaaaaaack!
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Jul 2003
    Location
    Maryland
    Posts
    5,538
    Rep Power
    243
    I get the same warnings when I compile in debug mode. Try compiling in release mode, you should see the errors go away. They are cause because the compiler only allocates 255 characters for a variable name for debugging purposes and C++ definitions can become quite lengthy. It is nothing to worry about. If you are using Visual C++ 6 you can turn off warnings and not have to have them cause errors to be difficult to find (but leave on all warnings in release mode).

    Regarding the conversions, here is a complete example:

    Code:
    #include <stdio.h>
    
    #include <map>
    #include <string>
    
    #define MAXLINELENGTH 1024
    
    int main(){
        std::map < std::string, std::string > myMap;
        char input[MAXLINELENGTH];
        FILE *fin;
        int len, ptr;
        bool found;
    
        if ((fin = fopen("config.txt", "r")) == NULL){
            fprintf(stderr, "Unable to open config file!\n");
            exit(1);
        }
    
        while (fgets(input, MAXLINELENGTH, fin)){
            if (input[0] == '#')
                continue;
            len = strlen(input);
            if (len < 2)
                continue;
            if (input[len-1] == '\n')
                input[len-1] = '\0';
            ptr = 0;
            found = false;
            while (ptr < len){
                if (input[ptr] == '='){
                    found = true;
                    input[ptr++] = '\0';
                    break;
                }
                ptr++;
            }
            if (found){
                myMap[input] = &input[ptr];
            }
        }
        fclose(fin);
    
        printf("Run through all of the values using an iterator:\n\n");
        std::map < std::string, std::string >::iterator myIterator = myMap.begin();
        while (myIterator != myMap.end()){
            printf("\t%s\t%s\n", myIterator->first.c_str(), myIterator->second.c_str());
            myIterator++;
        }
    
        printf("\n\nGet selected values into different variable types:\n\n");
        printf("A std::string (easiest, that is what the map stores):\n");
        std::string ip;
        if (myMap.find("ip") == myMap.end()){
            printf("\tDid not find variable 'ip' in the config file\n");
        }else{
            ip = myMap["ip"];
            printf("\tFound this '%s' for the value 'ip' in the config file\n", ip.c_str());
        }
    
        printf("\nAn integer:\n");
        int intVal;
        if (myMap.find("intVal") == myMap.end()){
            printf("\tDid not find variable 'intVal' in the config file\n");
        }else{
            intVal = atoi(myMap["intVal"].c_str());
            printf("\tFound this '%d' for the value 'intVal' in the config file\n", intVal);
        }
    
        printf("\nA char buffer:\n");
        char chrDomain[MAXLINELENGTH];//you could do a malloc if you want
        if (myMap.find("domain") == myMap.end()){
            printf("\tDid not find variable 'domain' in the config file\n");
        }else{
            //you could check the size of the value (i.e., myMap["domain"].size())
            //and do a malloc if you wanted instead of a fixed length buffer
            strncpy(chrDomain, myMap["domain"].c_str(), MAXLINELENGTH-1);
            printf("\tFound this '%s' for the value 'domain' in the config file\n", chrDomain);
        }
    
        return 0;
    }
    This is my config file:

    Code:
    #Some config file
    #
    #domain
    domain=mydomain.com
    
    #ip
    ip=127.0.0.1
    
    intVal=12345
    
    #end config file
    And the output:

    Code:
    Run through all of the values using an iterator:
    
            domain  mydomain.com
            intVal  12345
            ip      127.0.0.1
    
    
    Get selected values into different variable types:
    
    A std::string (easiest, that is what the map stores):
            Found this '127.0.0.1' for the value 'ip' in the config file
    
    An integer:
            Found this '12345' for the value 'intVal' in the config file
    
    A char buffer:
            Found this 'mydomain.com' for the value 'domain' in the config file

    My blog, The Fount of Useless Information http://sol-biotech.com/wordpress/
    Free code: http://sol-biotech.com/code/.
    Secure Programming: http://sol-biotech.com/code/SecProgFAQ.html.
    Performance Programming: http://sol-biotech.com/code/PerformanceProgramming.html.
    LinkedIn Profile: http://www.linkedin.com/in/keithoxenrider

    It is not that old programmers are any smarter or code better, it is just that they have made the same stupid mistake so many times that it is second nature to fix it.
    --Me, I just made it up

    The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore, all progress depends on the unreasonable man.
    --George Bernard Shaw
  22. #12
  23. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2003
    Posts
    217
    Rep Power
    0

    Talking Thanks


    Thanks alot, I understand now, and the example will help me finish this program.

    You are one of the most helpful on here :)

IMN logo majestic logo threadwatch logo seochat tools logo