格式输出:
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 <stdio.h>
#include <string.h>
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 <stdio.h>
- #include <sys/types.h>
- #include <regex.h>
- /* 取子串的函数 */
- static char* substr(const char*str,
- unsigned start, unsigned end)
- {
- unsigned n = end - start;
- static char stbuf[256];
- strncpy(stbuf, str + start, n);
- stbuf[n] = 0;
- return stbuf;
- }
- /* 主程序 */
- int main(int argc, char** argv)
- {
- char * pattern;
- int x, z, lno = 0, cflags = 0;
- char ebuf[128], lbuf[256];
- regex_t reg;
- regmatch_t pm[10];
- const size_t nmatch = 10;
- /* 编译正则表达式*/
- pattern = argv[1];
- z = regcomp(?, pattern, cflags);
- if (z != 0)
- {
- regerror(z, ?, ebuf, sizeof(ebuf));
- fprintf(stderr, "%s: pattern ‘%s‘", ebuf, pattern);
- return 1;
- }
- /* 逐行处理输入的数据 */
- while(fgets(lbuf, sizeof(lbuf), stdin))
- {
- ++lno;
- if ((z = strlen(lbuf)) > 0 && lbuf[z-1] == ‘ ‘)
- lbuf[z - 1] = 0;
- /* 对每一行应用正则表达式进行匹配 */
- z = regexec(?, lbuf, nmatch, pm, 0);
- if (z == REG_NOMATCH) continue;
- else if (z != 0)
- {
- regerror(z, ?, ebuf, sizeof(ebuf));
- fprintf(stderr, "%s: regcom(‘%s‘)", ebuf, lbuf);
- return 2;
- }
- /* 输出处理结果 */
- for (x = 0; x < nmatch && pm[x].rm_so != -1; ++ x)
- {
- if (!x) printf("%04d: %s", lno, lbuf);
- printf(" $%d=‘%s‘", x, substr(lbuf, pm[x].rm_so,pm[x].rm_eo));
- }
- }
- /* 释放正则表达式 */
- regfree(?);
- return 0;
- }
# gcc regexp.c -o regexp
# ./regexp ‘regex[a-z]*‘ < regexp.c
0003: #include <regex.h>
$0=‘regex‘
0027: regex_t reg;
$0=‘regex‘
0054: z = regexec(?, lbuf, nmatch, pm, 0);
$0=‘regexec‘
1.cin>>i>>j;是用空格或TAB来分隔输入的. 如果是cin>>i;cin>>j;必须先输入i,再回车,最后输入j .
2.cout<<: 设 int x=30, y=300, z=1024;
1) cout<<x<<‘ ‘<<y<<‘ ‘<<z<<endl; //按十进制输出
2) 数字进制:使用hex、dec、oct分别控制输出数字的十六,十,八进制
cout<<hex<<x<<‘ ‘<<y<<‘ ‘<<z<<endl;//x,y,z都按十六进制输出
3) 如何对齐:使用setw控制宽度
cout<<x<<setw(30)<<y<<endl;
//X正常输出,而Y左边会空出28个空格
默认对齐方式为右对齐,即填充字符从左开始,最后是输出字符.
如果setiosflags(ios::left),则填充字符在右,输出字符在前.
4) 填充字符:使用setfill控制填充字符
cout<<x<<setfill(‘.‘)<<setiosflags(ios::left)<<setw(30)<<y<<endl;//28个空格用"."填充.
填充时,如果实际长度比设置长度短,则按实际长度输出.
5) 设置精度:使用setprecision控制输出精度
6)如何取消对齐:
cout<<resetiosflags(ios::left);//取消左对齐.因为对齐是针对所有输出都有效果,而不专对最近的一个输出.
7)如何取消填充:
setfill()如何取消呢?
cout<<setfill(‘ ‘); 就可以了.
注意: ‘ ‘之间是一个空格符. 因为setfill()也是对所有输出有效,只要你设置了setw().
8) 浮点控制格式:
cout.setf(ios:: );//这也是针对所有输出有效的.
常用的有;
ios::fixed固定的浮点显示
ios::scientific指数表示,科学记数法
ios::left / ios::right 左/右对齐
ios::skipws忽略前导空白
ios::uppercase / ios::lowercase 十六进制大/小写输出
ios::showpos强制在正数前加+号
ios::showpoint 强制显示小数点后的无效0
precision(18); //精度为18
例如:
float f=2.0/3.0,f1=0.000000001,f2=-9.9;
cout<<f<<‘ ‘<<f1<<‘ ‘<<f2<<endl; //正常输出
cout.setf(ios::showpos); //强制在正数前加+号
cout<<f<<‘ ‘<<f1<<‘ ‘<<f2<<endl;
cout.unsetf(ios::showpos); //取消正数前加+号
cout.setf(ios::showpoint); //强制显示小数点后的无效0
cout<<f<<‘ ‘<<f1<<‘ ‘<<f2<<endl;
cout.unsetf(ios::showpoint); //取消显示小数点后的无效0
cout.setf(ios::scientific); //科学记数法
cout<<f<<‘ ‘<<f1<<‘ ‘<<f2<<endl;
cout.unsetf(ios::scientific); //取消科学记数法
cout.setf(ios::fixed); //按点输出显示
cout<<f<<‘ ‘<<f1<<‘ ‘<<f2<<endl;
cout.unsetf(ios::fixed); //取消按点输出显示
cout.precision(18); //精度为18,正常为6
cout<<f<<‘ ‘<<f1<<‘ ‘<<f2<<endl;
cout.precision(6); //精度恢复为6
操纵算子实现同样的功能:如下:
float f=2.0/3.0,f1=0.000000001,f2=-9.9;
cout<<f<<‘ ‘<<f1<<‘ ‘<<f2<<endl; //正常输出
cout<<setiosflags(ios::showpos); //强制在正数前加+号
cout<<f<<‘ ‘<<f1<<‘ ‘<<f2<<endl;
cout<<resetiosflags(ios::showpos); //取消正数前加+号
cout<<setiosflags(ios::showpoint); //强制显示小数点后的无效0
cout<<f<<‘ ‘<<f1<<‘ ‘<<f2<<endl;
cout<<resetiosflags(ios::showpoint); //取消显示小数点后的无效0
cout<<setiosflags(ios::scientific); //科学记数法
cout<<f<<‘ ‘<<f1<<‘ ‘<<f2<<endl;
cout<<resetiosflags(ios::scientific); //取消科学记数法
cout<<setiosflags(ios::fixed); //按点输出显示
cout<<f<<‘ ‘<<f1<<‘ ‘<<f2<<endl;
cout<<resetiosflags(ios::fixed); //取消按点输出显示
cout<<setprecision(18); //精度为18,正常为6
cout<<f<<‘ ‘<<f1<<‘ ‘<<f2<<endl;
cout<<setprecision(6); //精度恢复为6
9) 其它的输出方法:
还有些为了让缓冲区不影响程序的正确操作的缓冲去的操作,如:cin.putback(),fflush(stdin),cout.flush().我们
做一下简单的说明。
1、getch()和getche(),非缓冲式输入,从键盘读入一个字符。getch()读入字符不显示。有conio.h支持。
2、cin.get(),getchar(),缓冲式输入,从键盘读入一个字符,并显示。getchar()由stdio.h支持,cin.get()由iostream.h支持。
3、putch()和putchar(),非缓冲式输出,输出一个字符到显示器。putch()由conio.h支持,putchar()由stdio.h支持。
4、cout.put(),缓冲式输出,输出一个字符到显示器。由iostream.h支持。
5、gets()和cin.geline(),缓冲式输入,读入一字符串(包括空格,不包括最后的回车),gets()由stdio.h支持,cin.getline()由iostream.h支持。
6、puts(),非缓冲输出,输出一个字符串,由stdio.h支持。
7、cin.putback(),把一个字符送回输入缓冲区。
8、fflush(stdin),清除输入缓冲区操作。无法清除cin.get()等带来的操作。
9、cout.flush(),清楚输出缓冲区。