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!
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.