2014-04-23 14:26:53 muguan11 阅读数 1167


格式化输入输出函数

这些函数都要包含头文件stdio.h, 以v开始的还要包含头文件stdarg.h

1. 输出
printf: 格式化输出数据
函数定义: int printf(const char *format, ...);
函数说明: printf()会根据参数format字符串来转换并格式化数据, 然后将结果写出到标准输出设备, 直到出现字符串结束符('\0')为止. 成功则返回实际输出的字符数, 失败则返回-1, 错误原因存在于errno中.
fprintf: 格式化输出数据至文件
函数定义: int fprintf(FILE *stream, const char *format, ...);
说明: fprintf()同printf(), 不同点将结果输出到参数stream指定的文件中.
sprintf: 格式化字符串复制
函数定义: int sprintf(char *str, const char *format, ...);
说明: sprintf()同printf(), 不同点将结果复制到参数str所指的字符串数组中.
snprintf: 格式化字符串复制
函数定义: int snprintf(char *str, size_t size, const char *format, ...);
说明: snprintf()同sprintf(), 不同点出现字符串结束符('\0')或达到参数size都为止.


以v开始的函数功能同对应去掉v的函数, 就是参数不相同
vprintf: 格式化输出数据
函数定义: int vprintf(const char *format, va_list ap);
vfprintf: 格式化输入数据至文件
函数定义: int vfprintf(FILE *stream, const char *format, va_list ap);
vsprintf: 格式化字符串复制
函数定义: int vsprintf(char *str, const char *format, va_list ap);
vsnprintf: 格式化字符串复制
函数定义: int vsnprintf(char *str, size_t size, const char *format, va_list ap);

2. 输入
scanf: 格式化字符输入
函数定义: int scanf(const char *format, ...);
说明: scanf()会将输入的数据根据参数format字符串来转换并格式化数据. 成功则返回参数数目, 失败则返回-1, 错误原因存于errno中.
scanf()格式转换的一般形式如下:
%[*][size][l][h]type
以中括号括起来的参数为选择性参数, 而%与type则是必要的. 
* 代表该对应的参数数据忽略不保存. 
size 为允许参数输入的数据长度. 
l 输入的数据数值以long int 或double型保存. 
h 输入的数据数值以short int 型保存. 
底下介绍type的几种形式:
%d 输入的数据会被转成一有符号的十进制数字(int). 
%i 输入的数据会被转成一有符号的十进制数字, 若输入数据以“0x”或“0X”开头代表转换十六进制数字, 若以“0”开头则转换八进制数字, 其他情况代表十进制. 
%0 输入的数据会被转换成一无符号的八进制数字. 
%u 输入的数据会被转换成一无符号的正整数. 
%x 输入的数据为无符号的十六进制数字, 转换后存于unsigned int型变量. 
%X 同%x
%f 输入的数据为有符号的浮点型数, 转换后存于float型变量. 
%e 同%f
%E 同%f
%g 同%f
%s 输入数据为以空格字符为终止的字符串. 
%c 输入数据为单一字符. 
[] 读取数据但只允许括号内的字符. 如[a-z]. 
[^] 读取数据但不允许中括号的^符号后的字符出现, 如[^0-9].
fscanf: 格式化字符串输入
函数定义: int fscanf(FILE *stream, const char *format, ...);
说明: fscanf()同scanf(), 不同点从参数stream文件流中读取字符串进行转换.
sscanf: 格式化字符串输入
函数定义: int sscanf(const char *str, const char *format, ...);
说明: sscanf()同scanf(), 不同点取参数str中的字符串进行转换.

以v开始的函数功能同对应去掉v的函数, 就是参数不相同
vscanf: 格式化字符串输入
vfscanf: 格式化字符串输入
vsscanf: 格式化字符串输入

参数format字符串可包含下列三种字符类型:
1. 一般文本, 伴随直接输出.
2. ASCII控制字符, 如\t, \n等.
3. 格式转换字符.
    格式转换为一个百分比符号(%)及其后的格式字符所组成. 一般而言, 每个%符号在其后都必需有一printf()的参数与之相呼应(只有当%%转换字符出现时会直接输出%字符), 而欲输出的数据类型必须与其相对应的转换字符类型相同.
printf()格式转换的一般形式如下:
%[flags][width][.prec]type
以中括号括起来的参数为选择性参数, 而%与type则是必要的. 底下先介绍type的几种形式:
整数:
%d 整数的参数会被转成一有符号的十进制数字
%u 整数的参数会被转成一无符号的十进制数字
%o 整数的参数会被转成一无符号的八进制数字
%x 整数的参数会被转成一无符号的十六进制数字, 并以小写abcdef表示
%X 整数的参数会被转成一无符号的十六进制数字, 并以大写ABCDEF表示
浮点型数:
%f double型的参数会被转成十进制数字, 并取到小数点以下六位, 四舍五入.
%e double型的参数以指数形式打印, 有一个数字会在小数点前, 六位数字在小数点后, 而在指数部分会以小写的e来表示.
%E 与%e作用相同, 唯一区别是指数部分将以大写的E来表示.
%g double型的参数会自动选择以%f或%e的格式来打印, 其标准是根据欲打印的数值及所设置的有效位数来决定.
%G 与%g作用相同, 唯一区别在以指数形态打印时会选择%E格式.
字符及字符串:
%c 整型数的参数会被转成unsigned char型打印出.
%s 指向字符串的参数会被逐字输出, 直到出现NULL字符为止.
%p 如果是参数是"void *"型指针则使用十六进制格式显示.
prec有几种情况:
1. 正整数的最小位数.
2. 在浮点型数中代表小数位数
3. 在%g格式代表有效位数的最大值.
4. 在%s格式代表字符串的最大长度.
5. 若为×符号则代表下个参数值为最大长度.
width为参数的最小长度, 若此栏并非数值, 而是*符号, 则表示以下一个参数当做参数长度.
flags有下列几种情况:
- 此旗标会将一数值向左对齐.
+ 一般在打印负数时, printf()会加印一个负号, 整数则不加任何负号. 此旗标会使得在打印正数前多一个正号(+).
# 此旗标会根据其后转换字符的不同而有不同含义. 当在类型为o之前(如%#o), 则会在打印八进制数值前多印一个o.而在类型为x之前(%#o)则会在打印十六进制数前多印’0x’, 在型态为e、E、f、g或G之前则会强迫数值打印小数点. 在类型为g或G之前时则同时保留小数点及小数位数末尾的零.
0 当有指定参数时, 无数字的参数将补上0. 默认是关闭此旗标, 所以一般会打印出空白字符.

不定参数: va_list
   C语言中有些函数会利用不定参数的方式来取得参数内容, 常见的如printf(), sprintf(), execl()等等, 其最后参数是以...定义, 即代表后面的参数为不定个数的参数内容. 不定参数相关的表头文件在/usr/lib/gcc/include/stdarg.h其定义如下:


 函数名称 函数原型  功能说明 
getc  int getc(FILE *stream) 从文件流中读入一个字符
fgetc int fgetc(FILE *stream) 从文件流中读入一个字符
getchar int getchar(void) 从标准输入读入一个字符
putc int putc(int c,FILE *stream) 将字符c写入文件流中
fputc int fputs(int c,FILE *stream) 将字符c写入文件流中
putchar int putchar(int c) 将字符c写入标准输出
gets char *gets(char *s)  从标准输入中读入字符串,直到出现换行字符或文件尾部为止
fgets char *gets(char *s,int size,FILE *stream) 从文件流中读入字符串,直到出现换行字符或问津尾部为止
puts int puts(const char*s) 将指定的字符串写到标准输出中
puts int *fputs(char *s,FILE *stream) 将指定的字符串写到文件流中

2018-11-20 19:19:17 qq_27350133 阅读数 93

Linux标准I/O实例 向文件定时输出时间

向文件每秒写入一次当前系统时间,并添加行号。下一次启动程序时自动在文本末追加时间。

涉及的函数

