简体   繁体   中英

outsourcing strtok() in function in c

I want to outsource a string operation to a function and then ask the results in main. This doesn't work, and I don't understand why.

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

void splitRequest(char request[], char method[], char ressource[], char proto[]) {

    method = strtok(request, " ");
    ressource = strtok(NULL, " ");
    proto = strtok(NULL, " ");
    printf("\nResult:\n\nmethod:\t\t%s\nressource:\t%s\nproto:\t\t%s\n",method,ressource,proto);
}

int main()
{    
    char method[50], ressource[50], proto[50], request[50];
    memset(method, '\0', 50);
    memset(ressource, '\0', 50);
    memset(proto, '\0', 50);
    memset(request, '\0', 50);
    strcpy(request,"Get /index.htm HTTP/1.1");

    //rehash query
    splitRequest(request, method, ressource, proto);

    //check Results
    printf("\nResult:\n\nmethod:\t\t%s\nressource:\t%s\nproto:\t\t%s\n",method,ressource,proto);

    return 0;
}

In the splitRequest function all the arguments are pointers. And more importantly they are local variables . So all changes to them (like making them point anywhere else) will only affect the local variable, nothing else.

The solution is to copy to the memory instead. Perhaps something like

char *temp;

if ((temp = strtok(request, " ")) != NULL)
{
    strcpy(method, temp);
}

// And so on...

A little elaboration about what I mean...

In C all function arguments are passed by value . That means their value is copied and the function only have a local copy of the value. Chaning the copy will of course not change the original value.

It is the same with pointers. When you call your splitRequest function the pointers you pass are copied. Inside the function the variable method (for example) is pointing to the memory of the array you defined in the main function. When you assign to this variable, like you do with

method = strtok(...);

you only modify the local variable, the local copy of the pointer. When the function returns the local variable method goes out of scope, and all changes to it are lost.

There are two solutions to this problem. One is to emulate pass by reference (something which C doesn't have, which is why it must be emulated), but that will not work as long as you have an array. Therefore the second and easiest solution: To copy to the memory pointed to by the local variable method , which is what I show above.

An important note though: When you call the splitRequest function, passing the arrays, the arrays themselves are not passed. Instead the arrays decays to a pointer to their first element, and inside the function the variables defined by the arguments are pointers and not arrays.

The call

splitRequest(request, method, ressource, proto);

is equal to

splitRequest(&request[0], &method[0], &ressource[0], &proto[0]);

And the function declaration

void splitRequest(char request[], char method[], char ressource[], char proto[])

is equal to

void splitRequest(char *request, char *method, char *ressource, char *proto)

So no the strings are not copied, only the pointers. Otherwise you would have gotten an error when assigning to the pointer, since you can't assign to arrays only copy to them.

Found another workaround even more effectiv:

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

void splitRequest(char request[], char **method, char **ressource, char **proto) {

    *method = strtok(request, " ");
    *ressource = strtok(NULL, " ");
    *proto = strtok(NULL, " ");
    printf("\nResult:\n\nmethod:\t\t%s\nressource:\t%s\nproto:\t\t%s\n",*method,*ressource,*proto);
}

int main()
{    
    char *method, *ressource, *proto, request[50];
    memset(request, '\0', 50);
    strcpy(request,"Get /index.htm HTTP/1.1");

    //rehash query
    splitRequest(&request, &method, &ressource, &proto);

    //check Results
    printf("\nResult:\n\nmethod:\t\t%s\nressource:\t%s\nproto:\t\t%s\n",method,ressource,proto);

    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM