admin 管理员组

文章数量: 887031


2023年12月18日发(作者:fopen在那个头文件)

scanf格式控制字符串%

[Reading Undelimited strings]

*To read strings not delimited by whitespace characters, a set of

characters in brackets ([ ]) can be substituted for the s (string) type

character. The set of characters in brackets is referred to as a control

string. The corresponding input field is read up to the first character that

does not appear in the control string. If the first character in the set is a

caret (^), the effect is reversed: The input field is read up to the first

character that does appear in the rest of the character set.

*Note that %[a-z] and %[z-a] are interpreted as equivalent

to %[]. This is a common scanf function extension, but note that

the ANSI standard does not require it.

举一些例子:

对于 const char* p = "ABC12356";

sscanf(p,"%[123]",buf); // 就把是'1'或'2'或'3'的字读读到buf中,直到遇到一个不是'1'且不是'2'且不是'3'的字符,于是执行后buf应该是"1223211";

%[123]等同于%[231],等同于%[321]„„,列表中的顺序是无所谓的;

%[123]也等同于%[1-3]或%[3-1],也就是“1至3”,对于连续的字

符列表这样写就很简单,比如%[a-z]等同%[abc„省略„z];

想想看,%[3-14]应该等同于什么?是“3至14”吗?当然不是,因为[]中的是字符,而不是数字,所以%[3-14]应该等同于%[3214],等同于%[1234];

同理,想只取字母,那就可以写成%[A-Za-z];

如果列表的第一个字母是^,那么正好相反,比如%[^A-Za-z]的意思就是取字母之外的所有字符。

对于字符串"abDEc123"如果想按照字母和数字读到两个字符串中就应该是 "%[a-zA-Z]%[0-9]",buf1,buf2 ;

假如我想取一行字符,该怎么办?"%s"是不行的,因为%s遇到空白字符(空格、制表符、r、n)就结束了,所以可以写成

"%[^n]%*c",%[^n]的作用刚才讲过了,就是读n之外的所有字符,也就是说读到n为止,%*c的作用就是把n去掉,否则再次读的时候一直遇到的都是n;

所有对%s起作用的控制,都可以用于%[],比如"%*[^n]%*c"就表示跳过一行,"%-20[^n]"就表示读取n前20个字符。

scanf/sscanf 格式的特殊控制

代码

scanf中一种很少见但很有用的转换字符:[...]和[ ^...]。

#include

int main()

{

char strings[100];

scanf("%[1234567890]",strings);

printf("%s",strings);

return 0;

}

运行,输入:1234werew后,结果是:1234。

通过运行可以发现它的作用是:如果输入的字符属于方括号内字符串中某个字符,那么就提取该字符;如果一经发现不属于就结束提取。该方法会自动加上一个字符串结束符到已经提取的字符后面。

scanf("%[^1234567890]",strings); 它的作用是:如果一经发现输入的字符属于方括号内字符串中某个字符,那么就结束提取;如果不属于就提取该字符。该方法会自动加上一个字符串结束符到已经提取的字符后面。

注意:方括号两边不能空格,如:scanf("%[ 1234567890 ]",strings); scanf("%[ ^1234567890 ]",strings); 不让空格也会算在里面的。

用这种方法还可以解决scanf的输入中不能有空格的问题。只要用

scanf("%[^n]",strings); 就可以了。很神奇吧。

ANSI C 标准向 scanf() 增加了一种新特性,称为扫描集(scanse

t)。 扫描集定义一个字符集合,可由 scanf() 读入其中允许的字符并赋给对应字符数组。 扫描集合由一对方括号中的一串字符定义,左方括号前必须缀以百分号。 例如,以下的扫描集使 scanf() 读入字符 A、B 和 C:

%[ABC]

使用扫描集时,scanf() 连续吃进集合中的字符并放入对应的字符数组,直到发现不在集合中的字符为止(即扫描集仅读匹配的字符)。返回时,数组中放置以 null 结尾、由读入字符组成的字符串。

用字符 ^ 可以说明补集。把 ^ 字符放为扫描集的第一字符时,构成其它字符组成的命令的补集合,指示 scanf() 只接受未说明的其它字符。

