2012-04-27 83 views
2

我有一個程序,我想從一個字符串中刪除空格。我想找到一個優雅的方式來做到這一點,所以我發現下面的(我已經改變了它一點,所以它可能是更好的可讀)代碼in a forumC如何知道我的字符串的結尾?

char* line_remove_spaces (char* line) 
{ 
    char *non_spaced = line; 
    int i; 
    int j = 0; 
    for (i = 0; i <= strlen(line); i++) 
    { 
     if (line[i] != ' ') 
     { 
      non_spaced[j] = line[i]; 
      j++; 
     } 
    } 
    return non_spaced; 
} 

正如你可以看到,該函數採用字符串,並使用相同的分配的內存空間,只選擇無間隔字符。有用!

無論如何,根據維基百科,在C的字符串是「Null-terminated string」。我一直認爲這樣,一切都很好。但問題是:我們把沒有「空字符」在non_spaced字符串的結尾。並以某種方式編譯器知道它的最後一個字符用「non_spaced」串改結束。它如何知道?

+0

你是什麼意思「編譯器知道它」?你在運行時改變它,編譯過程是long已過 – Fred 2012-04-27 11:34:46

+0

@Fred - 好點! – 2012-04-27 11:36:14

+2

對於它的價值,'strlen(line)'會重新計算字符串的長度時間。這是一個非平凡的計算,不應該在每個循環迭代中完成。你會更好地計算一次並存儲它:'size_t len = strlen(line); for(i = 0; i <= len; i ++)'。 (另外,你所有作爲int的變量在技術上應該是'size_t'類型。) – 2012-04-27 11:38:38

回答

9

這不會發生魔法。你在你的代碼:

for (i = 0; i <= strlen(line); i++) 
       ^^ 

循環索引i運行,直到strlen(line)這個指數有字符數組的NULL字符,這被複製爲好。結果你的最終結果在所需的索引處有nul字符。

如果你有

for (i = 0; i < strlen(line); i++) 
       ^^ 

,那麼你不得不手動將空字符爲:

for (i = 0; i < strlen(line); i++) 
{ 
    if (line[i] != ' ') 
    { 
     non_spaced[j] = line[i]; 
     j++; 
    } 
} 
// put nul character 
line[j] = 0; 
+0

空字符將是'\ 0'而不是'' – KBN 2012-04-27 11:42:43

+0

@xFortyFourx:http: //stackoverflow.com/questions/4705968/what-is-value-of-eof-and-0-in-c – codaddict 2012-04-27 11:45:07

+0

哇!我永遠不會明白。謝謝! (嚴重的是,我沒有注意到「<=」那裏) – vaulttech 2012-04-27 11:46:33

0

你可以試試。在處理僅包含一個空格的字符串時對其進行調試:''。仔細觀察指數i發生了什麼。

0

你怎麼知道它「知道」?最有可能的情況是,你只是在運行時遇到了未定義的行爲,並且在line的有效字節結束後有一個'\0'-字符。

這很可能是因爲你沒有在最後看到空格,可能會在打到流浪的「幸運'\0'」之前打印。

其他一些要點:

  • 沒有必要寫這個使用索引。
  • 在每次循環迭代中調用strlen()效率不高。
  • 您可能想要使用isspace()刪除更多空格字符。

這是我怎麼會寫它,使用isspace()和指針:

char * remove_spaces(char *str) 
{ 
    char *ret = str, *put = str; 

    for(; *str != '\0'; str++) 
    { 
    if(!isspace((unsigned char) *str) 
     *put++ = *str; 
    } 
    *put = '\0'; 

    return ret; 
} 

注意,這確實終止字符串的空間較少的版本,所以返回的指針一定是在點有效的字符串。

+1

不,代碼不是未定義的。它會工作 - 檢查比較運算符。 – 2012-04-27 11:39:02

+0

如果'line'是一個以空字符結尾的字符串,那麼'non_spaced'確保爲空終止,因此它不是'lucky'\ 0'「 – Anthales 2012-04-27 11:39:39

2

該循環使用<= strlen,因此您還將複製空終止符(位於i == strlen(line))。

0

你的函數的字符串參數爲空值終止的,對不對? 而在循環中,原始字符串的空字符也會被複制到非間隔返回的字符串中。所以非間隔字符串實際上也是空終止的!

對於您的編譯器,空字符只是另一個沒有得到任何特殊處理的二進制數據,但它被字符串API用作方便的字符來輕鬆檢測字符串的結尾。

3

其他人已經回答了你的問題,但這裏是一個更快,相同的代碼也許更清晰的版本:

void line_remove_spaces (char* line) 
{ 
    char* non_spaced = line; 

    while(*line != '\0') 
    { 
    if(*line != ' ') 
    { 
     *non_spaced = *line; 
     non_spaced++; 
    } 

    line++; 
    } 

    *non_spaced = '\0'; 
} 
0

如果使用「< = strlen的(線),strlen的長度(行)包括'\ 0' 所以你的程序可以工作。你可以使用調試和運行分析。

相關問題