LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
楼主: haohao_h

请教一个字符串解析问题

[复制链接]
发表于 2005-5-9 12:01:46 | 显示全部楼层
Post by kj501
scanf是以空格,制表符,换行符作为分隔符的。格式字符串中的一个空格可能相当于多个输入的空格、制表符或换行符。


版主此言差矣
scanf族函数无分隔符之说!只是大家用多了%s匹配,才主观地认为有空白字符的分隔符。

以我之见,从下面共四种方式来认识scanf的格式匹配应该是比较正确的:
1, %s,%d,%f
最常用的一个匹配规范,也是基本匹配规范,它们是一个受限制的匹配规范,此限制是空白字符,即它匹配从开头或上一个匹配规范结束后的第一个非空白字符起到后面的第一个空白字符止。这里的非空白字符串定义就是空格,制表符,换行符了。

2, %*s ,%*d,%*f
忽略输入字串中的多余信息,也是受空白字符的限制。

3, %c
不受限的匹配规范,它可匹配上面提到的空白字符或其他非空白字符

4, %[XXX]
也是不受限的匹配规范,只要是[]里出现的字符都匹配,如果出现了空白字符,那也匹配

  1. #include <stdio.h>

  2. int
  3. main(void)
  4. {
  5.   char b[50];
  6.   int d,a;
  7.   sscanf("   123 432 abc  d888", "%d%*d%[ abcd]%d", &d, b, &a);
  8.   /* 这里的格式化字串%d等之间没有用所谓的分隔符,但用上是会有助于程序的可读性 */
  9.   printf("b is :%s\nd is %d\na is:%d\n", b, d, a);
  10.   return 0;
  11. }
复制代码
回复 支持 反对

使用道具 举报

发表于 2005-5-9 12:28:38 | 显示全部楼层
man scanf你就能理解scanf有多复杂了。
回复 支持 反对

使用道具 举报

发表于 2005-5-9 12:34:22 | 显示全部楼层
Post by 小锁
man scanf你就能理解scanf有多复杂了。

我自然知道scanf很复杂,我上面列举的当然是不全面的,但我在使用这个函数时绝大多数时候,上面的知识点已经够了

PS:我只是不同意分隔符这种说法
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-5-9 13:38:40 | 显示全部楼层
感谢解释!下面这个例子也许能加深理解吧!
#include <stdio.h>

main()
{
        char Host[64];
        char User[64];
  char *Buff = "Jobname=job1 Hostname=arnamul User=leslim Time=11:15";
  /*            <---------->          <-----> <---------> <-------->
   *              |                      |         |           |
   *              |           ------------         |           |
   *              |           |   ------------------           V
   *              |           |   |                              NULL
   *              V           V   V                                    */
  sscanf (Buff, "%*s Hostname=%s %s", Host, User);
/*我发现好像只有“=”是可以的,其他符号都不行,版主还要有补充条款吧!在哪儿可以得到这些函数的用法的完整资料呢?*/

  printf("Host is %s\n", Host);
  printf("User is %s\n", User);
}

/************************************************************************
*
*        Job Output is:
*
*  Host is arnamul
*  User is User=leslim
*
************************************************************************/
回复 支持 反对

使用道具 举报

发表于 2005-5-9 14:44:17 | 显示全部楼层
嗯,补充一点:
格式化字串时,如果在%s的旁边有固定的字符串,就一定要加空格了,像上面例子:
sscanf (Buff, "%*s Hostname=%s %s", Host, User);
如果改成sscanf (Buff, "%*sHostname=%s %s", Host, User);  =====>%*sH之间没有空格是错误的
这也算是所谓的分隔符吧:(

兄弟还是去GOOGLE一下全面的资料或MAN一下,比较全面
回复 支持 反对

使用道具 举报

发表于 2005-5-9 15:59:52 | 显示全部楼层
分隔符只是一种习惯说法,实际上按照规则表达式的匹配概念来理解scanf中格式字符串的作用可能更恰当一些。
回复 支持 反对

使用道具 举报

发表于 2005-5-9 16:14:07 | 显示全部楼层
Post by haohao_h
感谢解释!下面这个例子也许能加深理解吧!
#include <stdio.h>

main()
{
        char Host[64];
        char User[64];
  char *Buff = "Jobname=job1 Hostname=arnamul User=leslim Time=11:15";
  /*            <---------->          <-----> <---------> <-------->
   *              |                      |         |           |
   *              |           ------------         |           |
   *              |           |   ------------------           V
   *              |           |   |                              NULL
   *              V           V   V                                    */
  sscanf (Buff, "%*s Hostname=%s %s", Host, User);
/*我发现好像只有“=”是可以的,其他符号都不行,版主还要有补充条款吧!在哪儿可以得到这些函数的用法的完整资料呢?*/

  printf("Host is %s\n", Host);
  printf("User is %s\n", User);
}

/************************************************************************
*
*        Job Output is:
*
*  Host is arnamul
*  User is User=leslim
*
************************************************************************/



不是啊, "Hostname="替换成任何字符串都可以的
但不可以这样:

  1. sscanf("eth0:123", "%s:%d", s, &n);
复制代码
回复 支持 反对

使用道具 举报

发表于 2005-5-10 12:24:18 | 显示全部楼层
用perl的正则表达式很容易实现.
回复 支持 反对

使用道具 举报

发表于 2005-5-10 13:34:33 | 显示全部楼层
Post by danath
用perl的正则表达式很容易实现.


当然,lex也可以。不过有必要吗??
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-5-10 14:54:44 | 显示全部楼层
c语言中没有正则表达式吧!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表