对于许多实现来说,用连字符可以说明一个范围。 例如,以下扫描集使 scanf() 接受字母 A 到 Z:

%[A-Z]

重要的是要注意扫描集是区分大小写的。因此,希望扫描大、小写字符时,应该分别说明大、小写字母。

搜集一些特殊用法:

%[ ] 的用法:%[ ]表示要读入一个字符集合, 如果[ 后面第一个字符

是”^”,则表示反意思。

[ ]内的字符串可以是1或更多字符组成。空字符集(%[])是违反规定的,可

导致不可预知的结果。%[^]也是违反规定的。

%[a-z] 读取在 a-z 之间的字符串,如果不在此之前则停止,如

char s[]="hello, my friend” ; // 注意: ,逗号在不 a-z之间

sscanf( s, “%[a-z]”, string ) ; // string=hello

%[^a-z] 读取不在 a-z 之间的字符串,如果碰到a-z之间的字符则停止,如

char s[]="HELLOkitty” ; // 注意: ,逗号在不 a-z之间

sscanf( s, “%[^a-z]”, string ) ; // string=HELLO

%*[^=] 前面带 * 号表示不保存变量。跳过符合条件的字符串。

char s[]="notepad=1.0.0.1001" ;

char szfilename [32] = "" ;

int i = sscanf( s, "%*[^=]", szfilename ) ;

// szfilename=NULL,因为没保存

int i = sscanf( s, "%*[^=]=%s", szfilename ) ;

// szfilename=1.0.0.1001

%40c 读取40个字符

%[^=] 读取字符串直到碰到’=’号,’^’后面可以带更多字符,如:

char s[]="notepad=1.0.0.1001" ;

char szfilename [32] = "" ;

int i = sscanf( s, "%[^=]", szfilename ) ;

// szfilename=notepad

如果参数格式是:%[^=:] ,那么也可以从 notepad:1.0.0.1001读取notepad

scanf()函数用法小结

虽然有人说在大型程序设计中永远不要使用scanf(),

但是对于习惯用C的人和参加ACM/ICPC的人,

scanf()还是用的比较多的,而且用好了用起来也很方便

下面整理一点儿平时常需要用到而可能有些人一直理不清的一些知识

一般常识:

scanf()函数的一般格式为:scanf("格式字符串",输入项首地址表)

scanf的格式控制的一般形式为:%

 [宽度][F|N][h|l]类型字符

* []中的控制字符为可选项

* "*"表示该输入项读入后不赋予任何变量,即跳过该输入值。这在减小内存开支上面还是有一点用处的,不需要的字符直接跳过,免得申请没用的变量空间

* "宽度"表示输入读入字符的长度,对于整型表示截取相应宽度的数字赋给后面列表中的相应变量;对于字符型表示读入相应长度的字符后把第一个字符赋给相应的变量,其余的自动舍弃。例如scanf("%2d%3d",&a, &b);如果输入为12345则将12赋给a,将45赋给b;scanf("%2c%3c",&a, &b);如果输入为12345则将'1'赋给a,将'3'赋给b

* F 、N、h、l分别表示远指针、近指针、短整和长整型,对于_int64相应的控制字符为ll或I64

* "类型字符"为 d -- 输入十进制整数 、o -- 输入八进制整数 、x -- 输入十六进制整数 、u -- 输入无符号十进制整数 f或e -- 输入实型数(用小数形式或指数形式) 、c -- 输入单个字符 、s -- 输入字符串

字符串读入的一些技巧

对于输入字符串还有一些比较有用的控制,

例如经常需要读入一行字符串,而这串字符里面可能有空格、制表符等空白字符,

如果直接用%s是不可以的,于是有些人就想到用gets(),当然这也是一种选择,

但是懂C的人基本上都知道gets()是一个很危险的函数,而且很难控制,

特别是与scanf()交替使用时前者的劣势更是一览无余,所以gets()一般是不推荐用的,

其实用%[^n]就可以很好的解决这个问题了,

^表示"非",即读入其后面的字符就结束读入。

这样想读入一行字符串直接用scanf("%[^n]%*c",str);就可以了,

%*c的作用是读入n,否则后面读入的将一直是n。

所有对%s起作用的控制都可以用%[],

比如%[0-9]表示只读入'0'到'9'之间的字符,%[a-zA-Z]表示只读入字母,

'-'是范围连接符,

当然也可以直接列出你需要读入的字符,上面读字母之所以用范围连接符是因为要输入52个字符太麻烦了,

如果你只需要读"abc"里面的字符就可以用%[abc] (或者%[cab]、%[acb]、%[a-c]、%[c-a].....),

如果想读入某个范围之外的字符串就在前面加一个'^',如:%[^a-z]就

表示读入小写字母之外的字符

上面这些用法其实可以有很多推广用法的,比如说你要处理下面的字符串

23 44r f30

88888,3245;34:123.

让你输出里面所有的数字,就可以用下面的代码:

#include

bool skip(){

scanf("%*[^0-9]");

return true;

}

int main(){

int n;

while (skip() && scanf("%d", &n)!=EOF)

printf("%dn", n);

return 0;

}

1. 说明

当使用printf或scanf函数时,需要在源代码文件头部包含

,即需要增加以下预处理命令。

#inlcude

(1) printf函数的调用形式为:

printf(格式描述字符串, 其他参数1, 其他参数2, …, 其他参数n);

其他参数是可选的。其中格式描述字符串中可包含特殊以%开始的转换描述符(转化字符),转换描述符的作用是把其他参数中的数据填充到格式描述字符串中进行输出。所以,转换描述符的个数必须与其他参数的格式一致,且其相互对应的关系也有一些规定(详见裘宗燕书29页表格,更深入的查看第8章276页)。

(2) scanf函数的调用形式为:

scanf (格式描述字符串, &变量名1, &变量名2,…, &变量名k);

scanf从键盘(或标准输入)读取信息,按给定的格式描述把读入信息转换为指定数据类型的数据。把得到的结果赋给指定变量。scanf是与printf对应的输入函数。其格式描述字符串与printf的类似,其中可以包含一个或者多个转换描述(同样以%开始)。变量的个数必须

与格式串中的转换描述个数一致,书写形式是在变量名前加&符号,对于一般类型(整型、实型和字符型)的变量,这个符号是必须的(详见第4章102页和第8章272页)。

2. printf的格式控制的完整格式

% - 0 m.n l或h 格式字符

下面对组成格式说明的各项加以说明:

①%:表示格式说明的起始符号,不可缺少。

②-:有-表示左对齐输出,如省略表示右对齐输出。

③0:有0表示指定空位填0,如省略表示指定空位不填。

④m.n:m指域宽,即对应的输出项在输出设备上所占的字符数。N指精度。用于说明输出的实型数的小数位数。为指定n时,隐含的精度为n=6位。

⑤l或h:l对整型指long型,对实型指double型。h用于将整型的格式字符修正为short型。

---------------------------------------

格式字符

格式字符用以指定输出项的数据类型和输出格式。

①d格式:用来输出十进制整数。有以下几种用法:

%d:按整型数据的实际长度输出。

%md:m为指定的输出字段的宽度。如果数据的位数小于m,则左端补以空格,若大于m,则按实际位数输出。

%ld:输出长整型数据。

②o格式:以无符号八进制形式输出整数。对长整型可以用"%lo"格式输出。同样也可以指定字段宽度用“%mo”格式输出。

例(该例子大家可不看!):

main()

{ int a = -1;

printf("%d, %o", a, a);

}

运行结果:-1,177777

程序解析:-1在内存单元中(以补码形式存放)为(11111)2,转换为八进制数为(177777)8。

③x格式:以无符号十六进制形式输出整数。对长整型可以用"%lx"格式输出。同样也可以指定字段宽度用"%mx"格式输出。

④u格式:以无符号十进制形式输出整数。对长整型可以用"%lu"格式输出。同样也可以指定字段宽度用“%mu”格式输出。

⑤c格式:输出一个字符。

⑥s格式:用来输出一个串。有几种用法

%s:例如:printf("%s", "CHINA")输出"CHINA"字符串(不包括

双引号)。

%ms:输出的字符串占m列,如字符串本身长度大于m,则突破获m的限制,将字符串全部输出。若串长小于m,则左补空格。

%-ms:如果串长小于m,则在m列范围内,字符串向左靠,右补空格。

%:输出占m列,但只取字符串中左端n个字符。这n个字符输出在m列的右侧,左补空格。

%-:其中m、n含义同上,n个字符输出在m列范围的左侧,右补空格。如果n>m,则自动取n值,即保证n个字符正常输出。

⑦f格式:用来输出实数(包括单、双精度),以小数形式输出。有以下几种用法:

%f:不指定宽度,整数部分全部输出并输出6位小数。

%:输出共占m列,其中有n位小数,如数值宽度小于m左端补空格。

%-:输出共占n列,其中有n位小数,如数值宽度小于m右端补空格。

⑧e格式:以指数形式输出实数。可用以下形式:

%e:数字部分(又称尾数)输出6位小数,指数部分占5位或4位。

%和%-:m、n和”-”字符含义与前相同。此处n指数据的数字部分的小数位数,m表示整个输出数据所占的宽度。

⑨g格式:自动选f格式或e格式中较短的一种输出,且不输出无意义的零。

3. scanf格式控制的完整形式

% * m l或h 格式字符

最常用及建议的使用形式为:scanf("%d%c%s", &a, &b, &c). 输入时采用隐式分隔符(空格、Tab、换行符)分隔不同的数据。

①格式字符与printf函数中的使用方式相同,以%d、%o、%x、%c、%s、%f、%e,无%u格式、%g格式。

②可以指定输入数据所占列宽,系统自动按它截取所需数据。如:

scanf("%3d%3d", &a, &b);

输入:123456

系统自动将123赋给a,456赋给b。

③%后的"*"附加说明符,用来表示跳过它相应的数据。例如:

scanf("%2d%*3d%2d", &a, &b);

如果输入如下信息:1234567。将12赋给a,67赋给b。第二个数据"345"被跳过不赋给任何变量。

④输入数据时不能规定精度,例如:

scanf("%7.2f",&a);

是不合法的,不能企图输入:12345.67而使a的值为12345.67。

------------------相关---------

----------

输入数据流分隔

①根据格式字符的含义从输入流中取得数据,当输入流中数据类型与格式字符要求不符时,就认为这一项结束。如:

scanf("%d%c%f", &a, &b, &c);

如果输入如下信息:

1234r1234.567

则scanf函数在接收数据时发现"r"类型不匹配,于是把"1234"转换成整型赋值给a,把"r"赋给变量b,最后把"1234.567"转换成实型数据赋给c。

②根据格式项中指定的域宽分隔出数据项。如语句:scanf("%2d%3f%4f", &a, &b, &c);

如果输入如下信息:

2345

则scanf函数在接收数据时根据域宽把12赋值给a,345赋值给b,6789赋值给c。

③隐式分隔符。空格、跳格符('t')、换行符('n')都是C语言认定的数据分隔符。

④显式分隔符。在scanf函数的两个格式说明项间有一个或多个普通字符,那么在输入数据时,在两个数据之间也必须以这一个或多个字符分隔。如语句:

scanf("a=%d,b=%f,c=%f", &a, &b, &c);

则输入数据应该为:

a=1234,b=67.8,c=98.123

---------------------------------------

关于scanf函数的进一步说明:

① scanf 函数中的“格式控制”后面应当是变量地址,而不应是变量名。例如,如果a、b为整型变量,则

scanf("%d,%d", a, b);

是不对的,应将“a,b”改为“&a, &b”。

②如果在“格式控制”字符串中除了格式说明以外还有其它字符,则在输入数据时应输入与这些字符相同的字符。例如:

scanf("%d,%d", &a, &b);

输入时应输入:3,4。3与4之间的逗号应与scanf函数中的“格式控制”中的逗号相对应,输入其它符号是不对的。

③在用"%c"格式输入字符时,空格字符和转义字符都作为有效字符输入。

scanf("%c%c%c", &c1, &c2, &c3);

如输入:a b c 。字符'a'赋给c1,字符(空格)' '赋给c2,字符'b'赋给c3。

④ scanf 中不使用U说明符.对unsigned型数据用d、o、x说明符输入.


本文标签: 字符 格式 输入 输出 字符串