sscanf函数和正则表达式

此文所有的实验都是基于下面的程序:

char str[10];

for (int i = 0; i < 10; i++) str[i] = ‘!‘;

执行完后str的值为

str = "!!!!!!!!!!"

我们把str的每个字符都初始化为惊叹号,当str的值发生变化时,使用printf打印str的值,对比先前的惊叹号,这样就可以方便的观察str发生了怎样的变化。下面我们做几个小实验,看看使用sscanf和正则表达式格式化输入后,str有什么变化。

实验1:

sscanf("123456","%s",str); ---------str的值为 "123456\0!!!"

这个实验很简单,把源字符串"123456"拷贝到str的前6个字符,并且把str的第7个字符设为null字符,也就是\0

实验2:

sscanf("123456","%3s",str); ---------str的值为 "123\0!!!!!!"

看到没有,正则表达式的百分号后面多了一个3,这告诉sscanf只拷贝3个字符给str,然后把第4个字符设为null字符。

实验3:

sscanf("aaaAAA","%[a-z]",str); ---------str的值为 "aaa\0!!!!!!"

从这个实验开始我们会使用正则表达式,括号里面的a-z就是一个正则表达式,它可以表示从a到z的任意字符,

在继续讨论之前,我们先来看看百分号表示什么意思,%表示选择,%后面的是条件,比如实验1的"%s",s是一个条件,表示任意字符,"%s"的意思是:只要输入的东西是一个字符,就把它拷贝给str。

实验2的"%3s"又多了一个条件:只拷贝3个字符。实验3的“%[a-z]”的条件稍微严格一些,输入的东西不但是字符,还得是一个小写字母的字符,

所以实验3只拷贝了小写字母"aaa"给str,别忘了加上null字符。

实验4:

sscanf("AAAaaaBBB","%[^a-z]",str); ---------str的值为 "AAA\0!!!!!!"

对于所有字符,只要不是小写字母,都满足"^a-z"正则表达式,符号^表示逻辑非。前3个字符都不是小写字符,所以将其拷贝给str,但最后3个字符也不是小写字母,

为什么不拷贝给str呢?这是因为当碰到不满足条件的字符后,sscanf就会停止执行,不再扫描之后的字符。

实验5:

sscanf("AAAaaaBBB","%[A-Z]%[a-z]",str); ---------段错误

这个实验的本意是:先把大写字母拷贝给str,然后把小写字母拷贝给str,但很不幸,程序运行的时候会发生段错误,因为当sscanf扫描到字符a时,违反了条件"%[A-Z]",

sscanf就停止执行,不再扫描之后的字符,所以第二个条件也就没有任何意义,这个实验说明:不能使用%号两次或两次以上

实验6:

sscanf("AAAaaaBBB","%*[A-Z]%[a-z]",str); ---------str的值为 "aaa\0!!!!!!"

这个实验出现了一个新的符号:%*,与%相反,%*表示过滤满足条件的字符,在这个实验中,%*[A-Z]过滤了所有大写字母,然后再使用%[a-z]把之后的小写字母拷贝给str。

如果只有%*,没有%的话,sscanf不会拷贝任何字符到str,这时sscanf的作用仅仅是过滤字符串。

实验7:

sscanf("AAAaaaBBB","%[a-z]",str); ---------str的值为 "!!!!!!!!!!"

做完前面几个实验后,我们都知道sscanf拷贝完成后,还会在str的后面加上一个null字符,但如果没有一个字符满足条件,sscanf不会在str 的后面加null字符,

str的值依然是10个惊叹号。这个实验也说明了,如果不使用%*过滤掉前面不需要的字符,你永远别想取得中间的字符。

实验8:

sscanf("AAAaaaBC=","%*[A-Z]%*[a-z]%[^a-z=]",str); ---------str的值为 "BC\0!!!!!!!"

这是一个综合实验,但这个实验的目的不是帮我们复习前面所学的知识,而是展示两个值得注意的地方:

