读取文本文件
void main(){
char *path = "J:\\User.xml";
//打开
FILE *fp =fopen(path, "r");
if (fp == NULL){
printf("文件打开失败");
return;
}
//读取s
char buff[50];//缓冲
while (fgets(buff, 50, fp)){
printf("%s", buff);
}
fclose(fp);
getchar();
}
写入文本文件
void main(){
char * path = "J:\\hello.txt";
FILE *fp = fopen(path, "w");
char *text = "2018年9月12日 21:17:44";
fputs(text, fp);
fclose(fp);
getchar();
}
计算机的文件存储在物理上都是二进制
文本文件和二进制之分,其实是一个逻辑之分
C读写文本文件与二进制文件的差别仅仅体现在回车换行符
写文本时,每遇到一个'\n',会将其转换成'\r\n'(回车换行)
读文本时,每遇到一个'\r\n',会将其转换成'\n'
文件复制
void main(){
char *readPath = "J:\\1.jpg";
char *writePath = "J:\\2.jpg";
//r读的文件 b字符表示操作二进制文件binary
FILE *read_fp = fopen(readPath, "rb");
//写的文件
FILE * write_fp = fopen(writePath, "wb");
//复制
int buff[50]; //缓冲区域
int len = 0; //每次读到的数据长度
while ((len = fread(buff, sizeof(int), 50, read_fp)) != 0){
//将读到的内容写入新的文件
fwrite(buff, sizeof(int), len, write_fp);
}
//关闭流
fclose(read_fp);
fclose(write_fp);
getchar();
}
获取文件的大小
void main(){
char *read_path = "J:\\1.jpg";
FILE *fp = fopen(read_path, "r");
//重新定位文件指针
//SEEK_END文件末尾,0偏移量
fseek(fp, 0, SEEK_END);
//返回当前的文件指针,相对于文件开头的位移量
long filesize = ftell(fp);
printf("%d\n", filesize);
getchar();
}
预编译
c语言执行的流程
- 编译:形成目标代码(.obj)。
- 连接:将目标代码与c函数库链接合并,连接器负责找到这个函数的实现,形成最终的可执行文件。
- 执行
宏定义
定义标识
#ifdef __cplusplus 标识支持C++语法
可以解决互相引入问题
A.h
A.h头文件引入B.h头文件
#include "B.h"
void printfA();
B.h
B.h头文件又引入A.h头文件
#include "A.h"
void printfB();
c1.c
#include <stdio.h>
#include<stdlib.h>
#include "A.h"
void printfA(){
printf("Hello printfA");
}
void main(){
printfA();
getchar();
}
这里会报 error C1014: 包含文件太多 : 深度 = 1024,这是因为A.h和B.h循环引入导致的错误。
可以通过定义标识解决该问题。
A.h
#ifndef AH
#define AH
#include "B.h"
void printfA();
#endif
B.h
#ifndef BH
#define BH
#include "A.h"
void printfB();
#endif
tip:这里有更加简单的写法
A.h
//该头文件只被包含一次,让编译器自定处理好循环包含问题
#pragma once
#include "B.h"
void printfA();
B.h
#pragma once
#include "A.h"
void printfB();
定义常数
#define PI 3.14
定义宏函数
#include <stdio.h>
#include<stdlib.h>
//定义读写两个函数
void file_read(){
printf("file_read \n");
}
void file_write(){
printf("file_write \n");
}
//定义宏函数,OPERATE代表参数
//当函数很长的时候可以使用宏函数缩短函数的名称
#define file(OPERATE) file_##OPERATE();
void main(){
//输出file_read,等于执行file_read函数
file(read);
//输出file_write,等于执行file_write函数
file(write);
getchar();
}
除了可以像上面替换函数名之外,还可以传参数到宏函数中。以输出日志为例:
#include <stdio.h>
#include<stdlib.h>
//LEVEL 是日志的级别
//FORMAT是数据格式化的方式,使用的时候用 ##FORMAT代替
//... 代表可变参数,使用的时候用__VA_ARGS__ 代替
#define LOG(LEVEL,FORMAT,...) printf(##LEVEL);printf(##FORMAT,__VA_ARGS__);
#define LOG_I(FORMAT,...) LOG("INFO:",##FORMAT,__VA_ARGS__);
#define LOG_W(FORMAT,...) LOG("WARING",##FORMAT,__VA_ARGS__);
#define LOG_E(FORMAT,...) LOG("ERROR",##FORMAT,__VA_ARGS__);
void main(){
LOG_I("%s%s", "大小:", "89 \n");
LOG_W("%s%s", "大小:", "89 \n");
LOG_E("%s%s", "大小:", "89 \n");
getchar();
}