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

发布于 2024-09-13 21:36:56 字数 413 浏览 8 评论 0原文

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

我正在考虑使用 strchrstrcat,如下所示:

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

    return s;
}

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

接下来,我想知道是否可以使用 sscanf 之类的东西做得更好。

I have a string representing an integer with spaces -- digits are grouped by three.

I was considering using strchr and strcat, as in:

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

    return s;
}

But, first, I'm not sure it is safe to use strcat this way since the string to be appended overlaps the final string.

Next, I'm wondering whether this could be done better with something like sscanf.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

何以笙箫默 2024-09-20 21:36:56
char* trim (char* s)
{
    char* space;
    while (space = strchr(s, ' '))
    {
        memmove(space,space+1,strlen(space));
    }

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

    return s;
}
魂牵梦绕锁你心扉 2024-09-20 21:36:56

您可以使用 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 来完成此操作,但我不确定这是否会更快。

You could use 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;
}

EDIT:

If you have a constant number of items in each line you could just use malloc with that value instead of pre-counting the number of spaces in the string.

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

You could probably do this with malloc and realloc as well but I'm not sure if that would be faster.

ゃ人海孤独症 2024-09-20 21:36:56

对于这种简单的问题,通常最简单的方法是逐个字符地循环:

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

使用相同的缓冲区进行读取和写入是安全的,因为我们知道修剪后的字符串总是比原始字符串短。这是最快的解决方案,因为每个字符最多读取一次并写入一次。

当源和目标重叠时,您不能使用 strcpy() —— 规范禁止这样做。

我不知道 scanf();其中隐藏着各种晦涩但有用的东西,值得仔细阅读手册页。

已编辑:修复了导致它不起作用的愚蠢拼写错误。

For this kind of simple problem it's usually easiest just to loop through character by character:

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

It's safe to use the same buffer for both reading and writing because we know the trimmed string will always be shorter than the original string. This is the fastest possible solution as each character is read once and written at most once.

You can't use strcpy() when the source and destination overlap --- the specification forbids it.

I'm don't know about scanf(); there's all kinds of obscure yet useful stuff buried deep within it, and it's worth going through the man page.

Edited: fixed the stupid typo that meant it didn't work.

月下客 2024-09-20 21:36:56

基于 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 应该在输入字符串中的何处开始。

An alternative method based on David Given's:

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

I wouldn't worry about performance issues of using memmove unless your strings are really large. There isn't an easy way of using sscanf for this as it is hard to define where in the input string each call to sscanf should begin.

蓝眸 2024-09-20 21:36:56

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

如果您仔细查看,您会发现可能可以在网络上找到几十个(或更多)此实现(一个示例)。

No, your use of strcat is not safe (§7.21.3.1/2: "If copying takes place between objects that overlap, the behavior is undefined.")

If you do a bit of looking, you can probably find a few dozen (or more) implementations of this on the web (one example).

苦笑流年记忆 2024-09-20 21:36:56

您可以使用 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;
}

You could use strtoul for the conversion, without having to manipulate the string at all. strtoul converts as much as it can, and tells you where it stopped. Handily it also skips over leading white space. So:

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文