0
votes

I've got a function, that reads from a given file, looks for a given keyword, returning a keyvalue thats seperated by a given string from the word. The return value of my function is char * at the moment, which is subpar for error handling, as far as I understood the whole matter. On the other hand I don't wand to fiddle with a pointer to store the value in. At least in this case.

Is there a way to return the string value through just the function, while returning the int value for success/failure?

My char * code:

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

/*!
 * @brief Loads the config file and returns value of requested parameter search
 * @param char *file - Config file to search in
 * @param char *seperator - Seperator to identify keyword and keyvalue 
 * @param char *search - Requested parameter to look for
 * @return char * - Value of found keyword or error if search failed
*/

int confin(char *file, char *seperator, char *search)
{
    FILE *conf;
    char *buffer;
    char *output;
    char line[256];

    char *returnerror = "Error!";


    if((conf = fopen(file, "r")) == NULL)                                   // Try to open file from path, return error if failed
    {
        fprintf(stderr, "Could not open config file \"%s\"!\n", file);
        return returnerror;
    }

    while (fgets(line, sizeof(line), conf) != NULL)                         // Read lines of file until the end is reached
    {
        buffer = strtok(line, seperator);                                   // Search for first appearance of seperator in line;
        if((strcmp(buffer,search)) == 0)                                    // If keyword is found,
        {
            buffer = strtok(NULL, seperator);                               // buffer the keyvalue,
            output = malloc(sizeof(buffer));
            strcpy(output, buffer);                                         // copy it into the output string,
            output[strcspn(output, "\n")] = 0;                              // replace the "\n" char from the end with terminating 0
            fclose(conf);
            return output;                                                  // and return the value of output.        
        }
    }

    fprintf(stderr, "Could not find config keyword \"%s\"!\n", search);
    fclose(conf);
    return returnerror;

}


int main ()
{
    printf("%s\n",confin("test.conf","=","test"));
}

I've tried the following code, yet the returned value is (null)

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

/*!
 * @brief Loads the config file and returns value of requested parameter search
 * @param char *file - Config file to search in
 * @param char *seperator - Seperator to identify keyword and keyvalue 
 * @param char *search - Requested parameter to look for
 * @return int - 0 on success, 1 on failure 
*/

int confin(char *file, char *seperator, char *search, char *value)
{
    FILE *conf;

    char *output;
    char *buffer;
    char line[256];


    if((conf = fopen(file, "r")) == NULL)                                   // Try to open file from path, return error if failed
    {
        fprintf(stderr, "Could not open config file \"%s\"!\n", file);
        return 1;
    }

    while (fgets(line, sizeof(line), conf) != NULL)                         // Read lines of file until the end is reached
    {
        buffer = strtok(line, seperator);                                   // Search for first appearance of seperator in line;
        if((strcmp(buffer,search)) == 0)                                    // If keyword is found,
        {
            buffer = strtok(NULL, seperator);                               // buffer the keyvalue,
            output = malloc(sizeof(buffer));
            strcpy(output, buffer);                                         // copy it into the output string,
            output[strcspn(output, "\n")] = 0;                              // replace the "\n" char from the end with terminating 0.
            strcpy(value,output);                                           // Store the new value in my return value     
            fclose(conf);
            free (output);
            return 0;                                                       // and return the value of output.        
        }
    }

    fprintf(stderr, "Could not find config keyword \"%s\"!\n", search);
    fclose(conf);
    return 1;

}


int main ()
{
    char value[256] = "\0";
    printf("%s\n",confin("test.conf","=","test",value));
}

Hope this matter is sorted out quick. Even if it means I DO have to use the pointer method at the end. Thanks in advance!

2
One way is to make a structure containing both a char* and an int; then make your function return that. It is common practice in C, however to just pass a char** as a return parameter if you want to return a char*.merlin2011
Another way in C could be to return the char* outcome in a pointer that is passed when the function is called. The return value of the function would then be an int to indicate if it succeeded or not.EmbedWise
My recommendation would be to use some printf statements in you function to trace what is happening. C can be funny when it comes to many of its standard library functions. They may not work as you think they do.FernandoZ
Returning NULL when you don't find a string value seems reasonable. Also, output = malloc(sizeof(buffer)); just allocates 4 or 8 bytes (the size of a pointer).Bo Persson

2 Answers

0
votes

Change:

int main ()
{
    char value[256] = "\0";
    printf("%s\n",confin("test.conf","=","test",value));
}

to:

int main ()
{
    char value[256] = "\0";
    int retval = confin("test.conf","=","test",value);
    if(retval)
        // some error handling
    printf("%s\n", value);
}

What you did was call confin, which assigned the string value to value, but you tried to print the returned int from this function (as a string) instead of value.

You could also just return char* and in case of the key not being present in your config file return NULL. This is an easy case just for "No such key" type error. In such a case you'd just have to check if confin returned NULL.

0
votes

You already got some good answers but I am quite suprised that nobody mentioned errno here. (https://en.wikipedia.org/wiki/Errno.h)

Errno is one common way in C to manage errors. You could for example set errno yourself in the function where the error occured and return NULL. This will inform the calling function that something went wrong.