注意1:%只能使用一次,但%*可以使用多次,比如在这个实验里面,先用%*[A-Z]过滤大写字母,然后用%*[a-z]过滤小写字母。

注意2:^后面可以带多个条件,且这些条件都受^的作用,比如^a-z=表示^a-z且^=(既不是小写字母,也不是等于号)。

实验9:

int k;

sscanf("AAA123BBB456", "%*[^0-9]%i", &k); ---------k的值为123

首先,%*[^0-9]过滤前面非数字的字符,然后用%i把数字字符转换成int型的整数,拷贝到变量k,注意参数必须使用k的地址。

#if 0
1,sscanf():从一个字符串中读进与指定格式相符的数据.
2,sscanf与scanf类似,都是用于输入的,只是后者以屏幕(stdin)为输入源,前者以固定字符串为输入源。
3,关于正则表达式:
    (1)%[..],当字符属于方括号里表达式表示的字符集时继续读取,否则停止.方括号里的和正则表达式差不多,^是"排除..."的意思
    (2)%*[..],直接跳过方括号里的字符集并继续读取
#endif

#include <iostream>
using namespace std;

int main()
{
    char str[10];
    for (int i = 0; i < 10; i++) str[i] = ‘!‘;
    cout<<str<<endl;
    sscanf("123456","%s",str);//---------str的值为 "123456\0!!!"
    //这个实验很简单,把源字符串"123456"拷贝到str的前6个字符,并且把str的第7个字符设为null字符,也就是\0
    cout<<str<<endl;

    for (int i = 0; i < 10; i++) str[i] = ‘!‘;
    sscanf("123456","%3s",str); //---------str的值为 "123\0!!!!!!"
    //看到没有,正则表达式的百分号后面多了一个3,这告诉sscanf只拷贝3个字符给str,然后把第4个字符设为null字符。
    cout<<str<<endl;

    for (int i = 0; i < 10; i++) str[i] = ‘!‘;
    sscanf("aaaAAA","%[a-z]",str);// ---------str的值为 "aaa\0!!!!!!"
    //从这个实验开始我们会使用正则表达式,括号里面的a-z就是一个正则表达式,它可以表示从a到z的任意字符,
    //在继续讨论之前,我们先来看看百分号表示什么意思,%表示选择,%后面的是条件,比如实验1的"%s",s是一个条件,表示任意字符,"%s"的意思是:只要输入的东西是一个字符,就把它拷贝给str。实验2的"%3s"又多了一个条件:只拷贝3个字符。实验3的“%[a-z]”的条件稍微严格一些,输入的东西不但是字符,还得是一个小写字母的字符,所以实验3只拷贝了小写字母"aaa"给str,别忘了加上null字符。
    cout<<str<<endl;

    for (int i = 0; i < 10; i++) str[i] = ‘!‘;
    sscanf("AAAaaaBBB","%[^a-z]",str);// ---------str的值为 "AAA\0!!!!!!"
    //对于所有字符,只要不是小写字母,都满足"^a-z"正则表达式,符号^表示逻辑非。前3个字符都不是小写字符,所以将其拷贝给str,但最后3个字符也不是小写字母,为什么不拷贝给str呢?这是因为当碰到不满足条件的字符后,sscanf就会停止执行,不再扫描之后的字符。
    cout<<str<<endl;

    /*
    for (int i = 0; i < 10; i++) str[i] = ‘!‘;
    sscanf("AAAaaaBBB","%[A-Z]%[a-z]",str);// ---------段错误
    //这个实验的本意是:先把大写字母拷贝给str,然后把小写字母拷贝给str,但很不幸,程序运行的时候会发生段错误,因为当sscanf扫描到字符a时,违反了条件"%[A-Z]",sscanf就停止执行,不再扫描之后的字符,所以第二个条件也就没有任何意义,这个实验说明:不能使用%号两次或两次以上
    cout<<str<<endl;
    */

    for (int i = 0; i < 10; i++) str[i] = ‘!‘;
    sscanf("AAAaaaBBB","%*[A-Z]%[a-z]",str); //---------str的值为 "aaa\0!!!!!!"
    //这个实验出现了一个新的符号:%*,与%相反,%*表示过滤满足条件的字符,在这个实验中,%*[A-Z]过滤了所有大写字母,然后再使用%[a-z]把之后的小写字母拷贝给str。如果只有%*,没有%的话,sscanf不会拷贝任何字符到str,这时sscanf的作用仅仅是过滤字符串。
    cout<<str<<endl;

    for (int i = 0; i < 10; i++) str[i] = ‘!‘;
    sscanf("AAAaaaBBB","%[a-z]",str);// ---------str的值为 "!!!!!!!!!!"
    //做完前面几个实验后,我们都知道sscanf拷贝完成后,还会在str的后面加上一个null字符,但如果没有一个字符满足条件,sscanf不会在str 的后面加null字符,str的值依然是10个惊叹号。这个实验也说明了,如果不使用%*过滤掉前面不需要的字符,你永远别想取得中间的字符。
    cout<<str<<endl;

    for (int i = 0; i < 10; i++) str[i] = ‘!‘;
    sscanf("AAAaaaBC=","%*[A-Z]%*[a-z]%[^a-z=]",str); //---------str的值为 "BC\0!!!!!!!"
    //这是一个综合实验,但这个实验的目的不是帮我们复习前面所学的知识,而是展示两个值得注意的地方:
    //注意1:%只能使用一次,但%*可以使用多次,比如在这个实验里面,先用%*[A-Z]过滤大写字母,然后用%*[a-z]过滤小写字母。
    // 注意2:^后面可以带多个条件,且这些条件都受^的作用,比如^a-z=表示^a-z且^=(既不是小写字母,也不是等于号)。
    cout<<str<<endl;

    for (int i = 0; i < 10; i++) str[i] = ‘!‘;
    int k;
    sscanf("AAA123BBB456", "%*[A-Z]%i", &k); //---------k的值为123
    //首先,%*[^0-9]过滤前面非数字的字符,然后用%i把数字字符转换成int型的整数,拷贝到变量k,注意参数必须使用k的地址。    cout<<str<<endl;
    cout<<k<<endl;
    return 0;
}
/*****************************************************
** Name         : sscanf.c
** Author       : gzshun
** Version      : 1.0
** Date         : 2011-12
** Description  : sscanf function
******************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static void sscanf_test(void);

static void sscanf_test(void)
{
    int ret;
    char *string;
    int  digit;
    char buf1[255];
    char buf2[255];
    char buf3[255];
    char buf4[255];

    /*1.最简单的用法*/
    string = "china beijing 123";
    ret = sscanf(string, "%s %s %d", buf1, buf2, &digit);
    printf("1.string=%s\n", string);
    printf("1.ret=%d, buf1=%s, buf2=%s, digit=%d\n\n", ret, buf1, buf2, digit);
    /*
    **执行结果:
    **1.ret=3, buf1=china, buf2=beijing, digit=123
    **可以看出,sscanf的返回值是读取的参数个数
    */

    /*2.取指定长度的字符串*/
    string = "123456789";
    sscanf(string, "%5s", buf1);
    printf("2.string=%s\n", string);
    printf("2.buf1=%s\n\n", buf1);
    /*
    **执行结果:
    **2.buf1=12345
    */

    /*3.取到指定字符为止的字符串*/
    string = "123/456";
    sscanf(string, "%[^/]", buf1);
    printf("3.string=%s\n", string);
    printf("3.buf1=%s\n\n", buf1);
    /*
    **执行结果:
    **3.buf1=123
    */

    /*4.取到指定字符集为止的字符串*/
    string = "123abcABC";
    sscanf(string, "%[^A-Z]", buf1);
    printf("4.string=%s\n", string);
    printf("4.buf1=%s\n\n", buf1);
    /*
    **执行结果:
    **4.buf1=123abc
    */

    /*5.取仅包含指定字符集的字符串*/
    string = "0123abcABC";
    sscanf(string, "%[0-9]%[a-z]%[A-Z]", buf1, buf2, buf3);
    printf("5.string=%s\n", string);
    printf("5.buf1=%s, buf2=%s, buf3=%s\n\n", buf1, buf2, buf3);
    /*
    **执行结果:
    **5.buf1=123, buf2=abc, buf3=ABC
    */

    /*6.获取指定字符中间的字符串*/
    string = "ios<android>wp7";
    sscanf(string, "%*[^<]<%[^>]", buf1);
    printf("6.string=%s\n", string);
    printf("6.buf1=%s\n\n", buf1);
    /*
    **执行结果:
    **6.buf1=android
    */

    /*7.指定要跳过的字符串*/
    string = "iosVSandroid";
    sscanf(string, "%[a-z]VS%[a-z]", buf1, buf2);
    printf("7.string=%s\n", string);
    printf("7.buf1=%s, buf2=%s\n\n", buf1, buf2);
    /*
    **执行结果:
    **7.buf1=ios, buf2=android
    */

    /*8.分割以某字符隔开的字符串*/
    string = "android-iphone-wp7";
    /*
    **字符串取道‘-‘为止,后面还需要跟着分隔符‘-‘,
    **起到过滤作用,有点类似于第7点
    */
    sscanf(string, "%[^-]-%[^-]-%[^-]", buf1, buf2, buf3);
    printf("8.string=%s\n", string);
    printf("8.buf1=%s, buf2=%s, buf3=%s\n\n", buf1, buf2, buf3);
    /*
    **执行结果:
    **8.buf1=android, buf2=iphone, buf3=wp7
    */

    /*9.提取邮箱地址*/
    string = "Email:[email protected]";
    sscanf(string, "%[^:]:%[^@]@%[^.].%s", buf1, buf2, buf3, buf4);
    printf("9.string=%s\n", string);
    printf("9.buf1=%s, buf2=%s, buf3=%s, buf4=%s\n\n", buf1, buf2, buf3, buf4);
    /*
    **执行结果:
    **9.buf1=Email, buf2=beijing, buf3=sina, buf4=com.cn
    */

    /*10.过滤掉不想截取或不需要的字符串--补充,
    **在%号后面加一*号,代表过滤这个字符串,不读取
    */
    string = "android iphone wp7";
    sscanf(string, "%s %*s %s", buf1, buf2);
    printf("10.string=%s\n", string);
    printf("10.buf1=%s, buf2=%s\n\n", buf1, buf2);
    /*
    **执行结果:
    **10.android wp7
    */
}

