格式输出:
printf(格式控制, 输出表列);
%d 十进制数 %md m为指定的宽度 若数据位数小于m,则左端补以空格;若大于m,则按实际位数输出
%ld 长整型数据 %mld 指定字段宽度
%o 八进制整数形式 %mo
%x 十六进制整数形式 %mx
%u unsigned型数据,它也可用%o或%x格式输出
%c 一个字符 %mc
%s 字符串 有几种用法
1.%s
printf("%s", "China");
输出 China
2.%ms 控制为m列 若串长小于m, 则左补空格,大于则突破m限制,将字符串完全输出
3.%-ms 若串长小于m, 则右补空格(居左)
4.%m.ns 输出占m列,取字符串左端n个字符.这n个字符输出在m列的右侧,左补空格
5.%-m.ns m.n同上,这n个字符输出在m列的左侧,右补空格.若n>m,则m自动取n值,保证n个字符正常输出
%f 输出实数(包括单.双精度),以小数形式输出
1.%f 输出全部整数部分,输出6位小数
2.%m.nf 指定输出的数据共占m列,其中有n位小数.若数值长度小于m,则左端补空格
3.%-m.nf 指定输出的数据共占m列,其中有n位小数.若数值长度小于m,则右端补空格
%e 以指数形式输出实数
1.%e 不指定输出数据所占的宽度和数字部分的小数数位,数值按规范化输出
2.%m.ne 和 %-m.ne 输出占m列,n指输出的数据的小数部分(尾数)的小数数位,-同上
%g 输出实数,根据数值大小,自动选择f格式或者e格式(选择输出宽度小的),且不输出无意义的零
格式控制中可以包含转义字符,如'/n' '/t' '/b' '/r'
输出%的方法 printf("%f%%", 1.0/3) 输出: 0.333333%
格式输入
scanf(格式控制, 地址表列) sscanf
类似printf .以例程解释
1. scanf("%3d%3d", &a, &b); //列数截取数据
input -> 123456
then -> a = 123 b = 456
2. scanf("%2d %*3d %2d", &a, &b) //*表示跳过列数读取数据
input -> 12 345 67
then -> a = 12 b = 67
3. scanf("%d, %d", &a, &b)
input -> 1, 4 //在格式控制中,如果有非格式说明外的字符,应该在输入时在对应位置输入该字符
scanf("%d %d", &a, &b) //输入时,两数据应有不少于格式控制中的空格
scanf("%c%c%c", &a, &b, &c) //用%c输入字符时,空格字符和转义字符都作为有效字符输入
4. %s 输入字符串.将字符串传送到一个字符数组中,输入时以非空白字符开始,以第一个空白字符结束.
字符串以串结束标志'/0'作为最后一个字符
5. * 符用以表示该输入项读入后不赋予相应的变量,即跳过该输入值。
scanf("%d %*d %d",&a,&b); //当输入为:1 2 3 时,把1赋予a,2被跳过,3赋予b。
6. 在输入数据时,遇以下情况时认为该数据结束
(1)遇空格 或 回车 或 跳格(tab)
(2)按指定的宽度结束. 如3列的%3d
(3)非法输入
7. 输入带空格的字符串
scanf("%[^/n]%*c", str);
对比如下
#include
#include
int main()
{
char str[222];
char c;
scanf("%[^/n]", str);
printf("%s", str);
scanf("%c", &c);
printf("%c", c);
return 0;
}
8. 函数 int sscanf (const char *str,const char * format,........);
sscanf()会将参数str的字符串根据参数format字符串来转换并格式化数据。转换后的结果存于对应的参数内。
sscanf与scanf类似,都是用于输入的,只是scanf以stdin为输入源,前者以固定字符串为输入源。
# include < stdio. h>
int main( )
{
const char * s = "iios/12DDWDFF@122" ;
char buf[ 20] ;
sscanf ( s, "%*[^/]/%[^@]" , buf ) ;
printf ( "%s/n" , buf ) ;
return 0;
}
结果为: 12DDWDFF
9. scanf 和 sscanf 的一些特殊用法:(类似正则)
%[a-z] 表示匹配a到z中任意字符,贪婪性(尽可能多的匹配)
%[aB'] 匹配a、B、'中一员,贪婪性
%[^a] 匹配非a的任意字符,贪婪性
1. 常见用法。
charstr[ 512] = { 0} ;
sscanf( "123456" , "%s" , str) ;
printf( "str=%s" , str) ;
2. 取指定长度的字符串。如在下例中,取最大长度为4字节的字符串。
sscanf( "123456" , "%4s" , str) ;
printf( "str=%s" , str) ;
3. 取到指定字符为止的字符串。如在下例中,取遇到空格为止字符串。
sscanf( "123456abcdedf" , "%[^]" , str) ;
printf( "str=%s" , str) ;
4. 取仅包含指定字符集的字符串。如在下例中,取仅包含1到9和小写字母的字符串。
sscanf( "123456abcdedfBCDEF" , "%[1-9a-z]" , str) ;
printf( "str=%s" , str) ;
5. 取到指定字符集为止的字符串。如在下例中,取遇到大写字母为止的字符串。
sscanf( "123456abcdedfBCDEF" , "%[^A-Z]" , str) ;
printf( "str=%s" , str) ;
% [ ] 的用法:
% [ ] 表示要读入一个字符集合, 如果[ 后面第一个字符是”^”,则表示反意思。
[ ] 内的字符串可以是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
字符串处理函数
1.puts(字符数组)
将一个字符串输出到终端
char str[] = {"Hello otto./n"};
puts(str);
2.gets(字符数组) warning: the `gets' function is dangerous and should not be used.
从终端输入一个字符串到字符数组,并且返回字符数组的起始地址
gets(str);
3.strcat(字符数组1,字符数组2)
把字符串2连接到字符串1后面,结果放在字符数组1中,并返回字符数组1的地址.
a)字符数组1必须足够大,以容纳连接后的新字符串.
b)连接时将字符串1后的'/n'取消,保留字符串2的'/n'
4.strcpy(字符数组1,字符数组2)
将字符串2复制到字符数组1中去.
a)字符数组1必须足够大,以容纳连接后的新字符串.
b)字符数组1必须写成数组名形式,字符数组2还可以是一个字符串常量
c)复制时连同字符串后的'/n'一起复制到字符数组1中去
d)不能用赋值语句将一个字符串常量或字符数组直接给一个字符数组
e)可以用strncpy函数将字符串2中前面n个字符赋值到字符数组1中
strncpy(str1, str2, n); n不应大于str1的长度
5.strcmp(字符串1, 字符串2)
对两个字符串自左至右逐个字符相比(ASCII码,按英文字典顺序,在后面的为"大",小写字母比大写"大")
返回比较结果:
a)如果字符串1=字符串2,则函数值为0
b)如果字符串1>字符串2,则函数值为一个正整数
c)如果字符串1<字符串2,则函数值为一个负整数
6.strlen(字符数组)
返回字符串的实际长度(不包括'/n')
7.strlwr(字符串)
将字符串中大写字母换成小写字母
8.strupr(字符串)
将字符串中小写字母换成大写字母
字符串的输入输出与空间分配:
char p[34] = "string";
gets(p); //可以输入
char *aa;
//gets(aa); //不可以输入
aa = (char*)malloc(30);
gets(aa); //可以输入 分配空间
getch() getche() getchar()
getche() 有返回显示 //getch() with e(echo) 回显
getchar()是stdio.h中的库函数,它的作用是从stdin流中读入一个字符,把该字符显示在屏幕上
getch()和getche()是conio.h中的库函数,从键盘接收字符。
区别在于: getchar()函数等待输入直到按回车才结束(前提是缓冲区没有数据),回车前的所有输入字符都会逐个显示在屏幕上。但只有第一个字符作为函数的返回值。getch()每次都等待用户的输入,因为getch()从键盘接收,即时的接收,并不是从stdin流中去读取数据。
getchar()从stdin流中读取字符,所以第一个getchar()接受的是刚刚中断的流队列中即将出列的第一个字符(不限于回车符),如果流队列不为空,执行getchar()就继续直到把回车符也放空为止,空了之后再在执行getchar()就停下等待你的输入了。
getchar有一个int型的返回值.当程序调用getchar时.程序就等着用户按键.用户输入的字符被存放在键盘缓冲区中.直到用户按回车为止(回车字符也放在缓冲区中).getchar函数的返回值是用户输入的第一个字符的ASCII码,如出错返回-1,且将用户输入的字符回显到屏幕.如用户在按回车之前输入了不止一个字符,其他字符会保留在键盘缓存区中,等待后续getchar调用读取.也就是说, 后续的getchar调用不会等待用户按键,而直接读取缓冲区中的字符,直到缓冲区中的字符读完为后,才等待用户按键.
getch与 getchar基本功能相同,差别是getch直接从键盘获取键值,不等待用户按回车,只要用户按一个键,getch就立刻返回,getch返回值是用户输入的ASCII码,出错返回-1.输入的字符不会回显在屏幕上.getch函数常用于程序调试中,在调试时,在关键位置显示有关的结果以待查看,然后用 getch函数暂停程序运行,当按任意键后程序继续运行.
c与正则表达式
标准的C和C++都不支持正则表达式,但有一些函数库可以辅助C/C++程序员完成这一功能,其中最著名的当数Philip Hazel的Perl-Compatible Regular Expression库,许多Linux发行版本都带有这个函数库。
编译正则表达式
为了提高效率,在将一个字符串与正则表达式进行比较之前,首先要用regcomp()函数对它进行编译,将其转化为regex_t结构:
int regcomp(regex_t *preg, const char *regex,int cflags);
参数regex是一个字符串,它代表将要被编译的正则表达式;参数preg指向一个声明为regex_t的数据结构,用来保存编译结果;参数cflags决定了正则表达式该如何被处理的细节。
如果函数regcomp()执行成功,并且编译结果被正确填充到preg中后,函数将返回0,任何其它的返回结果都代表有某种错误产生。
匹配正则表达式
一旦用regcomp()函数成功地编译了正则表达式,接下来就可以调用regexec()函数完成模式匹配:
int regexec(const regex_t *preg,
const char *string, size_t nmatch,
regmatch_t pmatch[], int eflags);
typedef struct {
regoff_t rm_so;
regoff_t rm_eo;
} regmatch_t;
参数preg指向编译后的正则表达式,参数string是将要进行匹配的字符串,而参数nmatch和pmatch则用于把匹配结果返回给调用程序,最后一个参数eflags决定了匹配的细节。
在调用函数regexec()进行模式匹配的过程中,可能在字符串string中会有多处与给定的正则表达式相匹配,参数pmatch就是用来保存这些匹配位置的,而参数nmatch则告诉函数regexec()最多可以把多少个匹配结果填充到pmatch数组中。当regexec()函数成功返回时,从string+pmatch[0].rm_so到string+pmatch[0].rm_eo是第一个匹配的字符串,而从 string+pmatch[1].rm_so到string+pmatch[1].rm_eo,则是第二个匹配的字符串,依此类推。
释放正则表达式
无论什么时候,当不再需要已经编译过的正则表达式时,都应该调用函数regfree()将其释放,以免产生内存泄漏。
void regfree(regex_t *preg);
函数regfree()不会返回任何结果,它仅接收一个指向regex_t数据类型的指针,这是之前调用regcomp()函数所得到的编译结果。
如果在程序中针对同一个regex_t结构调用了多次regcomp()函数,POSIX标准并没有规定是否每次都必须调用regfree()函数进行释放,但建议每次调用regcomp()函数对正则表达式进行编译后都调用一次regfree()函数,以尽早释放占用的存储空间。
报告错误信息
如果调用函数regcomp()或regexec()得到的是一个非0的返回值,则表明在对正则表达式的处理过程中出现了某种错误,此时可以通过调用函数regerror()得到详细的错误信息。
size_t regerror(int errcode,const regex_t *preg, char *errbuf,size_t errbuf_size);
参数errcode是来自函数regcomp()或regexec()的错误代码,而参数preg则是由函数regcomp()得到的编译结果,其目的是把格式化消息所必须的上下文提供给regerror()函数。在执行函数regerror()时,将按照参数errbuf_size指明的最大字节数,在errbuf缓冲区中填入格式化后的错误信息,同时返回错误信息的长度。
应用正则表达式
最后给出一个具体的实例,介绍如何在C语言程序中处理正则表达式。#include
上述程序负责从命令行获取正则表达式,然后将其运用于从标准输入得到的每行数据,并打印出匹配结果。执行下面的命令可以编译并执行该程序:
# gcc regexp.c -o regexp
# ./regexp 'regex[a-z]*' < regexp.c
0003: #include
$0='regex'
0027: regex_t reg;
$0='regex'
0054: z = regexec(?, lbuf, nmatch, pm, 0);
$0='regexec'