-
数据流(stream): 程序与数据交互的方式 C语言可以读写文本文件(
.txt
)与二进制文件(.bytes
)FILE *file = NULL; file = fopen("./rua.txt","w+"); fclose(file);
-
fopen
的参数? “r”:以只读的形式打开文本文件(不存在则出错) “w”:以只写的形式打开文本文件(不存在则新建,覆盖已有文件) “a”:以追加的形式打开文本文件(不存在则新建,指针固定在末尾)- 附加值: “+”:可读可写 “t”:txt文件(文本文件,默认可忽略) “b”:bytes文件(二进制文件,须写) ·
-
输入与输出 C语言中将所有交互的设备(显示器、键盘等)都当作“文件” 输入 与 输出 的概念是相对于程序而言的 例如:
printf()
的主要功能是向标准输出按规定格式输出信息scanf()
的主要功能是从标准输入按规定格式输入(读取)信息 在C语言的文件读写中,我们主要使用以下几个输入与输出函数 ·
- 输出
- 1.
fputc()
和fputs()
FILE *file = NULL; file = fopen("./rua.txt","w+"); fputc('a',file); fputs("ywwuyi",file); //文件内容: aywwuyi
- 2.
fprintf
FILE *file = NULL; file = fopen("./rua.txt","w+"); fprintf(file,"%s","ywwuyi"); //文件内容: ywwuyi
- 1.
·
- 输入
-
1.
fgetc()
和fgets()
FILE *file = NULL; file = fopen("./rua.txt","r+"); char str[233];//可不可以用char * int a = fgetc(file);//注意返回值 printf("%c\n",a); fgets(str,10,file); puts(str); /*输出: 1 23456789y */
思考:为什么第二行不是
123456789y
或是23456789yw
? -
扩展: 关于
fgets()
fgets(str,10,stdin);
stdin
指标准输入(缓存),通常意义上可以理解为你的键盘 因此,不难理解,上述语句的意思为给str
输入一个字符串,长度保留为9 · -
2.
fscanf()
FILE *file = NULL; file = fopen("./rua.txt","w+"); char str[233]; fprintf(file,"%s","Ywwuyi rua Mr.quin."); rewind(file);//这是什么? fscanf(file,"%s",str); puts(str); //输出: Ywwuyi
-
·
- 文件中定位
- 1.
rewind()
定义:将文件内部指针重新指向文件(流)开头FILE *file = NULL; file = fopen("./rua.txt","w+"); char str[233]; fprintf(file,"%s","Ywwuyi rua Mr.quin."); rewind(file);//① fscanf(file,"%s",str); puts(str); rewind(file);//② fprintf(file,"%s","233333"); rewind(file);//③ fscanf(file,"%s",str); puts(str);
- 2.
fseek()
定义:按照给定参数将文件内部指针指向文件(流)指定位置int fseek(FILE *stream, long int offset, int whence)
offset
指偏移量,即相对于whence
移动多少位置,负号前移,正号后移whence
指文件内的位置,通常为以下三个参数实例:SEEK_SET 文件的开头 SEEK_CUR 文件内指针当前位置 SEEK_END 文件的末尾
FILE *file = NULL; file = fopen("./rua.txt","w+"); char str[233]; fprintf(file,"%s","Ywwuyi rua Mr.quin."); fseek(file,0,SEEK_SET);//等价于rewind(file) fscanf(file,"%s",str); puts(str); fseek(file,1,SEEK_CUR); fscanf(file,"%s",str); puts(str); fseek(file,-8,SEEK_END); fscanf(file,"%s",str); puts(str); /*输出: Ywwuyi rua Mr.quin. */
- 1.
大程序结构 含有多个源代码文件(C语言中为 .c) 每个源代码文件为一个编译单元 完成编译单元间的交互,需要链接器。 在诸如VS与DevC++的IDE(集成开发环境)中“创建项目”时便自带链接器 一般情况下,将多个.c文件放于同一个文件夹下面 在VScode中实现链接器的功能比较繁琐,因此此处用VS作工具说明 下面细嗦如何实现多文件的操作。 ·
-
跨文件调用变量 main.c
#include <stdio.h> extern int a; int main() { printf("%d", a); return 0; }
rua.c
#include <stdio.h> int a = 6;
输出:
6
- 注意点:
extern
关键字修饰变量的作用 ·
- 注意点:
-
跨文件调用函数 main.c
void rua1(); void rua2(); int main() { rua1(); rua2(); return 0; }
ywwuyi.c
#include <stdio.h> void rua1() { puts("ywwuyi"); }
awsl.c
#include <stdio.h> void rua1(); void rua2() { puts("awsl"); rua1(); }
输出:
ywwuyi awsl ywwuyi
- 思考:函数的原型,为什么不需要
extern
关键字? ·
- 思考:函数的原型,为什么不需要
-
-
extern
关键字 一般用作 声明 变量/函数 定义 全局变量/函数 时自带这个关键字 多文件程序中,extern
使不同文件可以共用一个全局变量 -
static
关键字 一般用作 定义 变量/函数 生命周期从整个程序开始到结束(全局与局部) 静态局部变量的作用域限制在代码块内 静态全局变量的作用域限制在编译单元内 多文件程序中,static
使不同文件中可以定义同名事物 main.c#include <stdio.h> void rua(); static int a = 233; int main() { rua(); printf("%d\n", a); return 0; }
ywwuyi.c
#include <stdio.h> static int a = 1551; void rua() { printf("%d ", a); }
输出:1551 233 ·
-
-
将函数的原型放到头文件(
.h
文件)中, 便可以在需要调用这些函数的编译单元中#include
该头文件, 来让编译器在编译的时候知道这些函数的原型。 ·ywwuyi.c
与awsl.c
同上main.c
#include "rua.h" int main() { rua1(); rua2(); return 0; }
rua.h
void rua1(); void rua2();
输出: 同上 ·
- 注意点: 一般来说,
.h
文件用来放置声明。
实际上,
#include
所做的事情是将该文件的所有文本原封不动地插入到该处位置 因此,#include
并非是用来引入库文件的,stdio.h
中仅含有函数的原型stdio.h
具体的函数定义在另外的地方,而现代C编译器则会默认引入所有的标准库 · - 注意点: 一般来说,
-
思考:
extern int a
与extern int a = 0
的区别?extern int a
为 变量的声明extern int a = 0
为 变量的定义 声明 不另外分配任何内存空间 此处所述的函数原型也是一种声明。 只定义不声明的行为会遭到编译器指指点点× 只声明不定义的行为会遭到编译器重拳出击× ·- 重复声明
main.c
rua.h
#include "rua.h" void rua1();//函数rua1()被重复声明 extern int a;//变量a被重复声明 int main() { rua1(); rua2(); return 0; }
编译通过,说明可以重复声明 ·void rua1(); void rua2(); extern int a;
- 重复定义
main.c
rua.h
#include "rua.h" #include "yyds.h"
yyds.hint a;
编译不通过,说明不可重复定义 ·#include "rua.h"
- 标准头文件结构 ——「重复定义の解决方法」
怎么解决重复定义的问题?
- 鳖在
.h
文件里面定义! 写.h
时鳖重复! (实际编程的时候其实经常碰到.h
里面include
另外一个.h
的情况) - 把
int a;
改成extern int a
,即改为 声明a
变量 然后在某个文件里进行定义 - 上面那些不好用,来搞点新东西!
rua.h
或者 rua.h
#ifndef _RUA_H_ #define _RUA_H_ int a; #endif
以上对#pragma once int a;
.h
文件的预处理使其成为 标准头文件 - 注意点: 以上预处理仅在同一个编译单元中起作用
实际在不同文件中
int a;(全局)
仍然会出现错误 ·
- 鳖在
- 重复声明
main.c