C语言重难点
文章平均质量分 76
精选出C语言中的重点和难点知识,并进行深入分析讲解。内容来自C语言中文网。
happy 天堂
这个作者很懒,什么都没留下…
展开
-
第十四章 C语言头文件的编写_C语言static变量和函数
我们知道,全局变量和函数的作用域默认是整个程序,也就是所有的源文件,这给程序的模块化开发带来了很大方便,让我们能够在模块 A 中调用模块 B 中定义的变量和函数,而不用把所有的代码都集中到一个模块。但这有时候也会引发命名冲突的问题,例如在 a.c 中定义了一个变量 n,在 b.c 中又定义了一次,链接时就会发生重复定义错误,原因很简单,变量只能定义一次。如果两个文件都是我们自己编写的或者其中一个是,遇到这样的情况还比较好处理,修改变量的名字即可;如果两个文件都是其他程序员编写的,或者是第三方的库,修改起原创 2022-03-04 10:24:41 · 686 阅读 · 0 评论 -
第十四章 C语言头文件的编写_防止C语言头文件被重复包含
头文件包含命令 #include 的效果与直接复制粘贴头文件内容的效果是一样的,预处理器实际上也是这样做的,它会读取头文件的内容,然后输出到 #include 命令所在的位置。头文件包含是一个递归(循环)的过程,如果被包含的头文件中还包含了其他的头文件,预处理器会继续将它们也包含进来;这个过程会一直持续下去,直到不再包含任何头文件,这与递归的过程颇为相似。递归包含会导致一个问题,就是重复引入同一个源文件。例如在某个自定义头文件 xyz.h 中声明了一个 FILE 类型的指针,以使得所有的模块都能使用它,原创 2022-03-04 10:24:34 · 470 阅读 · 0 评论 -
第十四章 C语言头文件的编写_C语言标准库以及标准头文件
我们常说,引入编译器自带的头文件(包括标准头文件)用尖括号,引入程序自定义的头文件用双引号,例如:使用尖括号< >,编译器会到系统路径下查找头文件;而使用双引号" ",编译器首先在当前目录下查找头文件,如果没有找到,再到系统路径下查找。也就是说,使用双引号比使用尖括号多了一个查找路径,它的功能更为强大,我们完全可以使用双引号来包含标准头文件,例如:使用尖括号< >,编译器会到系统路径下查找头文件;而使用双引号" ",编译器首先在当前目录下查找头文件,如果没有找到,原创 2022-03-04 10:24:28 · 2452 阅读 · 0 评论 -
第十四章 C语言头文件的编写_C语言标准库以及标准头文件
源文件通过编译可以生成目标文件(例如 GCC 下的 .o 和 Visual Studio 下的 .obj),并提供一个头文件向外暴露接口,除了保护版权,还可以将散乱的文件打包,便于发布和使用。实际上我们一般不直接向用户提供目标文件,而是将多个相关的目标文件打包成一个静态链接库(Static Link Library),例如 Linux 下的 .a 和 Windows 下的 .lib。打包静态库的过程很容易理解,就是将多个目标文件捆绑在一起形成一个新的文件,然后再加上一些索引,方便链接器找到,这和压缩文件原创 2022-03-04 10:24:20 · 2185 阅读 · 0 评论 -
第十四章 C语言头文件的编写_C语言模块化编程中的头文件
前面我们在演示多文件编程时创建了main.c 和 module.c 两个源文件,并在 module.c 中定义了一个函数和一个全局变量,然后在 main.c 中进行了声明。不过实际开发中很少这样做,一般是将函数和变量的声明放到头文件,再在当前源文件中 #include 进来。如果变量的值是固定的,最好使用宏来代替。下面的例子是改进后的代码。main.c 源码:module.c 源码:module.h 源码:在 Visual Studio 中,将上面的文件全部添加到工程,点击“..原创 2022-03-04 10:24:53 · 2277 阅读 · 0 评论 -
第十四章 C语言头文件的编写_到底什么是链接,它起到了什么作用?
编译器编译源代码后生成的文件叫做目标文件(Object File),例如 Visual Studio 下的.obj,或者 GCC 下的.o。从文件结构上来讲,目标文件已经是二进制文件,它与可执行文件的组织形式非常类似,只是有些变量和函数的地址还未确定,程序不能执行。链接的一个重要作用就是找到这些变量和函数的地址。另外需要明确的是:编译是针对单个源文件的,有几个源文件就会生成几个目标文件,并且在生成过程中不受其他源文件的影响。也就是说,不管当前工程中有多少个源文件,编译器每次只编译一个源文件、生成一个目标原创 2022-03-03 16:54:52 · 627 阅读 · 0 评论 -
第十四章 C语言头文件的编写_那些被编译器隐藏了的过程
对于平常应用程序的开发,很少有人会关注编译和链接的过程,因为我们使用的工具一般都是流行的集成开发环境(IDE),比如 Visual Studio、Dev C++、C-Free 等。这些功能强大的 IDE 通常将编译和链接合并到一起,也就是构建(Build)或运行(Run)。即使在 Linux 下使用命令行来编译一个源文件,简单的一句$gcc demo.c也包含了非常复杂的过程。虽然 IDE 提供的默认配置、编译和链接参数对于大部分应用程序来说已经足够使用了,但是作为学习者,我们还是要刨根问底,弄清从源代码原创 2022-03-03 16:54:44 · 535 阅读 · 0 评论 -
第十四章 C语言头文件的编写_从extern关键字开始谈C语言多文件编程
多文件编程就是把多个头文件(.h文件)和源文件(.c文件)组合在一起构成一个程序,这是C语言的重点,也是C语言的难点。C语言头文件的编写是其中的重点内容,有很多细节需要注意,有的甚至会让你感觉奇怪。多文件编程既涉及到了内存,也涉及到了编译原理,市面上的绝大部分资料对此也语焉不详,所以很多初学者对此都非常困惑。学会了多文件编程,你就可以使用C语言来开发中大型项目了,对初学者来说,这简直是跨域了一大步。在前面的教程中,我们都是将所有的代码写到一个源文件里面,对于小程序,代码不过几百行,这或许无可厚非原创 2022-03-03 16:54:36 · 902 阅读 · 0 评论 -
第十三章 C语言内存精讲_C语言变量的存储类别和生存期
我们知道,变量是有数据类型的,用以说明它占用多大的内存空间,可以进行什么样的操作。除了数据类型,变量还有一个属性,称为“存储类别”。存储类别就是变量在内存中的存放区域。在进程的地址空间中,常量区、全局数据区和栈区可以用来存放变量的值。常量区和全局数据区的内存在程序启动时就已经由操作系统分配好,占用的空间固定,程序运行期间不再改变,程序运行结束后才由操作系统释放;它可以存放全局变量、静态变量、一般常量和字符串常量。栈区的内存在程序运行期间由系统根据需要来分配(使用到变量才分配内存;如果定义了变量但没有执原创 2022-03-03 16:54:29 · 373 阅读 · 0 评论 -
第十三章 C语言内存精讲_C语言内存泄露(内存丢失)
使用 malloc()、calloc()、realloc() 动态分配的内存,如果没有指针指向它,就无法进行任何操作,这段内存会一直被程序占用,直到程序运行结束由操作系统回收。请看下面的代码:该程序中,第一次分配 100 字节的内存,并将 p 指向它;第二次分配 50 字节的内存,依然使用 p 指向它。这就导致了一个问题,第一次分配的 100 字节的内存没有指针指向它了,而且我们也不知道这块内存的地址,所以就再也无法找回了,也没法释放了,这块内存就成了垃圾内存,虽然毫无用处,但依然占用资源,唯一原创 2022-03-03 16:54:22 · 869 阅读 · 0 评论 -
第十三章 C语言内存精讲_C语言野指针以及非法内存操作
如果一个指针指向的内存没有访问权限,或者指向一块已经释放掉的内存,那么就无法对该指针进行操作,这样的指针称为野指针(Wild Pointer)。指向没有访问权限的内存请看下面的代码:在GCC下运行,输入一个字符串后会提示段错误(Segment Fault)。在VS下运行,输入一个字符串后会提示类似下面的错误:这是因为,str 是局部变量,它的值是不确定的,是随机的,不知道指向哪块内存。一般情况下,这块内存要么没有访问权限,要么还没有分配,当 gets() 函数试图将读取到的字符原创 2022-03-03 16:54:14 · 394 阅读 · 0 评论 -
第十三章 C语言内存精讲_malloc函数背后的实现原理——内存池
相对于栈而言,堆这片内存面临着一个稍微复杂的行为模式:在任意时刻,程序可能发出请求,要么申请一段内存,要么释放一段已经申请过的内存,而且申请的大小从几个字节到几个GB都有可能,我们不能假设程序一次申请多少堆空间,因此,堆的管理显得较为复杂。那么,使用 malloc() 在堆上分配内存到底是如何实现的呢?一种做法是把 malloc() 的内存管理交给系统内核去做,既然内核管理着进程的地址空间,那么如果它提供一个系统调用,可以让 malloc() 使用这个系统调用去申请内存,不就可以了吗?当然这是一种理论上原创 2022-03-03 16:54:07 · 523 阅读 · 0 评论 -
第十三章 C语言内存精讲_C语言动态内存分配
在进程的地址空间中,代码区、常量区、全局数据区的内存在程序启动时就已经分配好了,它们大小固定,不能由程序员分配和释放,只能等到程序运行结束由操作系统回收。这称为静态内存分配。栈区和堆区的内存在程序运行期间可以根据实际需求来分配和释放,不用在程序刚启动时就备足所有内存。这称为动态内存分配。使用静态内存的优点是速度快,省去了向操作系统申请内存的时间,缺点就是不灵活,缺乏表现力,例如不能控制数据的作用范围,不能使用较大的内存。而使用动态内存可以让程序对内存的管理更加灵活和高效,需要内存就立即分配,而且需要多少原创 2022-03-03 16:53:59 · 533 阅读 · 0 评论 -
第十三章 C语言内存精讲_栈溢出攻击的原理是什么?
我们先来看下面的一个例子:在 main() 函数内部定义一个字符数组,并通过 gets() 为它赋值。在VS2010 Debug模式下运行程序,当输入的字符不超过10个时,可以正确输出,但是当输入的字符过多时,就会出现运行时错误。例如输入"12345678901234567890",就会出现下面的错误:这是为什么呢?我们不妨先来看一下 main() 函数的栈:局部数组也是在栈上分配内存,当输入"12345678901234567890" 时,会发生数组溢出,占用“4字节空白内存原创 2022-03-03 16:53:49 · 417 阅读 · 0 评论 -
第十三章 C语言内存精讲_栈(Stack)是什么?栈溢出又是怎么回事?
在《Linux下C语言程序的内存布局(内存模型)》中我们讲到,程序的虚拟地址空间分为多个区域,栈(Stack)是其中地址较高的一个区域。栈(Stack)可以存放函数参数、局部变量、局部数组等作用范围在函数内部的数据,它的用途就是完成函数的调用。栈内存由系统自动分配和释放:发生函数调用时就为函数运行时用到的数据分配内存,函数调用结束后就将之前分配的内存全部销毁。所以局部变量、参数只在当前函数中有效,不能传递到函数外部。栈的概念在计算机中,栈可以理解为一个特殊的容器,用户可以将数据依次放入栈中,然原创 2022-03-03 16:53:40 · 1047 阅读 · 1 评论 -
第十三章 C语言内存精讲_分页机制究竟是如何实现的?
现代操作系统都使用分页机制来管理内存,这使得每个程序都拥有自己的地址空间。每当程序使用虚拟地址进行读写时,都必须转换为实际的物理地址,才能真正在内存条上定位数据。如下图所示:内存地址的转换是通过一种叫做页表(Page Table)的机制来完成的,这是本节要讲解的重点,即:页表是什么?为什么要采用页表机制,而不采用其他机制? 虚拟地址如何通过页表转换为物理地址?直接使用数组转换最容易想到的映射方案是使用数组:每个数组元素保存一个物理地址,而把虚拟地址作为数组下标,这样就能够很容易地完原创 2022-03-04 10:24:47 · 627 阅读 · 0 评论 -
第十三章 C语言内存精讲_C语言内存对齐,提高寻址效率
关于虚拟地址和物理地址的映射有很多思路,我们可以假设以程序为单位,把一段与程序运行所需要的同等大小的虚拟空间映射到某段物理空间。例如程序A需要 10MB 内存,虚拟地址的范围是从 0X00000000 到 0X00A00000,假设它被映射到一段同等大小的物理内存,地址范围从 0X00100000 到 0X00B00000,即虚拟空间中的每一个字节对应于物理空间中的每一个字节。程序运行时,它们的对应关系如下图所示:当程序A需要访问 0X00001000 时,系统会将这个虚拟地址转换成实际的物理原创 2022-03-01 19:31:16 · 1039 阅读 · 0 评论 -
第十三章 C语言内存精讲_C语言内存对齐,提高寻址效率
计算机内存是以字节(Byte)为单位划分的,理论上CPU可以访问任意编号的字节,但实际情况并非如此。CPU 通过地址总线来访问内存,一次能处理几个字节的数据,就命令地址总线读取几个字节的数据。32 位的 CPU 一次可以处理4个字节的数据,那么每次就从内存读取4个字节的数据;少了浪费主频,多了没有用。64位的处理器也是这个道理,每次读取8个字节。以32位的CPU为例,实际寻址的步长为4个字节,也就是只对编号为 4 的倍数的内存寻址,例如 0、4、8、12、1000 等,而不会对编号为 1、3、11、10原创 2022-03-01 19:31:07 · 738 阅读 · 1 评论 -
第十三章 C语言内存精讲_虚拟地址空间以及编译模式
所谓虚拟地址空间,就是程序可以使用的虚拟地址的有效范围。虚拟地址和物理地址的映射关系由操作系统决定,相应地,虚拟地址空间的大小也由操作系统决定,但还会受到编译模式的影响。这节我们先讲解CPU,再讲解编译模式,让大家了解编译器是如何配合CPU来提高程序运行速度的。CPU的数据处理能力CPU是计算机的核心,决定了计算机的数据处理能力和寻址能力,也即决定了计算机的性能。CPU一次(一个时钟内)能处理的数据的大小由寄存器的位数和数据总线的宽度(也即有多少根数据总线)决定,我们通常所说的多少位的CPU,原创 2022-03-01 19:30:58 · 680 阅读 · 0 评论 -
第十三章 C语言内存精讲_虚拟内存到底是什么?为什么我们在C语言中看到的地址是假的?
在C语言中,指针变量的值就是一个内存地址,&运算符的作用也是取变量的内存地址,请看下面的代码:在 C-Free 5.0 下运行,结果为:pa = 0X402000, &b = 0X402004代码中的 a、b 是全局变量,它们的内存地址在链接时就已经决定了,以后再也不能改变,该程序无论在何时运行,结果都是一样的。那么问题来了,如果物理内存中的这两个地址被其他程序占用了怎么办,我们的程序岂不是无法运行了?幸运的是,这些内存地址都是假的,不是真实的物理内存地址,而是虚拟地址。虚原创 2022-03-01 19:30:48 · 705 阅读 · 1 评论 -
第十三章 C语言内存精讲_一个程序在计算机中到底是如何运行的?
当你决定学习「内存」,你已然超越了 99% 的程序员!程序是在内存中运行的,一名合格的程序员必须了解内存,学习C语言是了解内存布局的最简单、最直接、最有效的途径,C语言简直是为内存而生的,它比任何一门编程语言都贴近内存。本专题将为你解开以下谜团:C语言中使用的地址为什么是假的,计算机又是如何通过假的地址访问到真实的物理内存的? 一个C语言程序在内存中是如何分布的?函数放在哪里?变量放在哪里?字符串放在哪里? 为什么全局变量在整个程序中都可以使用,而局部变量只能在函数内部使用? 一个C语言程原创 2022-03-01 19:30:39 · 1147 阅读 · 0 评论 -
第十二章 C语言调试_assert断言函数
在我们的实际开发过程之中,常常会出现一些隐藏得很深的BUG,或者是一些概率性发生的BUG,通常这些BUG在我们调试的过程中不会出现很明显的问题,但是如果我们将其发布,在用户的各种运行环境下,这些程序可能就会露出马脚了。那么,如何让我们的程序更明显的暴露出问题呢?这种情况下,我们一般都会使用 assert 断言函数,这是C语言标准库提供的一个函数,也就是说,它的使用与操作系统平台,调试器种类无关。我们只要学会了它的使用,便可一次使用,处处开花。接下来我们来了解一下 assert 函数的用法,这个函数在 as原创 2022-03-01 19:30:16 · 7543 阅读 · 0 评论 -
第十二章 C语言调试_有条件断点的设置
在此之前,我们已经了解了无条件断点、跟踪点这两种断点,事实上在 Visual Studio 中还有几种常用的断点,在本节我们将一一为大家介绍。大家有没有碰到这样的情况,在一个循环体中设置断点,假设有一千次循环,我们想在第五百次循环中设置断点,这该怎么办?反正设置断点不断按 F5 继续运行四百九十九次是不可能的。那该怎么办呢?其实我们的断点是可以设置各种各样的条件的,对于上述情况,我们可以对断点的命中次数做一个限制。我们首先在 Visual Studio 中创建一个工程,并且输入如下代码:首先,我们在原创 2022-03-01 19:30:04 · 1172 阅读 · 0 评论 -
第十二章 C语言调试_即时窗口的使用
“即时窗口”是VS提供的一项非常强大的功能,在调试模式下,我们可以在即时窗口中输入C语言代码并立即运行,如下图所示:在即时窗口中可以使用代码中的变量,可以输出变量或表达式的值(无需使用printf()函数),也可以修改变量的值。即时窗口本质上是一个命令解释器,它负责解释我们输入的代码,再由VS中的对应模块执行,最后将输出结果呈现到即时窗口。需要注意的是,在即时窗口中不能定义新的变量,因为程序运行时 Windows 已经为它分配好了只够刚好使用的内存,定义变量是需要额外分配内存的,所以调试器不允许原创 2022-03-01 19:29:52 · 1172 阅读 · 0 评论 -
第十二章 C语言调试_单步调试(逐语句调试和逐过程调试)
在实际开发中,常常会出现这样的情况,我们可以大致把出现问题的代码锁定在一定范围内,但无法确定到底是哪条语句出现了问题,该怎么办呢?按照前面的思路,必须要在所有代码行前面设置断点,让代码一个断点一个断点地执行。这种方案确实可行,但很麻烦,也不专业,这节我们就来介绍一种更加便捷的调试技巧——单步调试。所谓单步调试,就是让代码一步一步地执行。下面的代码用来求一个等差数列的和,我们以该代码来演示单步调试:在第6行设置一个断点,然后点击“逐过程调试”按钮,或者按F10键,程序就会运行到下一行并暂停:.原创 2022-02-27 09:15:23 · 6404 阅读 · 0 评论 -
第十二章 C语言调试_查看和修改变量的值
设置了断点,就可以观察程序的运行情况了,其中很重要的一点就是查看相关变量的值,这足以发现大部分逻辑错误。将下面的代码复制到源文件中:在第7行和第12行插入断点。运行到第一个断点时,在局部变量窗口可以看到各个变量的值:可以看到,未经初始化的局部变量和数组的值都是垃圾值,是随机的,没有意义。双击变量的值,可以进行修改。点击“运行”按钮或按F5键,程序会运行到下一个断点位置,在局部变量窗口可以看到各个值的变化:更加快捷的方式除了在窗口中查看变量,还有一种更加便捷的方法:在调试原创 2022-03-01 19:29:38 · 3175 阅读 · 0 评论 -
第十二章 C语言调试_设置断点,开始调试
默认情况下,程序不会进入调试模式,代码会瞬间从开头执行到末尾。要想观察程序的内部细节,就得让程序在某个地方停下来,我们可以在这个地方设置断点。所谓断点(BreakPoint),可以理解为障碍物,人遇到障碍物不能行走,程序遇到断点就暂停执行。上图中,我们希望让程序在第4行代码处暂停执行,那么在第4行代码左侧的灰色部分单击鼠标即可插入断点。你也可以将光标定位到要暂停的代码行,然后按F9键插入断点。也可以在要暂停的位置单击鼠标右键,在弹出菜单中插入断点,如下图所示:插入断点后,点击上方的“运行原创 2022-03-01 19:30:26 · 12011 阅读 · 0 评论 -
第十二章 C语言调试_调试的概念以及调试器的选择
所谓调试(Dubug),就是跟踪程序的运行过程,从而发现程序的逻辑错误(思路错误),或者隐藏的缺陷(Bug)。在调试的过程中,我们可以监控程序的每一个细节,包括变量的值、函数的调用过程、内存中数据、线程的调度等,从而发现隐藏的错误或者低效的代码。我敢保证,每个人都会遇到逻辑错误,而且会经常遇到,初学者更是错的离谱,所以,必须掌握调试技能,没有选择的余地,没有学会调试就是没有学会编程!调试器(Debugger)调试需要借助专业的辅助软件——调试器(Debugger)。现在主流C/C++调试原创 2022-02-27 09:16:31 · 1533 阅读 · 0 评论 -
第十一章 文件操作_C语言插入、删除、更改文件内容
我们平时所见的文件,例如 txt、doc、mp4 等,文件内容是按照从头到尾的顺序依次存储在磁盘上的,就像排起一条长长的队伍,称为顺序文件。除了顺序文件,还有索引文件、散列文件等,一般用于特殊领域,例如数据库、高效文件系统等。顺序文件的存储结构决定了它能够高效读取内容,但不能够随意插入、删除和修改内容。例如在文件开头插入100个字节的数据,那么原来文件的所有内容都要向后移动100个字节,这不仅是非常低效的操作,而且还可能覆盖其他文件。因此C语言没有提供插入、删除、修改文件内容的函数,要想实现这些功能,原创 2022-02-27 09:16:20 · 9710 阅读 · 1 评论 -
第十一章 文件操作_C语言获取文件大小(长度)
实际开发中,有时候需要先获取文件大小再进行下一步操作。C语言没有提供获取文件大小的函数,要想实现该功能,必须自己编写函数。ftell()函数ftell() 函数用来获取文件内部指针(位置指针)距离文件开头的字节数,它的原型为:long int ftell ( FILE * fp );注意:fp 要以二进制方式打开,如果以文本方式打开,函数的返回值可能没有意义。先使用 fseek() 将文件内部指针定位到文件末尾,再使用 ftell() 返回内部指针距离文件开头的字节数,这个返原创 2022-02-27 09:16:11 · 3767 阅读 · 1 评论 -
第十一章 文件操作_C语言FILE结构体以及缓冲区深入探讨
在C语言中,用一个指针变量指向一个文件,这个指针称为文件指针。通过文件指针就可对它所指的文件进行各种操作。定义文件指针的一般形式为:FILE *fp;这里的FILE,实际上是在stdio.h中定义的一个结构体,该结构体中含有文件名、文件状态和文件当前位置等信息,fopen 返回的就是FILE类型的指针。注意:FILE是文件缓冲区的结构,fp也是指向文件缓冲区的指针。不同编译器 stdio.h 头文件中对 FILE 的定义略有差异,这里以标准C举例说明:下面说一下如何控制缓冲区原创 2022-02-27 09:16:00 · 858 阅读 · 0 评论 -
第十一章 文件操作_C语言实现文件复制功能(包括文本文件和二进制文件)
文件的复制是常用的功能,要求写一段代码,让用户输入要复制的文件以及新建的文件,然后对文件进行复制。能够复制的文件包括文本文件和二进制文件,你可以复制1G的电影,也可以复制1Byte的txt文档。实现文件复制的主要思路是:开辟一个缓冲区,不断从原文件中读取内容到缓冲区,每读取完一次就将缓冲区中的内容写入到新建的文件,直到把原文件的内容读取完。这里有两个关键的问题需要解决:1) 开辟多大的缓冲区合适?缓冲区过小会造成读写次数的增加,过大也不能明显提高效率。目前大部分磁盘的扇区都是4K对齐的,如果读写的数据原创 2022-02-27 09:15:36 · 4032 阅读 · 0 评论 -
第十一章 文件操作_C语言rewind和fseek函数的用法详解(随机读写文件)
前面介绍的文件读写函数都是顺序读写,即读写文件只能从头开始,依次读写各个数据。但在实际开发中经常需要读写文件的中间部分,要解决这个问题,就得先移动文件内部的位置指针,再进行读写。这种读写方式称为随机读写,也就是说从文件的任意位置开始读写。实现随机读写的关键是要按要求移动位置指针,这称为文件的定位。文件定位函数rewind和fseek移动文件内部位置指针的函数主要有两个,即 rewind() 和 fseek()。rewind() 用来将位置指针移动到文件开头,前面已经多次使用过,它的原型为:原创 2022-02-27 09:15:13 · 254 阅读 · 0 评论 -
第十一章 文件操作_C语言fscanf和fprintf函数的用法详解(格式化读写文件)
fscanf() 和 fprintf() 函数与前面使用的 scanf() 和 printf() 功能相似,都是格式化读写函数,两者的区别在于 fscanf() 和 fprintf() 的读写对象不是键盘和显示器,而是磁盘文件。这两个函数的原型为:int fscanf ( FILE *fp, char * format, ... );int fprintf ( FILE *fp, char * format, ... );fp 为文件指针,format 为格式控制字符串,... 表示参数原创 2022-02-27 09:15:00 · 305 阅读 · 0 评论 -
第十一章 文件操作_C语言fread和fwrite的用法详解(以数据块的形式读写文件)
fgets() 有局限性,每次最多只能从文件中读取一行内容,因为 fgets() 遇到换行符就结束读取。如果希望读取多行内容,需要使用 fread() 函数;相应地写入函数为 fwrite()。对于 Windows 系统,使用 fread() 和 fwrite() 时应该以二进制的形式打开文件,具体原因我们已在《文本文件和二进制文件到底有什么区别》一文中进行了说明。fread() 函数用来从指定文件中读取块数据。所谓块数据,也就是若干个字节的数据,可以是一个字符,可以是一个字符串,可以是多行数据,并没有什原创 2022-02-27 09:14:48 · 734 阅读 · 0 评论 -
第十一章 文件操作_C语言fgets和fputs函数的用法详解(以字符串的形式读写文件)
fgetc() 和 fputc() 函数每次只能读写一个字符,速度较慢;实际开发中往往是每次读写一个字符串或者一个数据块,这样能明显提高效率。读字符串函数 fgetsfgets() 函数用来从指定的文件中读取一个字符串,并保存到字符数组中,它的用法为:char *fgets ( char *str, int n, FILE *fp );str 为字符数组,n 为要读取的字符数目,fp 为文件指针。返回值:读取成功时返回字符数组首地址,也即 str;读取失败时返回 NULL;如果开原创 2022-02-27 09:15:48 · 584 阅读 · 0 评论 -
第十一章 文件操作_C语言fgetc和fputc函数用法详解(以字符形式读写文件)
在C语言中,读写文件比较灵活,既可以每次读写一个字符,也可以读写一个字符串,甚至是任意字节的数据(数据块)。本节介绍以字符形式读写文件。以字符形式读写文件时,每次可以从文件中读取一个字符,或者向文件中写入一个字符。主要使用两个函数,分别是 fgetc() 和 fputc()。字符读取函数 fgetcfgetc 是 file get char 的缩写,意思是从指定的文件中读取一个字符。fgetc() 的用法为:int fgetc (FILE *fp);fp 为文件指针。fget.原创 2022-02-26 10:33:45 · 2524 阅读 · 0 评论 -
第十一章 文件操作_文本文件和二进制文件到底有什么区别?
在学习了 fopen()函数后,我们知道它的第二个参数是一个字符串,用来表示文件打开方式。如果字符串中出现b,则表示以二进制方式打开文件;如果字符串中出现t,或者两者都不出现,则表示以文本方式打开文件。文本文件和二进制文件的区别根据我们以往的经验,文本文件通常用来保存肉眼可见的字符,比如.txt文件、.c文件、.dat文件等,用文本编辑器打开这些文件,我们能够顺利看懂文件的内容。二进制文件通常用来保存视频、图片、程序等不可阅读的内容,用文本编辑器打开这些文件,会看到一堆乱码,根本看不懂。但.原创 2022-02-26 10:33:37 · 520 阅读 · 0 评论 -
第十一章 文件操作_C语言fopen函数的用法,C语言打开文件详解
在C语言中,操作文件之前必须先打开文件;所谓“打开文件”,就是让程序和文件建立连接的过程。打开文件之后,程序可以得到文件的相关信息,例如大小、类型、权限、创建者、更新时间等。在后续读写文件的过程中,程序还可以记录当前读写到了哪个位置,下次可以在此基础上继续操作。标准输入文件 stdin(表示键盘)、标准输出文件 stdout(表示显示器)、标准错误文件 stderr(表示显示器)是由系统打开的,可直接使用。使用 <stdio.h> 头文件中的 fopen() 函数即可打开文件,它的用法原创 2022-02-26 10:33:22 · 1718 阅读 · 0 评论 -
第十一章 文件操作_C语言中的文件是什么?
我们对文件的概念已经非常熟悉了,比如常见的 Word 文档、txt 文件、源文件等。文件是数据源的一种,最主要的作用是保存数据。在操作系统中,为了统一对各种硬件的操作,简化接口,不同的硬件设备也都被看成一个文件。对这些文件的操作,等同于对磁盘上普通文件的操作。例如:通常把显示器称为标准输出文件,printf 就是向这个文件输出数据; 通常把键盘称为标准输入文件,scanf 就是从这个文件读取数据。常见硬件设备所对应的文件 文件 硬件设备 stdin 标准输入文件,一般指键盘;sc原创 2022-02-26 10:33:14 · 157 阅读 · 0 评论