/*标准输出函数*/
int printf(const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
/*文件打开 读取函数*/
FILE *fopen(const char *path, const char *mode);
char *fgets(char *s, int size, FILE *stream);
/*获取系统时间函数*/
time_t time(time_t *t);
struct tm *localtime(const time_t *timep);
/*冲洗缓冲区函数*/
int fflush(FILE *stream);
/*休眠函数*/
unsigned int sleep(unsigned int seconds);

代码

#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
int main(int argc,char* argv[])
{

	FILE* fp;
	int line=0;
	char buf[64];
	time_t t;
	struct tm* tp;
	if(argc<2)
	{
		printf("Usage: %s <file>\n",argv[0]);
		return -1;
	}

	if((fp = fopen(argv[1],"a+"))==NULL)
	{
		perror("fopen\n");
		return -1;
	}

	while(fgets(buf,64,fp) != NULL) //计算有多少行。
	{
		if(buf[strlen(buf)-1] == '\n')line++;
	}

	while(1)
	{
		time(&t);
		tp = localtime(&t);
		fprintf(fp,"%02d, %d-%02d-%02d %02d:%02d:%02d\n",++line,tp->tm_year+1900,	tp->tm_mon+1,tp->tm_mday,tp->tm_hour,tp->tm_min,tp->tm_sec);
		fprintf(stdout,"%02d, %d-%02d-%02d %02d:%02d:%02d\n",line,tp->tm_year+1900,	tp->tm_mon+1,tp->tm_mday,tp->tm_hour,tp->tm_min,tp->tm_sec);
		
		fflush(fp);
		sleep(1);
	}
	return 0;
}

2018-12-06 21:10:35 qq_42579119 阅读数 75

输入输出函数的介绍:
(1)所谓输入输出是以计算机为主体而言的。
(2)本章介绍的是向标准输出设备显示器输出数据的语句。
(3)在C语言中,所有的数据输入/输出都是由库函数完成的。 因此都是函数语句。
(4)在使用C语言库函数时,要用预编译命令#include将有关“头文件”包括到源文件中。使用标准输入输出库函数时要用到 “stdio.h”文件,因此源文件开头应有以下预编译命令:#include< stdio.h >或#include ”stdio.h”,stdio是standard input &outupt的意思。
(5)考虑到printf和scanf函数使用频繁,系统允许在使用这两个函数时可不加#include< stdio.h >或#include ”stdio.h”
一、字符数据的输入输出
( 1 ) putchar 函数(字符输出函数)
putchar 函数是字符输出函数, 其功能是在显示器上输出单个字符。其一般形式为:putchar(字符变量).对控制字符则执行控制功能,不在屏幕上显示。使用本函数前必须要用文件包含命令:#include<stdio.h>或#include “stdio.h”
( 2 ) getchar函数(键盘输入函数)
getchar函数的功能是从键盘上输入一个字符。其一般形式为:getchar();
通常把输入的字符赋予一个字符变量,构成赋值语句,如:char c; c=getchar();使用getchar函数还应注意几个问题:
1)getchar函数只能接受单个字符,输入数字也按字符处理。输入多于一个字符时,只接收第一个字符。
2)使用本函数前必须包含文件“stdio.h”。
3)在TC屏幕下运行含本函数程序时,将退出TC 屏幕进入用户屏幕等待用户输入。输入完毕再返回TC屏幕。
二、格式输入与输出
(1)printf函数(格式输出函数)
printf函数称为格式输出函数,其关键字最末一个字母f即为“格式”(format)之意。其功能是按用户指定的格式,把指定的数据显示到显示器屏幕上。在前面的例题中我们已多次使用过这个函数。
(1)printf函数调用的一般形式
printf函数是一个标准库函数,它的函数原型在头文件“stdio.h”中。但作为一个特例,不要求在使用 printf 函数之前必须包含stdio.h文件。printf函数调用的一般形式为:printf(“格式控制字符串”,输出表列),其中格式控制字符串用于指定输出格式。格式控制串可由格式字符串和非格式字符串两种组成。格式字符串是以%开头的字符串,在%后面跟有各种格式字符,以说明输出数据的类型、形式、长度、小数位数等。如:“%d”表示按十进制整型输出;“%ld”表示按十进制长整型输出;“%c”表示按字符型输出等。非格式字符串在输出时原样照印,在显示中起提示作用。输出表列中给出了各个输出项,要求格式字符串和各输出项在数量和类型上应该一一对应。
**格式字符串
格式: [标志][输出最小宽度][.精度][长度]类型
1)类型:类型字符用以表示输出数据的类型,其格式符和意义如下表所示:
d,以十进制形式输出带符号整数(正数不输出符号)
o,以八进制形式输出无符号整数(不输出前缀0)
x或X ,以十六进制形式输出无符号整数(不输出前缀Ox)
u,以十进制形式输出无符号整数
f,以小数形式输出单、双精度实数
e或E,以指数形式输出单、双精度实数
g或G,以%f或%e中较短的输出宽度输出单、双精度实数
c,输出单个字符
s,输出字符串
2)标志:标志字符为-、+、#、空格四种,其意义下表所示:
-,结果左对齐,右边填空格
+,输出符号(正号或负号)
空格,输出值为正时冠以空格,为负时冠以负号
#,对c,s,d,u类无影响;对o类,在输出时加前缀o;对x类,在输出时加前缀0x;对e,g,f 类当结果有小数时才给出小数点
3)输出最小宽度:用十进制整数来表示输出的最少位数。若实际位数多于定义的宽度,则按实际位数输出,若实际位数少于定义的宽度则补以空格或0。
4)精度:精度格式符以“.”开头,后跟十进制整数。本项的意义是:如果输出数字,则表示小数的位数;如果输出的是字符,则表示输出字符的
个数;若实际位数大于所定义的精度数,则截去超过的部分。
5.长度:长度格式符为h,l两种,h表示按短整型量输出,l表示按长整型量输出。
(2)scanf函数(格式输入函数)
scanf函数称为格式输入函数,即按用户指定的格式从键盘上把数据输入到指定的变量之中。
(1) scanf函数的一般形式
scanf函数是一个标准库函数,它的函数原型在头文件“stdio.h”中,与printf函数相同,C语言也允许在使用scanf函数之前不必包含stdio.h文件。scanf函数的一般形式为:scanf(“格式控制字符串”,地址表列);其中,格式控制字符串的作用与printf函数相同,但不能显示非格式字符串,也就是不能显示提示字符串。地址表列中给出各变量的地址。地址是由地址运算符“&”后跟变量名组成的。这个地址就是编译系统在内存中给a,b变量分配的地址。在C语言中,使用了地址这个概念,这是与其它语言不同的。应该把变量的值和变量的地址这两个不同的概念区别开来。变量的地址是C编译系统分配的,用户不必关心具体的地址是多少。
(2) 格式字符串
格式字符串的一般形式为:%[
][输入数据宽度][长度]类型其中有方括号[]的项为任选项。各项的意义如下:

  1. 类型:表示输入数据的类型,其格式符和意义如下表所示。
    d,输入十进制整数
    o,输入八进制整数
    x,输入十六进制整数
    u,输入无符号十进制整数
    f或e,输入实型数(用小数形式或指数形式)
    c,输入单个字符
    s,输入字符串
  2. “*”符:用以表示该输入项,读入后不赋予相应的变量,即跳过该输入值。
    如:
    scanf("%d %*d %d",&a,&b);
    当输入为:123时,把1赋予a,2被跳过,3赋予b。
  3. 宽度:用十进制整数指定输入的宽度(即字符数)。
    例如:
    scanf("%5d",&a);
    输入:12345678
    只把12345赋予变量a,其余部分被截去。
    又如:
    scanf("%4d%4d",&a,&b);
    输入:12345678
    将把1234赋予a,而把5678赋予b。
  4. 长度:长度格式符为l和h,l表示输入长整型数据(如%ld) 和双精度浮点数(如%lf)。h表示输入短整型数据。
    使用scanf函数还必须注意以下几点:
    1))scanf函数中没有精度控制,如:scanf("%5.2f",&a);是非法的。不能企图用此语句输入小数为2位的实数。
    2))scanf中要求给出变量地址,如给出变量名则会出错。如 scanf("%d",a);是非法的,应改为scnaf("%d",&a);才是合法的。
    3))在输入多个数值数据时,若格式控制串中没有非格式字符作输入数据之间的间隔则可用空格,TAB或回车作间隔。C编译在碰到空格,TAB,回车或非法数据(如对“%d”输入“12A”时,A即为非法数据)时即认为该数据结束。
    4))在输入字符数据时,若格式控制串中无非格式字符,则认为所有输入的字符均为有效字符。
    例如: scanf("%c%c%c",&a,&b,&c);
    输入为:def
    则把’d’赋予a, ’ ’ 赋予b,'e’赋予c。
    只有当输入为:def
    时,才能把’d’赋于a,'e’赋予b,'f’赋予c。
    如果在格式控制中加入空格作为间隔,
    如:scanf ("%c %c %c",&a,&b,&c);
    则输入时各数据之间可加空格。
  5. 如果格式控制串中有非格式字符则输入时也要输入该非格式字符。
    例如:scanf("%d,%d,%d",&a,&b,&c);
    其中用非格式符“ , ”作间隔符,故输入时应为:5,6,7
    又如:scanf(“a=%d,b=%d,c=%d”,&a,&b,&c);
    则输入应为:a=5,b=6,c=7
  6. 如输入的数据与输出的类型不一致时,虽然编译能够通过,但结果将不正确。
