2011-04-20 116 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'; 
     } 
}