使用正确的sscanf [英] Properly using sscanf

查看:246
本文介绍了使用正确的sscanf的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我应该得到的输入线,可以​​是在任意的以下格式:


  • 必须有字1和字2之间的空间。

  • 必须有字2和字3之间的逗号。

  • 空格不是字2字3间一绝 - 但任意数量的空格可以

我怎么能分开1,2和3个字的情况下,把数据放到正确的变量?

 字1
字词1 WORD2
字词1 WORD2,WORD3
字词1 WORD2,WORD3

我想过是这样的:

 的sscanf(串,%s%S%S,字词1,word2和WORD3);

但它似乎并没有工作。

我使用严格C89。


解决方案

  INT N =的sscanf(串,%s%[^,]%* [,]%S 字词1,word2和WORD3);

的返回值n 告诉你很多任务是如何成功地进行。在%[^,] 是一个否定的字符类匹配的发现一个字不包括逗号或空格(添加标签,如果你喜欢)。在%* [,] 是一个比赛是找到一个逗号或空间,但燮presses分配。

我不知道我会在实践中使用,但它应该工作。然而,这是,未经考验的。


也许更严格的规范是:

  INT N =的sscanf(串,%s%[^,]%* [,]%S,字词1,word2和WORD3);

不同的是,在非分配字符类只接受一个逗号。在字词2 的sscanf()停止在任何空间(EOS,字符串结尾或),分配给前跳过空格 WORD3 。的previous版允许第二和第三字之间的空间,以代替一个逗号,该问题并不严格容许的

由于 PMG 表明在注释中,分配转换规范应给予长度,以prevent缓冲区溢出。注意,该长度不包括空终止,因此在格式字符串的值必须是小于以字节数组的大小。另外请注意,而的printf()允许您使用 * sscanf的动态指定大小( )等使用 * 共进晚餐preSS分配。这意味着你要专门创建的字符串手头的任务:

 字符字1 [20],WORD2 [32],WORD3 [64];
INT N =的sscanf(串,%19秒%31 [^]%* [,]%63S,字词1,word2和WORD3);

