2016-02-13 28 views
0

當我有一個功能,以空格替換選項卡中,看起來像這樣的字符串:分段故障detabing串

#include <stdio.h> 

char *detab(char *string) 
{ 
    for (int i = 0; string[i] != '\0'; i++) 
     if (string[i] == '\t') 
      string[i] = ' '; 
    return string; 
} 

int main(int argc, char **argv) 
{ 
    char *string = "\thello\thello"; 
    detab(string); 
    printf("%s\n", string); 
    return 0; 
} 

但是當我在"\thello\thello\t"運行它,它會產生分段錯誤。它爲什麼這樣做?我對C很新,所以我可能會錯過一些微不足道的東西。

+2

你不能修改字符串在C字面[是否有可能修改的char在C語言的字符串?](https://stackoverflow.com/questions/1011455/is-it-it-it-of-char-in-c/1011545#1011545) – Rabbid76

+0

我們不知道這個函數是否在字符串文字上被調用。你能否說明你是如何稱呼這個函數的,以及你如何聲明你作爲參數傳遞的東西? – e0k

+1

@ e0k他說:但是當我在「\ thello \ thello \ t」上運行它時 – Rabbid76

回答

2

這可能是因爲調用代碼沒有爲字符串分配足夠的空間。它必須始終至少分配一個大於字符串中可見字符的空間,以允許\ 0的空間。

這就是說,由於字符串是可變的,所以不需要返回字符串。它會在你工作時修改字符串。

這裏將是你的代碼的工作版本:

void detab(char * myStr) 
{ 
    for (int i = 0; myStr[i] != '\0'; i++) 
     if (myStr[i] == '\t') 
      myStr[i] = ' '; 
} 

char theString[] = "\thello\thello\t"; 
printf("Before: %s", theString); 
detab(theString); 
printf("After: %s", theString); 

另外,請記住以下幾點:

char buffer[4] = "test"; //THIS IS NOT SAFE. It might work, but it will overwrite stuff it shouldn't 
char buffer[5] = "test"; //This is Ok, but could be an issue if you change the length of the string being assigned. 
char buffer[] = "test"; //This is preferred for string literals because if you change the size of the literal, it will automatically fit. 

UPDATE:此基礎上添加的主要方法,這裏是你的問題:

您需要更改

char * string = "\thello\thello"; 

char string[] = "\thello\thello"; 

的原因是,當你定義一個字符串,並將其分配給一個char *,它駐留在記憶的文字部分,並且不能安全地修改。相反,您應該將字符串文字分配給一個char [](它可以作爲char *傳遞,因爲這是它的實際類型)。這個語法將讓編譯器知道它應該在堆棧上分配空間,並用字符串文本中的值填充它,從而允許修改它。

char * joe =「blah」只是創建char *指針,並將其指向文本部分中的數據(它是不可變的)。

char joe [] =「blah」告訴編譯器在堆棧上創建一個長度合適的數組,用字符串文字加載它來創建char *指針,然後將指針指向啓動堆棧上的數據陣列。

+1

我應該補充說,通常最好傳遞字符串的長度並使用它來代替檢查\ 0終止,因爲它可以允許函數在包含其他數據的二進制字符串上工作,而不僅僅是c字符串。 – techdude

+1

根據你如何分配你傳入的字符串,你必須小心,他們保持空終止,並且他們有足夠的空間分配。在你的問題中沒有足夠的上下文來確定你的問題是什麼,但這應該指向你正確的方向。 – techdude

+1

如果你正在使用malloc,讓我知道一些額外的細節,我可以覆蓋那些 – techdude

1

這工作:

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

char *detab(char *string) 
{ 
    for (int i = 0; string[i] != '\0'; i++) 
     if (string[i] == '\t') 
      string[i] = ' '; 
    return string; 
} 

int main (int argc, char ** argv) { 
    char str[21] = "\thello\thello\t"; 

    printf("%s\n", detab(str)); 

    return 0; 
} 

正如其他人所說,這可能是因爲段錯誤你正在修改一個字符串。使用char str[21]時,字符串文字被複制到堆棧分配的str中,然後可以在其中通過函數進行修改。

+0

沒有必要這樣做。假如它被分配給在堆棧上分配的char數組,它就會很好。 – techdude

+0

我想你的意思是''char str [21] =「\ thello \ thello \ t」''......是的,那也行得通。謝謝,我會更新我的答案。 – Chad

0

你確定字符串總是空終止。

嘗試一些帶和揹帶......

char *detab(char *string) 
{ 
    int s_len= strlen(string) + 1; 

    for (int i = 0; string[i] != '\0'; i++) 
    { 
     if (string[i] == '\t') 
     { string[i] = ' '; } 
     if (i == s_len) { /* failure - print some diagnostic */ return NULL; } 
    } 
    return string; 
    } 
+0

這不會是一個足夠的檢查,因爲strlen使用空終止字符來確定長度,這與OP最初所做的沒有什麼不同。 http://www.cplusplus.com/reference/cstring/strlen/ – techdude

+0

字符串文字自動爲您插入「\ 0」。 – Majora320

+0

strlen返回字符串的大小,不包括空終止字符,因此除了s_len(有人已經整理成一個而不是兩行)。 – cdcdcd