-4

So I have function that logs some data and writes that to a file and returns the path to the file as a string.

I then need to take that string and pass it to a function that parses the file and places the data in a structure

before the file can be parsed though, the string path needs to be "transformed" so each directory delimiter includes the escape character for the backslash. for this I pass the string to another function.

At a high level this seems like a very easy task, but I believe I am not passing the original return string correctly to the other functions, because when I check the output in the console after I have transformed I receive the gibberish characters. below is a simplified example of what I am trying to do. I know my method of transformation is not the problem because if I take the lines of code that are in the nested transform function and put them in main(), everything works smooth, so it must be the way I am passing the pointer through the other functions and then trying to operate.

main(){
    char* filePath = logData();
    parseData(filePath);
}

int parseData(char* filePath){

    char* transformFile = transFormPath(filePath);

    //parse data from transformFile

    return 0;
}

char* transFormPath(char* filePath){      

    //transform filePath to newPath

    return newPath;

}

any help would be greatly appreciated, thanks!

skevthedev
  • 447
  • 1
  • 7
  • 20
  • 1. function definition should be `char* transformPath(char *filepath)' Similarly for `parsedata`. 2. There should be a return statement at the end of `parsedata` 3. You can then capture this new pointer in the main with `filepath = parsedata(filepath)` – Rishikesh Raje Oct 06 '16 at 13:01
  • what does tranformPath do? – λuser Oct 06 '16 at 13:04
  • @RishikeshRaje is there really a difference between char* filePath and char *filePath? the return statement for parseData is an integer, I didn't include this because it is not relevant to the issue I am having. thanks for the help! – skevthedev Oct 06 '16 at 13:09
  • The code is not standard compliant omitting the return type is discouraged since 27 years! Write standard C, not prehistoric K&R-C. Also `const` qualifying parameters helps the compiler to detect errors. And provide a [mcve]. – too honest for this site Oct 06 '16 at 13:12
  • @λuser transformPath, takes the filePath and steps through each character and if it finds a backslash, it replaces it with an escaped backslash, creating a new character array that represents the new filepath that will be returned and used for the parsing. this works, I just only get it to work when the statements are part of main, and not in the nested functions – skevthedev Oct 06 '16 at 13:13
  • How shall `transformPath` return a `char *`? it is `int` – too honest for this site Oct 06 '16 at 13:15
  • @olaf fixed those issues, just kind of hacked it together, this is not my code obviously, just something I hacked together to give small example. thanks for the help – skevthedev Oct 06 '16 at 13:18
  • post the whole code, it's a pain to try to guess potential problems in code we can't see... – λuser Oct 06 '16 at 13:58

1 Answers1

1

In C, string operations cannot have a convenient interface, because of memory management. If a function receives a string, and converts it to another string, you should decide how to declare its interface.

The simplest interface is in-place (strtok uses it); you can use it only if the output is somehow smaller than input:

void func(char* input_and_output);

A more traditional interface is "output in pre-allocated buffer" (sprintf uses it); you can use it only if it's possible to calculate or somehow constrain the size of the output:

void func(const char* input, char* output);

Another idea is "allocate the output dynamically" (asprintf uses it); it doesn't have limitations but is harder to use:

char* func(const char* input);

Its disadvantage is the responsibility that it imposes on the caller - it must free the allocated string at some time in the future.


Let's use the third interface:

char* transFormPath(const char* filePath)
{
    char* newPath;
    newPath = malloc(100); // is 100 enough? no idea
    strcpy(newPath, "haha"); // just an example
    return newPath;
}

int main()
{
    ...
    char* filePath = "path";
    char* newPath = transFormPath(filePath);
    ...
    free(newPath);
}

If you decided to use this interface, your transFormPath function should allocate the string dynamically, and the caller should free the string at some time when it's not needed anymore. This is not trivial to accomplish - usually the "time when the string is not needed" is not easy to define, and if you change your code, the time when it's safe to call free can change without you realizing it. As a quick-and-dirty hack, you can write your code without freeing memory (i.e. introduce a memory leak on purpose).


Let's use the second interface:

void transFormPath(const char* filePath, char* newPath)
{
    // Here we assume newPath has enough space to hold the output
    strcpy(newPath, "haha"); // just an example
}

int main()
{
    ...
    char* filePath = "path";
    char* newPath = malloc(100); // is 100 enough? no idea
    transFormPath(filePath, newPath);
    ...
    free(newPath);
    ...
    char newPath2[100]; // is 100 enough? no idea
    transFormPath(filePath, newPath2);
}

A handy rule of thumb is "malloc and free should be called in the same function" - this interface makes it possible not to violate it.

Also, this interface makes it possible to use stack (automatic) memory allocation - if there is some limit on the size of the output, just allocate the maximum possible buffer on stack.

anatolyg
  • 26,506
  • 9
  • 60
  • 134