2016-11-17 29 views
-1

我想把一個字符串操作外包給一個函數,然後詢問main的結果。這不起作用,我不明白爲什麼。外包strtok()函數中的c

#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; 
} 

回答

3

splitRequest函數中,所有參數都是指針。更重要的是它們是局部變量。因此,對它們所做的所有更改(如將它們指向其他任何地方)只會影響局部變量,沒有別的。

解決方法是將拷貝到而不是內存。也許類似

char *temp; 

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

// And so on... 

什麼我意思是一點點的闡述......

在C語言中所有的函數參數通過值傳遞。這意味着它們的值是被複制並且該函數只有該值的本地副本。 Chaning副本當然不會改變原始值。

這與指針相同。當您致電splitRequest函數時,您傳遞的指針將被複制。在函數內部,變量method(例如)指向您在main函數中定義的數組的內存。當你分配給這個變量時,就像你用

method = strtok(...); 

你只能修改局部變量,指針的本地副本。當函數返回本地變量method超出範圍,並且對其所做的所有更改都將丟失。

這個問題有兩種解決方法。一是參照效仿通(一些東西,C沒有,這就是爲什麼它必須被仿真),但不會,只要你有一個數組工作。因此,第二和簡單的解決方案:要副本到內存指向的局部變量method,這是我看到前面。

一個重要的注意,雖然:當你調用splitRequest函數,將數組,數組本身不通過。相反,數組衰減爲指向其第一個元素的指針,而在函數內部,由參數定義的變量是指針而不是數組。

呼叫

splitRequest(request, method, ressource, proto); 

等於

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

和函數聲明

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

等於

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

所以沒有琴絃不會被複制,唯一的指針。否則,分配給指針時,你會得到一個錯誤,因爲你不能分配給數組只拷貝給他們。

+0

我有沒有正確認識,即*溫度則成爲局部變量請求指向某一部分?此外,這些字符串都是從main複製到splitRequest的? – Linz

+0

@Linz更新了我的回答 –

+0

非常感謝您的詳細解釋。我想我現在已經明白了。 – Linz

0

找到另一個解決辦法更有效實現了:

#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; 
}