2017-05-07 10:43:22 blight_888 阅读数 428

为了验证atexit()函数在Linux环境下的调用顺序,我们先来写四个fun函数,这样而且每个函数里边加一句话,这样我们就能更加清晰的在屏幕上看到 各个函数的调用顺序了。下边我们直接看代码。

这里写图片描述
这里写图片描述

这个是运行结果:
这里写图片描述
过程分析:
atexit函数先注册四个fun函数然后等待3秒,再打印hello main (如果main函数中不加\n 则main函数要输出的内容会先放到标准输出的缓冲区中,当main函数中调用exit函数的时候,会做一些自身的清理工作,同时刷新标准缓冲区中的内容),当执行到exit(0)时,exit会自动调用这些已经注册过的函数,但是由于压栈过程中先入后出的原则,所以先注册的函数会在最后执行。

关于atexit:
一个进程可以登记多达32个函数,这些函数将由exit自动调用,通常这32个函数被称为终止处理程序,并调用atexit函数来登记这些函数,atexit的参数是一个函数的地址,当调用到此函数时无需传递任何参数,该函数也不能返回,atexit函数被称为终止处理程序注册程序,注册完成以后,当函数终止exit()函数会主动调用前面注册的各个函数,但是exit()函数调用这些函数的的顺序于这些函数登记的顺序相反,这些都是由参数的压栈造成的,参数由于压栈顺序先进后出,同时如果一个函数被多次登记,那么该函数也将多次执行。