(Kernighan的&安培;派克认为他们(优秀)的书动态格式格式字符串编程的'实践。)



  

刚刚发现一个问题:给定字词1 word2和WORD3,它不读 WORD3 。是否有办法治吗?


是的,有治愈,它实际上是微不足道了。非分配,逗号配对转换说明前添加格式字符串的空间。因此:

 的#include<&stdio.h中GT;静态无效测试仪(为const char *数据)
{
    炭字词1 [20],WORD2 [32],WORD3 [64];
    INT N = sscanf的(数据,%19秒%31 [^]%* [,]%63S,字词1,word2和WORD3);
    的printf(测试数据:其中;&下;%S取代;> \\ N,数据);
    的printf(N =%d个; W1 =<<%S>>中W2 =<<%S>>中W3 =<<%S>> \\ N,N,字1 ,WORD2,WORD3);
}INT主要(无效)
{
    为const char *数据[] =
    {
        字词1 WORD2,WORD3
        字词1 WORD2,WORD3
        字词1 WORD2,WORD3
        字词1 WORD2,WORD3
        字词1 WORD2,WORD3
    };
    枚举{DATA_SIZE = sizeof的(数据)/的sizeof(数据[0])};
    为size_t我;
    对于(i = 0; I< D​​ATA_SIZE;我++)
        试验机(数据[I]);
    返回(0);
}

输出示例:

 测试数据:其中;<字词1 word2和WORD3>>
N = 3; W1 =<<&字1 GT;>中W2 =<<&字词2 GT;>中W3 =<<&WORD3 GT;>
测试数据:其中;<字词1 word2和WORD3>>
N = 3; W1 =<<&字1 GT;>中W2 =<<&字词2 GT;>中W3 =<<&WORD3 GT;>
测试数据:其中;<字词1 word2和WORD3>>
N = 3; W1 =<<&字1 GT;>中W2 =<<&字词2 GT;>中W3 =<<&WORD3 GT;>
测试数据:其中;<字词1 word2和WORD3>>
N = 3; W1 =<<&字1 GT;>中W2 =<<&字词2 GT;>中W3 =<<&WORD3 GT;>
测试数据:其中;<字词1 word2和WORD3>>
N = 3; W1 =<<&字1 GT;>中W2 =<<&字词2 GT;>中W3 =<<&WORD3 GT;>


一旦非指定字符类只接受一个逗号,可以缩写,要在格式字符串字面逗号:

  INT N = sscanf的(数据,%19秒%31 [^]%63S,字词1,word2和WORD3);

堵该进入测试工具如之前产生相同的结果。注意从审查,所有code利益;它往往可以(基本上总是)来即使它正在改善。

I am supposed to get an input line that can be in of any of the following formats:

  • There must be space between word 1 and word 2.
  • There must be a comma between word 2 and word 3.
  • Spaces are not a must between word 2 and word 3 — but any number of spaces is possible.

How can I separate 1, 2 and 3 word cases and put the data into the correct variables?

word1
word1 word2 
word1 word2 , word3
word1 word2,word3

I thought about something like:

sscanf("string", "%s %s,%s", word1, word2, word3);

but it doesn't seem to work.

I use strict C89.

解决方案

int n = sscanf("string", "%s %[^, ]%*[, ]%s", word1, word2, word3);

The return value in n tells you how many assignments were made successfully. The %[^, ] is a negated character-class match that finds a word not including either commas or blanks (add tabs if you like). The %*[, ] is a match that finds a comma or space but suppresses the assignment.

I'm not sure I'd use this in practice, but it should work. It is, however, untested.


Maybe a tighter specification is:

int n = sscanf("string", "%s %[^, ]%*[,]%s", word1, word2, word3);

The difference is that the non-assigning character class only accepts a comma. sscanf() stops at any space (or EOS, end of string) after word2, and skips spaces before assigning to word3. The previous edition allowed a space between the second and third words in lieu of a comma, which the question does not strictly allow.

As pmg suggests in a comment, the assigning conversion specifications should be given a length to prevent buffer overflow. Note that the length does not include the null terminator, so the value in the format string must be one less than the size of the arrays in bytes. Also note that whereas printf() allows you to specify sizes dynamically with *, sscanf() et al use * to suppress assignment. That means you have to create the string specifically for the task at hand:

char word1[20], word2[32], word3[64];
int n = sscanf("string", "%19s %31[^, ]%*[,]%63s", word1, word2, word3);

(Kernighan & Pike suggest formatting the format string dynamically in their (excellent) book 'The Practice of Programming'.)


Just found a problem: given "word1 word2 ,word3", it doesn't read word3. Is there a cure?

Yes, there's a cure, and it is actually trivial, too. Add a space in the format string before the non-assigning, comma-matching conversion specification. Thus:

#include <stdio.h>

static void tester(const char *data)
{
    char word1[20], word2[32], word3[64];
    int n = sscanf(data, "%19s %31[^, ] %*[,]%63s", word1, word2, word3);
    printf("Test data: <<%s>>\n", data);
    printf("n = %d; w1 = <<%s>>, w2 = <<%s>>, w3 = <<%s>>\n", n, word1, word2, word3);
}

int main(void)
{
    const char *data[] =
    {
        "word1 word2 , word3",
        "word1 word2 ,word3",
        "word1 word2, word3",
        "word1 word2,word3",
        "word1 word2       ,       word3",
    };
    enum { DATA_SIZE = sizeof(data)/sizeof(data[0]) };
    size_t i;
    for (i = 0; i < DATA_SIZE; i++)
        tester(data[i]);
    return(0);
}

Example output:

Test data: <<word1 word2 , word3>>
n = 3; w1 = <<word1>>, w2 = <<word2>>, w3 = <<word3>>
Test data: <<word1 word2 ,word3>>
n = 3; w1 = <<word1>>, w2 = <<word2>>, w3 = <<word3>>
Test data: <<word1 word2, word3>>
n = 3; w1 = <<word1>>, w2 = <<word2>>, w3 = <<word3>>
Test data: <<word1 word2,word3>>
n = 3; w1 = <<word1>>, w2 = <<word2>>, w3 = <<word3>>
Test data: <<word1 word2       ,       word3>>
n = 3; w1 = <<word1>>, w2 = <<word2>>, w3 = <<word3>>


Once the 'non-assigning character class' only accepts a comma, you can abbreviate that to a literal comma in the format string:

int n = sscanf(data, "%19s %31[^, ] , %63s", word1, word2, word3);

Plugging that into the test harness produces the same result as before. Note that all code benefits from review; it can often (essentially always) be improved even after it is working.

这篇关于使用正确的sscanf的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