C语言 超详细讲解库函数

目录
  • 1 返回整数的getchar函数
  • 2 更新顺序文件
  • 3 缓冲输出与内存分配
  • 4 库函数
  • 练习

1 返回整数的getchar函数

代码:

#include<stdio.h>
int main()
{
	char c;
	while((c = getchar())!=EOF)//getchar函数的返回值为整型
		putchar(c);
	return 0;
}

上述代码有三种可能:

  • 某些合法的输入字符在被“截断”后使得c的取值与EOF相同,程序将在复制的中途停止。
  • c根本不可能取到EOF这个值,陷入死循环。
  • 程序表面上能够正常工作,但完全是因为巧合。尽管函数geutchar的返回结果在赋给char类型的变量c时会发生“截断”操作,但在许多编译器下,它们在比较表达式中并不是比较c与EOF,而是比较getchar函数的返回值与EOF!,如果编译器采取的是这种做法,上面的例子就能够正常运行了。

2 更新顺序文件

在使用r+同时进行写入和读出文件的操作时,要使用fseek移动指针才行,因为在进行写入和读取的同时,文件指针指向的位置发生了改变。

3 缓冲输出与内存分配

程序输出有两种方式:一种是即时处理方式;另一种是先暂存起来,然后再大块写入的方式。

setbuf(stdout,buf);

语句将通知输入/输出库。所有写入stdout的输出都应该使用buf作为输出缓冲区,直到buf缓冲区被填满或者程序员直接调用fflush(对于由写操作打开的文件,调用fflush将导致输出缓冲区的内容被实际的写入该文件),buf缓冲区种的内容才实际的写入stdout中。缓冲区的大小由系统头文件<stdio.h>中的BUFSIZ定义。

下面是实例:

#include<stdio.h>
int main()
{
	int c;
	char buf[BUFSIZ];
	setbuf(stdout,buf);
	while((c = getchar())!=EOF)
		putchar(c);
}

上面这个程序是错误的,因为buf缓冲区最后一次清空是再main()函数结束之后,在将控制权交给操作系统之前,C运行时库所必须进行清理工作的一部分。但是,在此之前buf字符数组已经被释放。

两种解决方案:

static char buf[BUFSIZ];
setbuf(stdout,(char*)malloc(BUFSIZ));
//此处不需要检查malloc函数调用是否成功,因为setbuf函数的第二个参数取值可以为NULL,此时标准输出不需要进行缓冲。

4 库函数

C语言实现中包括signal库函数,将其作为捕获异步时间的一种方式。

#include<signal.h>//需要引用的头文件
signal(signal type , handler function);

这里的signal type代表系统头文件signal.h中定义的某些常量,这些常量用来标识signal函数将要捕获的信号类型。这里的handler function是当指定的事件发生时,将要加以调用的事件处理函数。

注意:信号甚至可能出现在某些复杂库函数(如malloc)的执行过程中。。因此,从安全的角度考虑,信号的处理函数不应该调用上述类型的库函数。

例如:假设malloc函数的执行过程被一个信号中断。此时,malloc用来跟中可用内存的数据结构很可能只有部分被更新。如果signal处理函数再调用malloc函数,结果可能是malloc函数用到的数据结构完全崩溃,后果不堪设想。

结论:信号非常复杂棘手,而且具有一些从本质上而言不可移植的特性。所以我们应该让signal处理的函数尽可能的简单,并将它们组织在一起,这样,当需要适应一个新系统时,我们可以很容易的进行修改。

练习

问:当一个程序异常终止时,程序输出的最后几行常常会丢失,原因是什么?我们能够采用怎样的措施来解决这个问题?

答:一个异常终止的程序可能没有机会来清空输出其缓冲区,因此,该程序生成的输出可能位于内存中的某个位置,但却永远不会被写出了。在某些系统上,这些无法被写出的输出数据可能长达好几页。

对于调试这类程序的编程人员来说,这种丢失输出的情况经常会误导他们,因为这会造成这样一种印象,即程序发生失败的时刻比实际上运行失败的真正时刻要早得多。**解决方案就是在调试时强制不允许对输出进行缓冲。**解决方案如下:

setbuf(stdout,(char*)0);

这个语句必须在任何输出被写入stdout(包括任何对printf函数的调用)之前执行。该语句最恰当的位置就是作为main函数的第一个语句。

下面程序的作用是把它的输入复制到输出:

#include<stdio.h>
int main()
{
	register int c;
	while((c = getchar())!=EOF)
		putchar(c);
	return 0;
}

把代码改为下面的代码,程序依然能够正确运行,但是慢了许多,这是为什么?

#define EOF -1
int main()
{
	register int c;
	while((c = getchar())!=EOF)
		putchar();
	return 0;
}

函数调用需要花费较长的程序执行时间,因此getchar常常被实现为宏。这个在stdio.h中定义,因此一个程序没有包含stdio.h头文件,在所有fgetchar宏出现的地方,都用getchar函数调用来替换getchar宏。这个程序之所以变慢,就是因为函数调用所导致的开销增多。同样的依据也适用于putchar。

