sscanf()函数是否支持“递归”缓冲区?

5

我做了一些研究,想要查找 sscanf() 的源代码。但是我没有找到答案。

当我们以如下方式使用 sscanf()

char str[50] = "5,10,15";
int x;
sscanf(str,"%d,%s",&x,str);

sscanf()函数是否支持“递归”缓冲区str?

同时从同一内存区域读取和写入数据通常不是一个好主意。 - Some programmer dude
我知道这一点。但它可能得到 sscanf 函数的支持。这就是为什么我在寻找它的原因。也许 scanf 对此没有问题。这将使我能够优化我的代码。我将不必再添加另一个缓冲区并进行复制... - MOHAMED
顺便说一下,我在一个小程序中测试了它,执行过程中没有遇到任何问题。但我想从懂代码的人那里得到确认。 - MOHAMED
4
http://pubs.opengroup.org/onlinepubs/9699919799/functions/fscanf.html 中的源字符串上有一个 restrict 限定词。在参数列表中传递另一个指向 str 的指针可能会违反 restrict 承诺,但我对此并不完全确定。 - Mat
4个回答

3

它不会从自我修改的缓冲区中断开。但要使其(尾部)递归,您必须读取到字符串的末尾。
代码片段:

char str[]="5,10,15";
int a[10]={0},x = 0; 
while (sscanf(str,"%d,%s",a+ x++,str)>1);

读取所有整数。

由于这不是真正的递归,并且要读取的字符串不会覆盖字符串中的asciiz,我相信这在意义上是“安全”的:只能在家里尝试。


好技巧。显然不如使用%n和逐渐增加偏移量进入str循环来得有效率,这可能是问题要求的,但这是个好主意。我觉得你必须以相当愚蠢的方式实现sscanf才行不通。 - Nicholas Wilson

3

scanf系列函数逐个读取格式说明符并进行转换。在您的示例代码中:

char str[50] = "5,10,15";
int x;
sscanf(str,"%d,%s",&x,str);

可能会起作用,因为它首先读取一个整数和另一个C字符串。原始的str被新值覆盖,这里没有问题。

但考虑以下情况:

char str[50] = "5 10 15";
int x;
sscanf(str,"%s %d",str, &x);

这段代码首先从原始值中读取5,并覆盖了str,由于前一个%s的空终止符,str的末尾已经被读取完毕,因此后续的格式说明符%d无法从str中读取任何内容。

这只是一个反例,用来说明这是一个不好的想法,并且不起作用。因此可以说这将在某个时候引发未定义的行为或导致其他问题。


1
同意。即使使用正确,递归sscanf()很可能会触发下一个维护您代码的程序员的所有警报,让他们重复这个非平凡的推断。尊重你的同事的时间。保持你的代码可读性,不要让他们思考! - deStrangis

1
一般我会建议避免这样做。如果它能够工作一次并不意味着它在所有情况下都适用。要确保,您必须检查您使用的具体实现的源代码。如果您希望其具有可移植性,请立即忘记它,除非您在libc规范中看到写明作为保证行为。使用 strchr()查找下一个分隔符,并更新字符串指针以指向下一个字符。

0

使用strtok()解决了我曾经遇到的一个几乎相同的问题,即递归地使用sscanf()char*中提取内容(一串由空格分隔的double列表,例如"1.00 2.01 ..."),并将其转换为double数组(例如array[1]=1.00array[2]=2.01,...)。

如果我理解你的问题正确,以下内容可能会有所帮助:

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


int main(int argc, char** argv)
{
    char str[]= "5,10,15";
    char* token;

    int x[3];

    token = strtok(str, ",");

    for(int i=0; i<3; i++){

            sscanf(token, "%d", &x[i]);

            token = strtok(NULL, ",");

    }

    for(int i=0; i<3; i++) printf("%d\n", x[i]);

    return 0;
}

运行时,它会产生:

5
10
15

请参阅http://www.cplusplus.com/reference/cstring/strtok/,了解有关strtok()的有用描述。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接