热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

C语言文件看这一篇就够了

码字不易,对你有帮助点赞转发关注支持一下作者微信搜公众号:不会编程的程序圆看更多干货,获取第一时间更新想看更好排版,可以看原

码字不易,对你有帮助 点赞/转发/关注 支持一下作者
微信搜公众号:不会编程的程序圆
看更多干货,获取第一时间更新

想看更好排版,可以看原文
点击看原文

本节思维导图

文件


格式化的输入输出


printf
% [flag] [width] [.prec] [hlL] type
scanf
% [flag] type


printf

flag 属性一般与 width 属性结合

Flag含义
-左对齐
+在正数放 +
0在前面填充 0

例1

int main(void) {printf("%9d\n", 123);printf("%-9d\n", 123);return 0;
}

123
123

例2

int main(void) {printf("%+9d\n", 123);printf("%-9d\n", -123);return 0;
}

+123
-123

+ 可以让正数打印出符号,负数的符号自动会打印出来

例3

int main(void) {printf("%+09d\n", 123);printf("%-09d\n", -123);return 0;
}

+00000123
-123

*有的编译器不允许 - 0*这样的语法,因为 - 已经表示左对齐了,0 就没有意义了

width.prec

width.prec含义
number . number总共的输出占几位 . 小数点后占几位
*.*下一个参数是字符数或小数点后的位数

例1

int main(void) {printf("%9.2f\n", 12.3);printf("%8.4f\n", -12.3);return 0;
}

12.30
-12.3000

例2:融合一下

int main(void) {printf("%+09.2f\n", 12.3);printf("%-8.3f\n", -12.3);return 0;
}

+00012.30
-12.300

小数点 . 也是占位数的

例3:

int main(void) {int len = 5;int dec = 2;printf("%*.*f\n",5, 2, 12.3);printf("%*.*f\n",len, dec, 12.3);return 0;
}

12.30
12.30

给了我们用参数控制格式的途径,可以用变量来改变输出的格式

hlL 格式

修饰类型含义
hh单个字节
hshort
llong
lllong long
Llong double

int main(void) {printf("%hhd\n", (char)12345);//当作 1 个字节输出(最低为作为 char 输出)printf("%hd\n", 12345);//当作 short 输出return 0;
}

12345 的 16 进制数是:3039
39 的十进制是 57

57
12345

格式

type表示type表示
i&dintgfloat
uunsigned intGfloat
o八进制a&A十六进制浮点
x十六进制cchar
X大写的十六进制s字符串
f&Ffloatp指针
e&E指数n读入/写出的个数

scanf :% [flag] type

flag 属性

flag含义
*跳过
数字最大字符数
hhchar
hshort
llong ,double
lllong long
Llong double

例:

int main() {int num;scanf("%*d %d", &num);printf("%d\n", num);return 0;
}

程序输出如下:
输入:123 456

456

type属性

type用于
dint
i整数(10进制,8进制或16进制)
uunsigned int
o八进制
x十六进制
a,e,f,gfloat
cchar
s字符串
[…]允许的字符
p指针

printf 与 scanf 的返回值


scanf:读入的项目(item)数
printf: 输出的字符数

有什么用?
再由严格要求的程序中,应该判断每次调用 scanf 或 printf 的返回值,从而了解运行中的程序是否出现了问题

例如:

int main(void) {int num = 0;int return_scanf = 0;int return_printf = 0;return_scanf = scanf("%d", &num);return_printf = printf("%d\n", num);printf("%d:%d\n", return_scanf, return_printf);return 0;
}

//输入
1234
//输出
1234
1:5 //回车键要算进去

文件输入输出

<与 > 来重定向

  • <重定向输入
  • > 重定向输出

我们用 linux 操作系统为例&#xff1a;

1.写一个c文件并完成编译


2.这是标准的输入输出


3.我们先创建一个文件 read.out&#xff0c;并写入 1234


4.用 read.out 作为输入&#xff0c;向 write.out 中写入程序运行结果


用程序打开文件

fopen


FILE *fopen( const char *filename, const char *mode );(C99 前)
FILE *fopen( const char *restrict filename, const char *restrict mode );(C99 起)
头文件&#xff1a;stdio.h
参数&#xff1a;
filename - 关联到文件系统的文件名
mode - 确定访问模式的空终止字符串
返回值&#xff1a;
若成功&#xff0c;则返回指向新文件流的指针。流为完全缓冲&#xff0c;除非 filename 表示一个交互设备。错误时&#xff0c;返回空指针


简单理解

