我有一个表示带空格的整数的字符串 - 数字按三个分组。
我正在考虑使用strchr
和strcat
,如:
char* remove_spaces (char* s)
{
char* space;
while (space = strchr(s, ' '))
{
*space = '\0';
strcat(s, space + 1);
}
return s;
}
但是,首先,我不确定以这种方式使用strcat
是否安全,因为要附加的字符串与最终字符串重叠。
接下来,我想知道是否可以通过sscanf
等方式做得更好。
答案 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;
}