您的位置:首页 > 编程语言 > Go语言

sscanf一小用法

2011-07-28 16:25 211 查看
背景:欲从FTP服务器下载一文件,须知其大小,使用SIZE命令无效(该命令在RFC959中未出现,即非标准命令)。经测试发现RETR命令返回的信息中包含了文件大小,即字节数,现需要将其从字符串中解析出来。

PS:本人是写代码的,并非使用工具的。

信息如:"150 Opening BINARY mode data connection for latelee.dat (29068 bytes)\r\n\0"

后面写出“\r\n\0”没其它意思,只表明该命令以\r\n结尾,为一正常字符串(以'\0'结束)。

方法1:逐一解析该字符串,遇到左括号作一标志,遇到右括号作一标志,中间者即为我们所需要字符串,再从中解析出数字。示意代码(示意而已,非实际用中)如下:

    for (int i = 0; foo[i] != '\0'; i++)

    {

        if (foo[i] == '(')

        {

            do {

            buf[j++] = foo[i++];

            } while (foo[i] != ')');

            buf[j++] = '\0';

        }

    }

方法2:使用字符串操作函数,示意代码如下:

    char buf1[32];

    char *p1, *p2;

    p1 = strchr(foo, '(') + 1;

    p2 = strchr(foo, ')') -1;

    strncpy(buf1, p1, p2-p1);

    buf1[p2 - p1] = '\0';

方法3:使用sscanf函数,这个函数很早就留意到了,只是没使用它的高级用法。所谓高级者,大部分时间不使用,一旦使用到,便觉得神奇,正如某人低调刻苦研究,不为人所知,突然搞出一重大成果,便一举成名。

关于sscanf函数,网上有资料,不过绝大部分都基本同一版本演绎,以“sscanf用法”为关键字google即可找到多篇相同文章。此处结合前面提出的问题说一下我对它的理解(其实没有理解,只使用它解决问题而已)。

示意代码如下:

    char foo[] = "150 Opening BINARY mode data connection for latelee.dat (29068 bytes)";

    char buf[32];

    int size = 0;

    sscanf(foo, "%*[^(](%s[^)]", buf);

    sscanf(foo, "%*[^(](%d[^)]", &size);

其中buf为一数组,size为整型(不是整形)类型。结果都能输出29068,前者是一个字符串,后面的是整型数据。buf实际数据为"29068\0",以'\0'结束,可放心使用。

sscanf似乎是以单词为单位,本来是输出"29068 bytes”然而后面的bytes并没有存储到buf中,“%*[^(]”表示过滤掉“(”前面所有字符,直到遇到“(”为止,%s与%d分别表示以字符串、整型存储,注意它们前面还有一个“(”,这个是必须的,不然会被识别为"(29068"的,后面的“[^)]”表示直到遇到右括号“)”为止——不过似乎改写成“[^ ]”更好一些,即遇到空格符号为止。

此法针对某一固定格式的字符串,个人认为使用sscanf还是挺好的,虽然没有比较过上面几种方法的效率,但个人更喜欢使用sscanf函数。

 

2013-05-09补记:

最近又遇到需要使用sscanf的情况,下面简单写一下。

问题:uboot在启动时需要写日志,该日志存放到EEPROM,并且带有时间信息,现在为了处理时间,需要将时间信息解析出来。

方法:使用scanf一一解析出时间及其它信息。

举例:

    int year, month, day, hour, min, sec;

    char p[] = "2000-01-01 01:35:02:come on!! hello world!!!";

    char tmp[128] = {0};

    printf("org: %s\n", p);

    sscanf(p, "%04d-%02d-%02d %02d:%02d:%02d%[ -~]", &year, &month, &day, &hour, &min, &sec, tmp);

    //strcpy(tmp, p + 19);

    printf("%04d-%02d-%02d %02d:%02d:%02d\n", year, month, day, hour, min, sec);

   

    year += 1;

    day += 1;

    sprintf(p, "%04d-%02d-%02d %02d:%02d:%02d%s", year, month, day, hour, min, sec, tmp);

    printf("new: %s\n", p);

 

结果:

org: 2000-01-01 01:35:02:come on!! hello world!!!

2000-01-01 01:35:02

new: 2001-01-02 01:35:02:come on!! hello world!!!

 

说明:主要遇到的问题是如何解析时间后面的字符串,因为这个字符串有空格,所以scanf不用直接用%s。上面的方法是%[ -~],把所有的打印的ASCII字符都读到缓冲区中。

至于为什么要这样做,后面有空再写篇文章出来。

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息