如何将带空格的字符串解析为整数

时间:2010-08-09 15:01:29

标签: c parsing integer

我有一个表示带空格的整数的字符串 - 数字按三个分组。

我正在考虑使用strchrstrcat,如:

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

    return s;
}

但是,首先,我不确定以这种方式使用strcat是否安全,因为要附加的字符串与最终字符串重叠。

接下来,我想知道是否可以通过sscanf等方式做得更好。

6 个答案:

答案 0 :(得分:4)

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

    return s;
}

答案 1 :(得分: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做到这一点,但我不确定那会更快。

答案 2 :(得分: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();有深藏在其中的各种晦涩但有用的东西,值得通过手册页。

编辑:修复了愚蠢的错字,意味着它无效。

答案 3 :(得分:1)

基于David Given的替代方法:

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

我不担心使用memmove的性能问题,除非你的字符串非常大。没有一种简单的方法可以使用sscanf,因为很难定义输入字符串中每次调用sscanf的位置。

答案 4 :(得分:0)

不,您使用strcat并不安全(§7.21.3.1/ 2:“如果在重叠的对象之间进行复制,则行为未定义。”)

如果你做一些观察,你可以在网上找到几十(或更多)这样的实现(one example)。

答案 5 :(得分: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;
}