2016-02-22 70 views
-1

我得到一個指向作爲函數參數傳遞的字符串的指針,我需要更改字符串中的幾個字符。我將字符串複製到一個char數組中,並編輯我需要的東西,但是我需要將指向的原始字符串更改爲剛剛創建的新char []。更改指針指向的值的值C

該函數必須返回void,並且因爲傳遞的指針只是main的一個副本,所以將其設置爲指向新的char []將不會執行任何操作,因爲它只會在函數結束,所以我需要實際更改指向的字符串。

*str = &newstr[0] 

這給了我編譯器錯誤:賦值使得指針中的整數沒有強制轉換。

*str = newstr 

而這是運行該程序時的子網段。

以下是完整的功能:

void replace(char* str, char toReplace, char replaceWith) { 
    int strLen = strlen(src); 
    char newstr[strLen]; 
    int i; 
    for (i = 0; i < strLen; i++) { 
    if (str[i] == toReplace) 
     newstr[i] = replaceWith; 
    else 
     newstr[i] = str[i]; 
    } 
    // How to change the value of the string being pointed to by *str to now be newstr? 
} 
+3

爲什麼不直接在字符串上工作?請注意字符串是如何創建的,如果您正在測試字符串文字,您將無法更改它,因爲它被放置在只讀內存部分。 – DMH

+1

請顯示您的實際功能。 – paddy

+0

它是一個字符串文字。 – Jeremiah

回答

0

How to change the value of the string being pointed to by *str to now be newstr?

你不能因爲(1)你傳遞str的功能char *s的方式(2),因爲你聲明newstr爲一個局部變量replace。 (也可能爲那些不是從您發佈的代碼有限的部分確定的其他原因一大堆)

當你傳遞一個指針的函數,該函數接收指針的副本非常自己的差別很大內存地址。換言之,當您在函數參數列表中聲明參數char *str時,會創建一個新指針。 (它仍指向str中的任何內容,但其可變地址與調用函數中的原始指針地址非常不同 - 因此,您對str的地址所做的任何操作都不會在調用函數中反映出來)。如果你想給一個函數中的指針分配一個新地址,你必須通過從調用者傳遞原始地址。例如

void replace(char **str, char toReplace, char replaceWith) 

,然後在調用程序與調用它:

replace (&origPtr, char toReplace, char replaceWith) 

(作爲一種風格旁白:不要使用用C CamelCase變量,camelcase是正確的)

最後,由於當您退出功能replace時,newstr的地址將被銷燬,您將newstr的地址指定爲*str的唯一選項是(1)聲明newstr作爲static,或(2)動態分配newstr(例如, char *newstr = malloc (sizeof *newstr * strLen + 1);。然後,您可以將newstr的值指定爲str。例如:

void replace(char **str, char toReplace, char replaceWith) { 
    int strLen = strlen(*str); 
    int i; 
    char *newstr = malloc (sizeof *newstr * strLen + 1); 
    if (!newstr) { 
     fprintf (stderr, "error: virtual memory exhausted.\n"); 
     exit (EXIT_FAILURE); 
    } 
    for (i = 0; i < strLen; i++) { 
     if ((*str)[i] == toReplace) 
      newstr[i] = replaceWith; 
     else 
      newstr[i] = (*str)[i]; 
    } 
    newstr[strLen] = 0; /* nul-terminate (or use calloc to allocate) */ 
    free (*str);  /* MUST have been dynamically allocated in caller */ 
    *str = newstr; 
} 

注:str一定不是靜態地調用函數聲明,你必須free的內存它指向的塊或者你會被改寫的起始地址爲創建內存泄漏內存它原來指向塊 - 使其無法釋放原始塊)

所有這些原因的原因,最好是通過更改到位toReplacereplaceWith字符來解決這個問題(假設它str是一個陣列,而不是一個字串文本),或使一個附加的陣列,以填補替換作爲參數(或作爲指針分配 - 或返回一個指針的存儲器包含新新分配的塊串)。

讓我知道你是否還有其他問題。

+0

函數中需要什麼** str?爲了支持多個字符串? –

+0

好的。你正在釋放傳遞的字符串。但是這個函數使得像str這樣的假設應該被分配了內存。 –

+0

因爲您將通過傳遞原始指針的地址來調用該函數。 (例如'替換(&origPtr,char toReplace,char replaceWith)')。所以在你的主代碼中,你會說'char * origPtr;'(將被分配和填充)。你會傳遞它是'&origPtr',它是'char **'。 –

1

消化對您的問題所有的評論之後,我走到那你要調用你的函數以下列方式理解:

char * str = "string literal"; /* compiler should have warned you about assigning 
            string literal to non-const pointer.   */ 
replace(str, 'i', 'u'); 
printf("%s\n", str); 

現在,這個問題是任何企圖修改str指向的內存將爲未定義的行爲

您在解決方案中的嘗試是嘗試更改函數內的實際指針。但要這樣做,您的replace函數將需要接受char**,然後分配新的內存。在這種情況下,這不是一個好方法。你真的只需要在原地修改字符串:

void replace(char* str, char toReplace, char replaceWith) 
{ 
    while(*str) 
    { 
     if(*str == toReplace) *str = replaceWith; 
     str++; 
    } 
} 

如何處理字符串文字?那麼,解決方案很簡單。製作陣列:

char str[] = "string literal"; 
replace(str, 'i', 'u'); 
printf("%s\n", str);