2010-08-09 111 views
4

我有一個字符串表示一個整數與空格 - 數字分爲三。如何用空格解析字符串到整數

我用strchrstrcat,如考慮:

char* remove_spaces (char* s) 
{ 
    char* space; 
    while (space = strchr(s, ' ')) 
    { 
     *space = '\0'; 
     strcat(s, space + 1); 
    } 

    return s; 
} 

但是,第一,我不知道它是安全的使用strcat這種方式,因爲要追加字符串重疊,最後一個字符串。

接下來,我想知道這是否可以用sscanf之類的東西做得更好。

+0

裝飾表明,字符正在從字符串開始處或結束脩整,我會重命名功能removeSpaces()或類似 – Patrick 2010-08-09 15:15:39

+0

這是正確的!我糾正了。 – 2010-08-10 07:06:29

+0

我正在考慮基於特殊區域設置的解決方案,將decimal_separator設置爲空格。我沒有時間去嘗試,所以如果有人想得到一些代表...繼續前進! – Sjoerd 2010-08-10 07:08:30

回答

4
char* trim (char* s) 
{ 
    char* space; 
    while (space = strchr(s, ' ')) 
    { 
     memmove(space,space+1,strlen(space)); 
    } 

    return s; 
} 
+1

由於反覆讀寫字符串的後續部分,這不是真的效率低下嗎? – 2010-08-09 15:12:54

+0

表現不是問題 – user411313 2010-08-09 16:47:15

0

不,你的strcat使用並不安全(§7.21.3.1/ 2:「如果進行復制操作是重疊的對象之間,行爲是不確定的。」)

如果你做一點看,你可能會在網上找到幾十個(或更多)這個實現(one example)。

1

你可以使用strtok的

//asuming line points to the beginning of your string 

char *col_str = line, c; 
short int *the_numbers; 
int col, col_num, count = 0; 
while((c = *col_str++) != '\0'){ 
    if(c == ' '){ 
     count++; 
    } 
} 

the_numbers = (*short int)malloc(sizeof(short int)*count+1); 

for(col_num = 0,col_str = line; ; col_num++,col_str = NULL){ 
    col = atoi(strtok(col_str, ' ')); 
    the_numbers[col_num] = (short int)col; 
} 

編輯:

如果你在每一行,你可以只用malloc與價值,而不是預先計算-的空格數中的項目的常數字符串。

short int *the_numbers = (short int*)malloc(NUM_ITEMS * sizeof(short int)); 

你或許可以用malloc和realloc做到這一點,但我不確定這是否會更快。

+0

這就是我正在建議的。 – James 2010-08-09 15:14:07

+1

我不認爲這是作者所問的---不是最終會包含數字的最後一個子句的數字值嗎? – 2010-08-09 15:14:58

+0

他將不得不將它們存儲在整數數組中,我想我應該包含該部分 – GWW 2010-08-09 15:15:40

1

對於這種簡單的問題,它的性質通常是最容易通過字符只是循環:

void trim(char* buffer) 
{ 
    char* r = buffer; 
    char* w = buffer; 
    for (;;) 
    { 
     char c = *r++; 
     if (c != ' ') 
      *w++ = c; 
     if (c == '\0') 
      break; 
    } 
} 

它的安全使用同一個緩衝的讀取和寫入,因爲我們知道修剪字符串永遠是短比原來的字符串。這是最快的解決方案,因爲每個字符只讀一次,最多一次寫入。

當源和目標重疊時,不能使用strcpy() - 規範禁止它。

我不知道scanf();有各種各樣的晦澀而有用的東西埋在它的內部,值得通過手冊頁。

編輯:修復了愚蠢的錯字,這意味着它沒有工作。鑑於

+0

-1這實際上並不改變緩衝區的內容 – Patrick 2010-08-09 15:38:10

+0

D'oh!你是對的。固定。 – 2010-08-09 15:58:35

+0

-1已刪除,並剛剛添加了我自己的想法 – Patrick 2010-08-09 16:04:17

1

根據大衛的另一種方法的:

void removeSpaces(char* str) 
{ 
    char* input = str; 
    char* output = str; 
    for(; *input != 0; ++input) 
    { 
     if(*input != ' ') 
      *output++ = *input; 
    } 
    *output = 0; 
} 

我不會擔心使用的memmove的性能問題,除非你的字符串是真正的大。有沒有一種簡單的方法來使用sscanf,因爲很難定義每個調用sscanf的輸入字符串應該在哪裏開始。

+0

我接受gordongekko的答案,因爲字符串足夠短不會影響性能,但我真的很喜歡你的! – 2010-08-10 07:29:53

0

您可以使用strtoul進行轉換,而不必操縱字符串。 strtoul儘可能轉換,並告訴你它停在哪裏。有用它也跳過領先的白色空間。所以:

static unsigned long conv(const char* s) 
{ unsigned long num, dig; 
    char* endp; 

    for(num=0;;s=endp) 
    {  dig = strtoul(s, &endp, 10); 
      if (s == endp) 
      { break; 
      } 
      num = num*1000 + dig; 
    } 
    return num; 
}