fopen(打开文件)
相关函数 open, fclose
表头文件 #include< stdio.h>
定义函数 FILE * fopen(const char * path,const char * mode);
函数说明 参数path字符串包含欲打开的文件路径及文件名,参数mode字符串则代表着流形态。
mode有下列几种形态字符串:
r 打开只读文件,该文件必须存在。
r+ 打开可读写的文件,该文件必须存在。
rb+ 读写打开一个二进制文件,只允许读写数据。
rt+ 读写打开一个文本文件,允许读和写。
w 打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件。
w+ 打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。
a 以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。(EOF符保留)
a+ 以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。 (原来的EOF符不保留)
wb 只写打开或新建一个二进制文件;只允许写数据。
wb+ 读写打开或建立一个二进制文件,允许读和写。
wt+ 读写打开或着建立一个文本文件;允许读写。
at+ 读写打开一个文本文件,允许读或在文本末追加数据。
ab+ 读写打开一个二进制文件,允许读或在文件末追加数据。
上述的形态字符串都可以再加一个b字符,如rb、w+b或ab+等组合,加入b 字符用来告诉函数库打开的文件为二进制文件,而非纯文字文件。不过在POSIX系统,包含Linux都会忽略该字符。由fopen()所建立的新文件会具有S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH(0666)权限,此文件权限也会参考umask 值。
返回值
文件顺利打开后,指向该流的文件指针就会被返回。若果文件打开失败则返回NULL,并把错误代码存在errno 中。
使用打印信息的接口时,经常见到__VA_ARGS__和##__VA_ARGS__这两个字符串,花时间学习下这部分的知识,发现还有#和##这两个比较有意思的字符串,记下他们的用法:
#: 用来把参数转换成字符串;
#include <iostream>
#define LOG(x) do { printf("%s=%d\n",#x,x); }while(0)
int main()
{
int score = 96;
LOG(score);
LOG(6);
getchar();
return 0;
}
##:用于将带参数的宏定义中将两个子串(token)联接起来,从而形成一个新的子串;但它不可以是第一个或者最后一个子串。所谓的子串(token)就是指编译器能够识别的最小语法单元;
#include <iostream>
#define LOG(x) log##x()
void logA(){
printf("log func A \n");
}
void logB(){
printf("log func B\n");
}
int main()
{
LOG(A);
getchar();
return 0;
}
__VA_ARGS__:用于在宏替换部分中,表示可变参数列表;
#include <iostream>
#define LOG(...) printf(__VA_ARGS__);
int main()
{
LOG("score is %d\n",96);
getchar();
return 0;
}
##__VA_ARGS__ :和 __VA_ARGS_ 作用类似,## __VA_ARGS__ 宏前面加上 ## 的作用在于,当可变参数的个数为0时,这里的##起到把前面多余的","去掉的作用,否则会编译出错
#include <stdio.h>
#define LOG(...) printf("123+%s=%d\n", __VA_ARGS__)
//#define LOG2(...) printf("123+s=d\n", __VA_ARGS__) //该宏定义GCC下报错,MSVC下未报错
#define LOG2(...) printf("123+s=d\n", ##__VA_ARGS__) //该宏定义GCC、MSVC下均未报错
int main()
{
LOG("3", 123);
LOG2();
return 0;
}
fflush()函数:更新缓存区
头文件:#include<stdio.h>
函数定义:int fflush(FILE *stream);
函数说明:调用fflush()会将缓冲区中的内容写到stream所指的文件中去.若stream为NULL,则会将所有打开的文件进行数据更新
extern int snprintf (char *__restrict __s, size_t __maxlen, const char *__restrict __format, ...)
(1) 如果格式化后的字符串长度 < size,则将此字符串全部复制到str中,并给其后添加一个字符串结束符(‘\0’);
(2) 如果格式化后的字符串长度 >= size,则只将其中的(size-1)个字符复制到str中,并给其后添加一个字符串结束符(‘\0’),返回值为欲写入的字符串长度。
snprintf的返回值是欲写入的字符串长度,而不是实际写入的字符串度。如:
char buf[8];
int n = snprintf(buf, 5, "abcdefghijk");
printf("n %d buf %s\n", ret, buf);
运行结果为:
n 10 buf abcd
注意这个结果,只输出了abcd,长度为4,不是期待的5,没有输出 e ,说明snprintf函数最后自动加上去的’\0’,是算在size内部的,是格式
化字符串的总长度(不包括’\0’),这里使用sizeof(buf)时需要注意+1,这一点与malloc申请空间类似。
总结:
1.snprintf 会自动在格式化后的字符串尾添加\0,结尾符是包含在size长度内部的。
2.snprintf 会在结尾加上\0,不管buf空间够不够用,所以不必担心缓冲区溢出。
3.snprintf 的返回值n,当调用失败时,n为负数,当调用成功时,n为格式化的字符串的总长度(不包括\0),当然这个字符串有可能被截
断,因为buf的长度不够放下整个字符串。
#include <stdio.h>
int vsnprintf(char* str, size_t size, const char* format, va_list ap);
参数说明
char *str [out],把生成的格式化的字符串存放在这里.
size_t size [in], str可接受的最大字符数 [1] (非字节数,UNICODE一个字符两个字节),防止产生数组越界.
const char *format [in], 指定输出格式的字符串,它决定了你需要提供的可变参数的类型、个数和顺序。
va_list ap [in], va_list变量. va:variable-argument:可变参数
函数功能:将可变参数格式化输出到一个字符数组。
用法类似于vsprintf,不过加了size的限制,防止了内存溢出(size为str所指的存储空间的大小)。
返回值:执行成功,返回最终生成字符串的长度,若生成字符串的长度大于size,则将字符串的前size个字符复制到str,同时将原串
的长度返回(不包含终止符);执行失败,返回负值,并置errno. [2]
备注:
linux环境下是:vsnprintf
VC6环境下是:_vsnprintf