r打开只读
r&#43;打开读写&#xff0c;从文件头开始
w打开只写。如果不存在则新建&#xff0c;如果存在就清空
w&#43;打开读写。如果不存在则新建&#xff0c;如果存在清空
a打开追加。如果不存在则新建&#xff0c;如果存在则从文件尾开始追加
x后附于上面。表示如果文件已存在则不能打开

fclose


int fclose( FILE *stream )
**头文件&#xff1a;**stdio.h
参数&#xff1a;
stream - 需要关闭的文件流
返回值&#xff1a;
成功时为 ​0​ &#xff0c;否则为 EOF 。


定义&#xff1a;
关闭给定的文件流。冲入任何未写入的缓冲数据到 OS 。舍弃任何未读取的缓冲数据。

无论操作是否成功&#xff0c;流都不再关联到文件&#xff0c;且由 setbuf 或 setvbuf 分配的缓冲区若存在&#xff0c;则亦被解除关联&#xff0c;并且若使用自动分配则被解分配。

若在 fclose 返回后使用指针 stream 的值则行为未定义。


scanf系


·int scanf( const char *format, ... );​(C99 前)

​int scanf( const char *restrict format, ... );​(C99 起)
(2)
int fscanf( FILE *stream, const char *format, ... );(C99 前)

int fscanf( FILE *restrict stream, const char *restrict format, ... );(C99 起)
(3)
int sscanf( const char *buffer, const char *format, ... );(C99 前)

int sscanf( const char *restrict buffer, const char *restrict format, ... );(C99 起)
定义
从各种资源读取数据&#xff0c;按照 format 转译&#xff0c;并将结果存储到指定位置。

  1. 从 stdin 读取数据

  2. 从文件流 stream 读取数据

  3. 从空终止字符串 buffer 读取数据。抵达字符串结尾等价于 fscanf 的抵达文件尾条件

参数&#xff1a;
stream - 要读取的输入文件流

buffer - 指向要读取的空终止字符串的指针

format - 指向指定读取输入方式的空终止字符串的指针。

返回值&#xff1a;
成功赋值的接收参数的数量&#xff08;可以为零&#xff0c;在首个接收用参数赋值前匹配失败的情况下&#xff09;&#xff0c;者若输入在首个接收用参数赋值前发生失败&#xff0c;则为EOF。


printf系


头文件&#xff1a; stdio.h
(1)
int printf( const char *format, ... )​(C99 前)

​int printf( const char *restrict format, ... );​(C99 起)

(2)

int fprintf( FILE *stream, const char *format, ... );(C99 前)

int fprintf( FILE *restrict stream, const char *restrict format, ... );(C99 起)

(3)

int sprintf( char *buffer, const char *format, ... );(C99 前)

int sprintf( char *restrict buffer, const char *restrict format, ... );(C99 起)

(4)

int snprintf( char *restrict buffer, int bufsz, const char *restrict format, ... );(C99 起)

定义&#xff1a;
从给定位置加载数据&#xff0c;转换为字符串等价物&#xff0c;并写结果到各种池。

  1. 写结果到 stdout 。

  2. 写结果到文件流 stream 。

  3. 写结果到字符串 buffer 。

  4. 写结果到字符串 buffer 。至多写 buf_size - 1 个字符。产生的字符串会以空字符终止&#xff0c;除非 buf_size 为零。若 buf_size 为零&#xff0c;则不写入任何内容&#xff0c;且 buffer 可以是空指针&#xff0c;然而依旧计算返回值&#xff08;会写入的字符数&#xff0c;不包含空终止符&#xff09;并返回。

参数&#xff1a;
stream - 要写入的输出文件流

buffer - 指向要写入的字符串的指针

bufsz - 最多会写入 bufsz - 1 个字符&#xff0c;再加空终止符

format - 指向指定数据转译方式的空终止多字节字符串的指针。

返回值&#xff1a;
1,2) 传输到输出流的字符数&#xff0c;或若出现输出错误或编码错误&#xff08;对于字符串和字符转换指定符&#xff09;则为负值。

  1. 写入到 buffer 的字符数&#xff08;不计空终止字符&#xff09;&#xff0c;或若输出错误或编码错误&#xff08;对于字符串和字符转换指定符&#xff09;发生则为负值。

  2. 假如忽略 bufsz 则本应写入到 buffer 的字符数&#xff08;不计空终止字符&#xff09;&#xff0c;或若出现输出错误或编码错误&#xff08;对于字符串和字符转换指定符&#xff09;则为负值。


标准代码&#xff1a;

FILE* fp &#61; fopen("file", "r");if (fp) {fscanf(fp, ...);fclose(fp);
}
else {...
}

