2011-04-20 159 views
1

嘿! 我被卡在一個ANSI C問題,我認爲這應該是相當平凡的(至少在任何現代語言中:/)。ANSI C分割字符串

我的腳本的(臨時)目標是分割一個包含6個字符(「123:45」)的字符串(「字符數組」),它代表時間戳分鐘:秒(對於音頻文件,因此可以有120分鐘)分爲幾分鐘和幾秒鐘。

我嘗試了幾種方法 - 一般尋找「:」和一個硬編碼的方法,只是通過索引分割字符串,但似乎沒有任何工作。

void _splitstr (char *instr, int index, char *outstr) { 
char temp[3]; 
int i; 
int strl = strlen (instr); 
if (index == 0) { 
    for (i = 0; i < 3; ++i) { 
     if (temp[i] != '\0') { 
      temp[i] = instr[i]; 
     } 
    } 
} else if (index == 1) { 
    for (i = 6; i > 3; i--) { 
      temp[i] = instr[i]; 
     } 
    } 
strcpy (outstr, temp); 
} 

另一個「有趣」的事情是,char [3]的字符串長度是6或9,實際上從來沒有3.這是什麼問題?

+0

功課?如果是,請告訴我們。 – pmg 2011-04-20 16:11:18

+0

你的代碼嘗試將3個字符放入'temp'(它可以容納),然後在「string」函數中使用'temp'。一個字符串需要以空字節結尾。你的'temp'沒有空字節的空字節。 – pmg 2011-04-20 16:13:10

回答

6

有關使用sscanf()如何。儘可能簡單。

char time[] = "123:45"; 
    int minutes, seconds; 

    sscanf(time, "%d:%d", &minutes, &seconds); 

如果您可以確定時間字符串語法總是有效,那麼這種方法效果最佳。否則,您必須添加檢查。成功時,sscanf函數返回成功讀取的項目數,因此也很容易檢測錯誤。

工作示例:http://ideone.com/vVoBI

+1

上帝這可能讓我一整天瘋狂的調試,謝謝! 我不認爲這會很容易>。> – Asmodiel 2011-04-20 16:28:23

1

......怎麼

int seconds, minutes; 
minutes = atoi(instr); 
while(*instr != ':' && *++instr != '\0'); 
seconds = atoi(instr); 

應該是相當快。

+0

雖然我認爲如果'instr'不會包含冒號字符,這可能會導致SIGSEGV或類似的崩潰(或可能產生無意義的結果),這有點嚴厲。 – 2011-04-20 16:18:26

+0

這很好,但應該添加NULL字符。 – 2011-04-20 16:19:37

+0

@Simon Nickerson,@Athabaska Dick:的確如此。它不能容忍錯誤。我將添加'NULL'檢查。稍微慢一些,但不應該是一個問題;) – Wolph 2011-04-20 22:12:02

0

你可以嘗試這樣的事情:

void break_string(const char* input, char* hours, char* minutes) 
{ 
    if(input == 0 || hours == 0 || minutes == 0) 
     return; 

    while(*input != ':') 
     *hours++ = *input++; 

    *hours = '\0'; 
    ++input; 

    while(*minutes++ = *input++); 

    return; 
} 

這裏是相同的功能有點簡單:

void break_string(const char* input, char* hours, char* minutes) 
{ 
    if(input == 0 || hours == 0 || minutes == 0) 
     return; 

    while(*input != ':') 
    { 
     *hours = *input; 
     ++hours; 
     ++input; 
    } 
    *hours = '\0'; 

    ++input; //ignore the ':' part 
    while(*input) 
    { 
     *minutes = *input; 
     ++minutes; 
     ++input; 
    } 
    *minutes = '\0'; 

    return; 
} 

int main() 
{ 
    char* test = "123:45"; 
    char* minutes = malloc(sizeof(char) * 12); 
    char* hours  = malloc(sizeof(char) * 12); 
    break_string(test , hours , minutes); 
    printf("%s , %s \n" , hours , minutes); 
    //... 
    free(minutes); 
    free(hours) ; 
} 
+0

爲什麼'malloc'並複製已經在內存中的東西?你可以只保留兩個指向原始字符串的指針。 – 2011-04-20 16:14:52

0

您有三個基本選項

  • 改變輸入字符串(不能是字符串文字)
  • 將數據複製到輸出s trings(輸入可以是文字)
  • 變換的字符序列爲數字

改變輸入串意味着轉化"123:45""123\0" "45"具有嵌入式零。

複製數據意味着管理副本的存儲。

轉換字符序列意味着使用例如strtol

0

您不會在temp []中的字符串中加上終止空格,所以當您執行strlen(temp)時,您正在訪問任意內存。

使用你已知的長度,你可以使用這樣的事情:

char temp[4]; 
if (index==0) 
{ 
    strncpy(temp, instr, 3); 
    temp[3] = 0; 
} 
else if (index==1) 
{ 
    strncpy(temp, instr+4, 2); 
    temp[2] = 0; 
} 
strcpy(outstr, temp); 

不過,我會告誡說,我已經跳過各種檢查中INSTR和outstr有效長度。

0

This?

char *mins, *secs; 
mins = str; 
while(*(++str) != ':'); 
str[0] = '\0'; 
secs = s + 1; 
0

這裏有一種方法,我有忽略上面的 「指標」 的說法:

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

void _splitstr (char *instr, char *outstr) { 
     char temp[10]; 
     char* end = strchr(instr, ':'); 
     int i = 0; 

     if(end != 0) { 
       while(instr != end) 
         temp[i++] = *instr++; 
       temp[i] = '\0'; 
       strcpy(outstr, temp); 
     } else { 
       outstr = '\0'; 
     } 
}