关于exit:
exit函数运行时会首先执行由atexit()函数登记的函数,然后会做一些自身的清理工作,同时刷新所有输出流,关闭所有打开的流,并且关闭通过标准I/O函数tmofile()创建的临时文件。
exit()函数用于在程序运行的过程中随时结束程序,exit的参数state是返回给操作系统,返回0表示正常程序结束,非0表示程序非正常结束。

2018-07-22 15:50:00 Mac_timmy 阅读数 164

个人博客传送门

Linux 中进行文件描述符的重定向可以使用两个函数:dup函数和dup2函数,其中还有一个dup3函数,但是这个是Linux后面版本添加的,不是所有的Linux内核都支持,在这里不讨论。

在Linux系统中约定文件描述符 0、1、2 对应标准输入、标准输出、标准错误,默认开启。

dup()

#include <unistd.h>
int dup(int fd);

使用dup()函数的时候,参数是新的文件描述符期望指向的文件描述符。返回文件描述符表中最小的没有被使用的文件描述符。

如果我们的fd除了默认打开的0、1、2之外,没有被使用的。我们调用dup(1),那么最小的没有被使用的fd = 3 就会指向跟fd = 1的同一个文件表。

dup(1)

他的做法就类似以下做法:

fcntl(1, F_DUPFD, 0);   //fcntl函数用来改变已经打开文件的属性。

dup2()

#include <unistd.h>
int dup2(int fd, int fd2);

参数中fd指的是希望被改变的文件描述符,fd2是期望指向的旧的文件描述符。如果fd已经被使用,那么就关闭它。如果fd = fd2,返回fd2但是不关闭。
dup2()函数的做法跟dup一样,不同点是dup2()函数可以指定期望改变的fd,而不是去最小未被使用的fd。如果要我们的fd = 3也指向fd = 1的话。调用如下:

dup2(3, 1)

他的做法类似以下做法:

close(3);
fcntl(3, F_DUPFD, 1);

但是跟上面两个函数调用有点不同的是,dup2()函数的操作是原子性的。分两个函数调用的中间可能会出现其他函数的调用。

Linux之select函数

阅读数 522

没有更多推荐了,返回首页