例&#xff1a;
写一个c程序
测试

二进制文件


fread

size_t fread( void *restrict buffer, size_t size, size_t count, FILE *restrict stream );
定义于头文件
参数&#xff1a;
buffer - 指向要读取的数组中首个对象的指针
size - 每个对象的字节大小
count - 要读取的对象数
stream - 读取来源的输入文件流
返回值&#xff1a;
成功读取的对象数&#xff0c;若出现错误或文件尾条件&#xff0c;则可能小于 count 。
若 size 或 count 为零&#xff0c;则 fread 返回零且不进行其他动作。
fread 不区别文件尾和错误&#xff0c;而调用者必须用 feof 和 ferror 鉴别出现者为何。


定义&#xff1a;
从给定输入流 stream 读取至多 count 个对象到数组 buffer 中&#xff0c;如同以对每个对象调用 size 次 fgetc &#xff0c;并按顺序存储结果到转译为 unsigned char 数组的 buffer 中的相继位置。流的文件位置指示器前进读取的字符数。
若出现错误&#xff0c;则流的文件位置指示器的结果值不确定。若读入部分的元素&#xff0c;则元素值不确定。

直白点说就是从 一个流&#xff08;文件&#xff09;种读取 count 个 size 大小 的对象到 buffer 数组中

成功返回读取的对象数( <&#61; count), 失败返回 0

fwrite

size_t fwrite( const void *restrict buffer, size_t size, size_t count, FILE *restrict stream );
定义于头文件
参数&#xff1a;
buffer - 指向数组中要被写入的首个对象的指针
size - 每个对象的大小
count - 要被写入的对象数
stream - 指向输出流的指针
返回值&#xff1a;
成功写入的对象数&#xff0c;若错误发生则可能小于 count 。
若 size 或 count 为零&#xff0c;则 fwrite 返回零并不进行其他行动。


定义
写 count 个来自给定数组 buffer 的对象到输出流stream。如同转译每个对象为 unsigned char 数组&#xff0c;并对每个对象调用 size 次 fputc 以将那些 unsigned char 按顺序写入 stream 一般写入。文件位置指示器前进写入的字节数。


程序演示

现在我们想将学生的信息以二进制文本写入到 student.data 文件中

应该如何写这个程序呢&#xff1f;

关注公众号: 不会编程的程序圆 回复[0212 1]
获取程序演示以及程序的详细注释&#xff01;

ftell


long ftell( FILE *stream );
定义于头文件
参数&#xff1a;stream - 要检验的文件流
返回值&#xff1a;
成功时为文件位置指示器&#xff0c;若失败发生则为 -1L 。
失败时&#xff0c;设 errno 对象为实现定义的正值。


定义&#xff1a;
返回流 stream 的文件位置指示器。
若流以二进制模式打开&#xff0c;则由此函数获得的值是从文件开始的字节数。
若流以文本模式打开&#xff0c;则由此函数返回的值未指定&#xff0c;且仅若作为 fseek() 的输入才有意义。


fseek


int fseek( FILE *stream, long offset, int origin );
定义于头文件
参数&#xff1a;
stream - 要修改的文件流
offset - 相对 origin 迁移的字符数
origin - offset 所加上的位置。它能拥有下列值之一&#xff1a; SEEK_SET 、 SEEK_CUR 、 SEEK_END
返回值&#xff1a;
成功时为 ​0​ &#xff0c;否则为非零。


定义&#xff1a;
设置文件流 stream 的文件位置指示器为 offset 所指向的值。

若 stream 以二进制模式打开&#xff0c;则新位置准确地是文件起始后&#xff08;若 origin 为 SEEK_SET &#xff09;或当前文件位置后&#xff08;若 origin 为 SEEK_CUR &#xff09;&#xff0c;或文件结尾后&#xff08;若 origin 为 SEEK_END &#xff09;的 offset 字节。不要求二进制流支持 SEEK_END &#xff0c;尤其是是否输出附加的空字节。

若 stream 以文本模式打开&#xff0c;则仅有的受支持 offset 值为零&#xff08;可用于任何 origin &#xff09;和先前在关联到同一个文件的流上对 ftell 的调用的返回值&#xff08;仅可用于 SEEK_SET 的 origin &#xff09;。

若 stream 为宽面向&#xff0c;则一同应用对文本和二进制流的限制&#xff08;允许 ftell 的结果与 SEEK_SET 一同使用&#xff0c;并允许零 offset 以 SEEK_SET 和 SEEK_CUR 但非 SEEK_END 为基准&#xff09;。

除了更改文件位置指示器&#xff0c; fseek 还撤销 ungetc 的效果并清除文件尾状态&#xff0c;若可应用。

若发生读或写错误&#xff0c;则设置流的错误指示器&#xff08; ferror &#xff09;而不影响文件位置。


SEEK_SET 从头开始
SEEK_CUR 从当前位置开始
SEEK_END 从尾开始

简单的理解&#xff1a;将 stream 指针&#xff0c;从 origin 开始&#xff0c;移动 offset 个字节

比如&#xff1a;fseek(fp, 100L, SEEK_SET)

它的意义时&#xff0c;将 fp 指针从 文件头开始移动100个字节

程序演示

上面一个程序我们将学生信息以二进制形式写入到了 student.data 文件中

如何打开这个二进制文件呢&#xff1f;

关注公众号: 不会编程的程序圆 回复[0212 1]
获取程序演示以及程序的详细注释&#xff01;

可移植性

这一节&#xff0c;我们看了到各种比较复杂的函数&#xff0c;

fprintf fscanf sprintf fopen fclose fread fwrite

我们也看到了文本文件的一些操作和二进制文件比较复杂的读写&#xff0c;而且你也不能直接从windows 上读我们到底以二进制的形式向文件内写了什么

这样的二进制文件不具备可移植性&#xff0c;因为在int 为32为的机器上写成的数据文件无法直接在int为64位的机器上正确读出

解决方案之一是放弃使用int&#xff0c;用typedef具有明确大小的类型

更好的方案是用文本

时至今日&#xff0c;我们已经很少用c语言这种最底层的文件读写方式了&#xff0c;要么用数据库&#xff0c;要么用第三方库

参考网站&#xff1a;https://zh.cppreference.com/



在 Github 上看更全的目录&#xff1a;

https://github.com/hairrrrr/C-CrashCourse

以后的这个系列的代码都会上传上去&#xff0c;欢迎 star



以上就是本次的内容。

如果文章有错误欢迎指正和补充&#xff0c;感谢&#xff01;

最后&#xff0c;如果你还有什么问题或者想知道到的&#xff0c;可以在评论区告诉我呦&#xff0c;我可以在后面的文章加上你们的真知灼见​​。

关注我&#xff0c;看更多干货&#xff01;

我是程序圆&#xff0c;我们下次再见。


推荐阅读
  • 一文了解Python collections模块中的deque用法[python头条资讯]
    Python中文网有大量免费的Python入门教程,欢迎大家来学习。collections是Python内建的一个集合模块,deque是双边队列,具有队列和栈的性质,在list的基 ... [详细]
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 本文介绍了在Linux下安装Perl的步骤,并提供了一个简单的Perl程序示例。同时,还展示了运行该程序的结果。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • Linux磁盘的分区、格式化的观察和操作步骤
    本文介绍了如何观察Linux磁盘的分区状态,使用lsblk命令列出系统上的所有磁盘列表,并解释了列表中各个字段的含义。同时,还介绍了使用parted命令列出磁盘的分区表类型和分区信息的方法。在进行磁盘分区操作时,根据分区表类型选择使用fdisk或gdisk命令,并提供了具体的分区步骤。通过本文,读者可以了解到Linux磁盘分区和格式化的基本知识和操作步骤。 ... [详细]
  • Android JSON基础,音视频开发进阶指南目录
    Array里面的对象数据是有序的,json字符串最外层是方括号的,方括号:[]解析jsonArray代码try{json字符串最外层是 ... [详细]
  • 本文探讨了C语言中指针的应用与价值,指针在C语言中具有灵活性和可变性,通过指针可以操作系统内存和控制外部I/O端口。文章介绍了指针变量和指针的指向变量的含义和用法,以及判断变量数据类型和指向变量或成员变量的类型的方法。还讨论了指针访问数组元素和下标法数组元素的等价关系,以及指针作为函数参数可以改变主调函数变量的值的特点。此外,文章还提到了指针在动态存储分配、链表创建和相关操作中的应用,以及类成员指针与外部变量的区分方法。通过本文的阐述,读者可以更好地理解和应用C语言中的指针。 ... [详细]
  • imx6ull开发板驱动MT7601U无线网卡的方法和步骤详解
    本文详细介绍了在imx6ull开发板上驱动MT7601U无线网卡的方法和步骤。首先介绍了开发环境和硬件平台,然后说明了MT7601U驱动已经集成在linux内核的linux-4.x.x/drivers/net/wireless/mediatek/mt7601u文件中。接着介绍了移植mt7601u驱动的过程,包括编译内核和配置设备驱动。最后,列举了关键词和相关信息供读者参考。 ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
author-avatar
倚栏听风
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有