int main(int argc, char **argv)
{
    sscanf_test();

    return 0;
}

/*
**测试程序
**环境:
**Linux ubuntu 2.6.32-24-generic-pae #39-Ubuntu SMP Wed Jul 28 07:39:26 UTC 2010 i686 GNU/Linux
**gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5)
**
[email protected]:~/c/sscanf$ gcc sscanf.c -o sscanf
[email protected]:~/c/sscanf$ ./sscanf
1.string=china beijing 123
1.ret=3, buf1=china, buf2=beijing, digit=123

2.string=123456789
2.buf1=12345

3.string=123/456
3.buf1=123

4.string=123abcABC
4.buf1=123abc

5.string=0123abcABC
5.buf1=0123, buf2=abc, buf3=ABC

6.string=ios<android>wp7
6.buf1=android

7.string=iosVSandroid
7.buf1=ios, buf2=android

8.string=android-iphone-wp7
8.buf1=android, buf2=iphone, buf3=wp7

9.string=Email:[email protected]
9.buf1=Email, buf2=beijing, buf3=sina, buf4=com.cn

10.string=android iphone wp7
10.buf1=android, buf2=wp7
*/

代码来源:

http://kmplayer.iteye.com/blog/556293

http://blog.csdn.net/gzshun/article/details/7081736