到此这篇关于C语言 超详细讲解库函数的使用方法的文章就介绍到这了,更多相关C语言 库函数内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言strcpy库函数详解

    目录 C语言strcpy库函数的讲解 附1:MSDN关于strcpy库函数的简介 思路: 总结 C语言strcpy库函数的讲解 附1:MSDN关于strcpy库函数的简介 思路: 1.从上面的MSDN关于strcpy库函数的简介中,我们可以知道,传进函数的第一个参数是目标数组,也就是用来接收被拷贝的字符串,第二个参数是源头数组,也就是将这个参数的字符串拷贝到目标数组里面去.(一定要注意目标数组的空间大小一定要比源头数组的空间大小大,不然即使拷贝成功了也会报错!!!) 2.在我们自我实现strcp

  • C语言库函数qsort及bsearch快速排序算法使用解析

    目录 qsort 含义 实现 格局打开 bsearch qsort qsrot 就是C语言库函数中的快速排序函数,对数组,结构体都可以实现快速排序, 他在头文件<stdlib.h>中使用,声明格式为: void qsort(void* base, size_t nums, size_t size, int (*compare)(const void *, const void*)) 这么烦人一长串的参数各是什么意思呢,base 是指向要排序的数组的第一个元素的指针.nums是由 base 指向

  • 一篇文章教你自己动手实现C语言库函数

    目录 memmove 函数声明 函数作用 实现memmove memcpy 函数声明 函数作用 实现memcpy strstr 函数声明 函数作用 实现strstr strcat 函数声明 函数作用 实现strcat strcmp 函数声明 函数作用 实现strcmp strcpy 函数声明 函数作用 实现strcpy strlen 函数声明 函数作用 实现strlen 总结 memmove 函数声明 void * memmove ( void * destination, const void

  • C语言库函数中qsort()的用法

    目录 (一)void*  的指针类型是什么? (二)void qsort(void*, size_t, size_t, int ( * )(const void * ,  const void *  ))  该怎么使用该库函数? (三)使用qsort()来排序不同类型的数据  总结: qsort是库函数提供的一种排序方法,我们就简单1了解一下怎么去用,而不去深究它的库函数是怎么写的 qsort是库函数中提供的一种能排序任何类型的数据的一种排序方法,思想是quick sort(快速排序),今天我听

  • 实现C语言常用字符串库函数

    目录 strlen strcpy strcat strcmp 总结 strlen 数组长度的计算是通过strlen来的,它的作用就是判断给定的数组元素个数,直到碰到\0结束 函数原型 size_t strlen ( const char * str ); 废话少说,直接上代码 int my_strlen(char *str) { char* ch=str; int count=0; while(*ch!='\0') { count++; ch++; } return count; } 但考虑到安

  • C语言实现常用字符串库函数(推荐)

    目录 一.实现memcpy 二.memmove模拟实现 三.strlen的模拟实现 1.计数器方法: 2.递归方式: 3.利用指针实现: 四.strcpy的模拟实现 五.strcmp的模拟实现 六.strstr模拟实现 七.模拟实现strcat 一.实现memcpy 将src所指向的内容拷贝到dst所指向的位置,拷贝len个字节. memcpy是内存拷贝函数 memcpy在使用的时候不用考虑类型,以字节为单位进行拷贝 遇到"\0"的时候不会停下,所以拷贝字符串的时候最好还是用strcp

  • 一篇文章带你实现C语言中常用库函数的模拟

    目录 前言 函数介绍 strlen(求字符串长度) strcpy(字符串拷贝) strcat(字符串追加) strcmp(字符串比较) strstr(找子字符串) memcpy(内存拷贝) memmove(内存移动) 总结 前言 C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在常量字符串中或者字符数组中. 字符串常量适用于那些对它不做修改的字符串函数. 函数介绍 strlen(求字符串长度) size_t strlen ( const char * str

  • C语言 超详细讲解库函数

    目录 1 返回整数的getchar函数 2 更新顺序文件 3 缓冲输出与内存分配 4 库函数 练习 1 返回整数的getchar函数 代码: #include<stdio.h> int main() { char c; while((c = getchar())!=EOF)//getchar函数的返回值为整型 putchar(c); return 0; } 上述代码有三种可能: 某些合法的输入字符在被"截断"后使得c的取值与EOF相同,程序将在复制的中途停止. c根本不可能

  • C语言 超详细讲解链接器

    目录 1 什么是链接器 2 声明与定义 3 命名冲突 3.1 命名冲突 3.2 static修饰符 4 形参.实参.返回值 5 检查外部类型 6 头文件 1 什么是链接器 典型的链接器把由编译器或汇编器生成的若干个目标模块,整合成一个被称为载入模块或可执行文件的实体–该实体能够被操作系统直接执行. 链接器通常把目标模块看成是由一组外部对象组成的.每个外部对象代表着机器内存中的某个部分,并通过一个外部名称来识别.因此,==程序中的每个函数和每个外部变量,如果没有被声明为static,就都是一个外部

  • C语言 超详细讲解算法的时间复杂度和空间复杂度

    目录 1.前言 1.1 什么是数据结构? 1.2 什么是算法? 2.算法效率 2.1 如何衡量一个算法的好坏 2.2 算法的复杂度 2.3 复杂度在校招中的考察 3.时间复杂度 3.1 时间复杂度的概念 3.2 大O的渐进表示法 3.3 常见时间复杂度计算举例 4.空间复杂度 5. 常见复杂度对比 1.前言 1.1 什么是数据结构? 数据结构(Data Structure)是计算机存储.组织数据的方式,指相互之间存在一种或多种特定关系的数据元素的集合. 1.2 什么是算法? 算法(Algorit

  • C语言超详细讲解字符串相乘

    目录 前言 一. 分析思路 二.使用步骤 1.代码如下 2.memset函数 三.总结 前言 我们已经知道,正常的两位整形数据通过*相乘,C语言中int为4字节,32bit(字节),其机器码第一位为符号位,余下31位表示数字,表示范围:-2^31(-2147483648)~2^31-1(2147483647),但超过了这个范围我们该如何做呢? 提示:将数字以字符串的形式进行操作 一. 分析思路 示例: 我们把每一个数都看成是一个字符串,每一个元素为十进制数字所对应的字 符,由于是后面的元素先进行

  • C语言超详细讲解排序算法上篇

    目录 1.直接插入排序 2.希尔排序(缩小增量排序) 3.直接选择排序 4.堆排序 进入正式内容之前,我们先了解下初阶常见的排序分类 :我们今天讲前四个! 1.直接插入排序 基本思想:当插入第i(i>=1)个元素时,前面的array[0],array[1],…,array[i-1]已经排好序,此时用array[i]的排 序码与array[i-1],array[i-2],…的排序码顺序进行比较,找到插入位置即将array[i]插入,原来位置上的元素顺序后移! 直接插入排序的特性总结: 1. 元素集

  • C语言超详细讲解栈与队列实现实例

    目录 1.思考-1 2.栈基本操作的实现 2.1 初始化栈 2.2 入栈 2.3 出栈 2.4 获取栈顶数据 2.5 获取栈中有效元素个数 2.6 判断栈是否为空 2.7 销毁栈 3.测试 3.1测试 3.2测试结果 4.思考-2 5.队列的基本操作实现 5.1 初始化队列 5.2 队尾入队列 5.3 队头出队列 5.4 队列中有效元素的个数 5.5 判断队列是否为空 5.6 获取队头数据 5.7 获取队尾的数据 5.8 销毁队列 6.测试 6.1测试 6.2 测试结果 1.思考-1 为什么栈用

  • C语言超详细讲解轮转数组

    目录 题目描述 实例 解题思路 1. 先整体逆转 2.逆转子数组[0, k - 1] 3.逆转子数组[k, numsSize - 1] 易错点 代码 题目描述 给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数.OJ链接 实例 1.实例1 输入: nums = [1,2,3,4,5,6,7], k = 3输出: [5,6,7,1,2,3,4]解释:向右轮转 1 步: [7,1,2,3,4,5,6]向右轮转 2 步: [6,7,1,2,3,4,5]向右轮转 3 步: [5,6,7

  • C语言超详细讲解数据结构中双向带头循环链表

    目录 一.概念 二.必备工作 2.1.创建双向链表结构 2.2.初始化链表 2.3.动态申请节点 2.4.打印链表 2.5.销毁链表 三.主要功能 3.1.在pos节点前插入数据 尾插 头插 3.2.删除pos处节点数据 尾删 头删 3.3.查找数据 四.总代码 List.h 文件 List.c 文件 Test.c 文件 五.拓展 一.概念 前文我们已经学习了单向链表,并通过oj题目深入了解了带头节点的链表以及带环链表,来画张图总体回顾下: 在我们学习的链表中,其实总共有8种,都是单双向和带不带

  • C语言超详细讲解栈的实现及代码

    目录 前言 栈的概念 栈的结构 栈的实现 创建栈结构 初始化栈 销毁栈 入栈 出栈 获取栈顶元素 获取栈中有效元素个数 检测栈是否为空 总代码 Stack.h 文件 Stack.c 文件 Test.c 文件 前言 栈的概念 栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作.进行数据插入和删除操作的一端称为栈顶,另一端称为栈底.栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则.有点类似于手枪弹夹,后压进去的子弹总是最先打出,除非枪坏了. 压栈:栈的插入

  • C语言超详细讲解队列的实现及代码

    目录 前言 队列的概念 队列的结构 队列的应用场景 队列的实现 创建队列结构 队列初始化 队列销毁 入队列 出队列 队列判空 获取队列元素个数 获取队列头部元素 获取队列尾部元素 总代码 Queue.h 文件 Queue.c 文件 Test.c 文件 前言 队列的概念 队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头 队列和前文所学的栈

随机推荐