sscanf函数和正则表达式

时间: 2024-10-12 23:36:15

sscanf函数和正则表达式的相关文章

c语言 sscanf()函数

sscanf()函数用于从字符串中读取指定格式的数据,其原型如下:    int sscanf (char *str, char * format [, argument, ...]); [参数]参数str为要读取数据的字符串:format为用户指定的格式:argument为变量,用来保存读取到的数据. [返回值]成功则返回参数数目,失败则返回-1,错误原因存于errno 中. sscanf()会将参数str 的字符串根据参数format(格式化字符串)来转换并格式化数据(格式化字符串请参考sc

sscanf()函数。

#include <stdio.h> int main() { char str[10002]; char a[1002],b[1002]; while(gets(str)) { sscanf(str,"%s %s",a,b); printf("%s\n",a); printf("%s\n",b); } } #include <stdio.h> int main() { char str[10002]; char a[10

linux c sscanf函数

sscanf函数 是从一个字符串中读取与指定格式相符的数据 函数原型 int sscanf(const char *str, const char *format, ...); 参数说明 str:要读取的原字符串. format:可以是一个或多个 {%[*] [width] [{h | l | I64 | L}]type | ' ' | '\t' | '\n' | 非%符号} 注: 1.* 亦可用于格式中, (即 %d 和 %*s) 加了星号 () 表示跳过此数据不读入. (也就是不把此数据读入

sscanf 函数

sscanf 函数: 从一个字符串中读进与指定格式相符的数据. 头文件: #include<stdio.h> 返回值:  sscanf("1 2 3","%d %d %d",buf1, buf2, buf3); 成功调用返回值为3,即buf1,buf2,buf3均成功转换. sscanf("1 2","%d %d %d",buf1, buf2, buf3); 成功调用返回值为2,即只有buf1,buf2成功转换 s

Sscanf函数 及其用法

sscanf()  :从一个字符串中读进与指定格式相符的数据.  函数原型:  Int sscanf( string str, string fmt, mixed var1, mixed var2 ... );  int scanf( const char *format [,argument]... );       sscanf与scanf类似,都是用于输入的,只是后者以屏幕(stdin)为输入源,前者以固定字符串为输入源. 简单地说就是输入的类型不同.          首先要先搞清楚,s

sscanf函数引起android 5.0卡死,C++中慎用C库函数

为了准备即将到来的面试们,把以前的RPG项目拿出来安装到手机上跑了跑,发现游戏会卡死,简直郁闷... 当初我写完这个项目的时候,android 5.0还没有发布,我在android 2.3到android 4.4的设备上都测试通过了(作为穷逼的我,自己的手机就是2.3..),现在终于换手机了,刷了CM12(android 5.0.2),果然出现bug了,游戏会莫名卡死... 测试了一个小时,终于把错误范围锁定在一个读取文件的函数中,然后一点一点的注释函数中的某些行,最终发现是sscanf函数引发

认识sscanf函数

sscanf函数 /* GitHub stylesheet for MarkdownPad (http://markdownpad.com) / / Author: Nicolas Hery - http://nicolashery.com / / Version: b13fe65ca28d2e568c6ed5d7f06581183df8f2ff / / Source: https://github.com/nicolahery/markdownpad-github */ /* RESET ==

C语言sscanf()函数详解的代码

下面资料是关于C语言sscanf()函数详解的内容,希望能对各位朋友有好处. 说明:sscanf()会将参数str的字符串根据参数format来转换并格式化数据. format格式 #include <stdio.h> #include <stdlib.h> #include <string.h> int main() { int result; char str[100]; char buf1[255], buf2[255], buf3[255], buf4[255]

C语言sprintf和sscanf函数用法

以前刚用C语言的时候,觉得字符串很难处理,后来用多了,发现其实并非如此,C语言也提供了许多函数给程序员使用.今天记录一下两个常用的两个字符串处理函数:sprintf和sscanf 1. sprintf 从名称上来看,这个函数名称由三部分组成: s 代表字符串(string) print 代表打印 f 代表格式化(format) 这样拆分,可以大概知道它是干嘛用的了,相对于我们常用的用来处理输出流的printf,sprintf是用来处理字符串的.实际上这个函数,是把数据按格式打印到字符串中,常用于