C语言KR圣经笔记 7.7行输入和输出 7.8其他函数

news/2024/7/23 18:41:35 标签: c语言, 笔记, 开发语言

7.7 行输入和输出

标准库提供了一个输入例程 fgets,类似于我们在之前章节使用过的 getline 函数:

char *fgets(char *line, int maxline, FILE *fp)

fgets 从文件 fp 中读取下一个输入行(包括换行符)到字符数组 line 中;最多读入 maxline-1 个字符。结果行以 '\0' 结尾。 fgets 通常返回 line;若遇到文件结束或错误则返回 NULL。(我们的getline 返回行的长度,这个返回值更有用;若文件结束则返回 0。)

至于输出, 有 fputs 函数写一个字符串(不必包含换行符)到文件中:

int fputs(char *line, FILE *fp)

如果遇到错误会返回EOF,否则返回 0。

库函数 gets 和 puts 类似 fgets 和 fputs,不过操作的是 stdin 和 stdout。令人困惑的是,gets 删除结尾的 '\n',而 puts 在结尾添加 '\n'。

为了说明 fgets 和 fputs 这样的函数也没什么特别的,这里把它们源代码从我们系统的标准库中拷贝出来,给大家看看:

/* fgets: 从 iop 中获取最多 n 个字符 */
char *fgets(char *s, int n, FILE *iop)
{
    register int c;
    register char *cs;

    cs = s;
    while (--n > 0 && (c = getc(iop)) != EOF)
        if ((*cs++ = c) == '\n')
            break;
    *cs = '\0';
    return (c == EOF && cs == s) ? NULL : s;
}

/* fputs: 写字符串到文件iop */
int fputs(char *s, FILE *iop)
{
    int c;

    while (c = *s++)
        putc(c, iop);
    return ferror(iop) ? EOF : 0;
}

标准库规定 ferror 在错误时返回非零;fputs 在错误时返回 EOF,其他情况下返回非负数。

可以很容易用 fgets 来实现我们的 getline:

/* getline:读一行,返回长度 */
int getline(char *line, int max)
{
    if (fgets(line, max, stdin) == NULL)
        return 0;
    else
        return strlen(line);
}

练习7-6、写个程序来比较两个文件,打印出它们的第一个差异行。
练习7-7、修改第五章的样式搜索程序,使其从一系列文件中获取输入,如果没有给出文件名做参数,则用标准输入。当找到匹配行时,是否应当输出文件名?
练习7-8、写个程序打印一系列文件,每个文件从新的一页开始,带标题和页码。

7.8 其他函数

标准库提供了种类繁多的函数。本节是对其中最常用部分的概述。更多的细节和更多其他函数,参见附录B。


7.8.1 字符串操作


我们已经提到过 <string.h> 中的字符串函数 strlen, strcpy, strcat 和 strcmp 。在下面的描述中, s 和 t 是 char * 类型,而 c 和 n 是 int 类型。

strcat(s,t)             连接 t 到 s 的末尾
strncat(s,t,n)        连接 t 的 n 个字符到 s 的末尾
strcmp(s,t)           在 s < t ,s == t 或 s > t 时分别返回负数,0 和 正数 
strncmp(s,t,n)      与 strcmp 一样,但只比较前 n 个 字符
strcpy(s,t)             把 t  拷贝到 s
strncpy(s,t,n)        最多拷贝 t 的 n 个字符到 s
strlen(s)                返回 s 的长度
strchr(s,c)             返回 s 中第一个 c 的指针,若没有则返回 NULL
strtchr(s,c)            返回 s 中最后一个 c 的指针,若没有则返回 NULL


7.8.2 字符类型判断和转换


一些来自 <ctype.h>的函数执行字符判断和转换。在下面的描述中,c 是可以表示为 unsigned char 或 EOF 的一个 int。这些函数返回 int。

isalpha(c)        若 c 为字母则返回非0,否则返回0
isupper(c)        若 c 为大写则返回非0,否则返回0
islower(c)         若 c 为小写则返回非0,否则返回0
isdigit(c)           若 c 为数字则返回非0,否则返回0
isalnum(c)        若 isalpha(c) 或 isdigit(c) 则返回非0,否则返回0
isspace(c)        若 c 为空格、制表符、换行符、回车符、换页符、垂直制表符则返回非0
toupper(c)        返回转换成大写后的 c
tolower(c)         返回转换成小写后的 c


7.8.3 ungetc

我们在第四章写过 ungetch 函数,标准库提供了一个更加受限的版本;称为 ungetc

int ungetc(int c, FILE *fp)

将字符 c 推回给文件 fp 并返回 c,或遇到错误则返回 EOF。每个文件只保证推回一个字符。ungetc 能够与任意输入函数如 scanf,getc 或 getchar 一起使用。

7.8.4 命令执行


system(char *s) 函数执行字符串 s 中的命令,然后继续当前程序的执行。s 的内容强依赖于本地系统。举个UNIX系统上的小例子,如下语句

system("date");


使程序 date 被执行;它在标准输出上打印日期和时间。 system 从被执行的命令中返回一个依赖于系统的整数。在 UNIX 系统中,返回的状态是 exit 返回的值。

7.8.5 内存管理

函数 malloc 和 calloc 动态地获取内存块。

void *malloc(size_t n)

返回一个指针,指向 n 个字节的未初始化的内存空间,若无法满足要求则返回 NULL。

void *calloc(size_t n, size_t size)

返回一个指针,指向能容纳 n 个指定大小为 size 的对象的数组空间,若无法满足要求则返回 NULL。内存空间初始化为零。

malloc 和 calloc 返回的指针为所需的对象提供了正确的对齐,但必须要转换成恰当的类型,例如

int *ip;

ip = (int *) calloc(n, sizeof(int));

free(p) 释放 p 指向的内存空间,其中 p 最初是通过调用 malloc 或 calloc 得到的。空间的释放顺序是随意的,但释放并非由调用 calloc 或 malloc 得到的内存是非常可怕的错误。

在内存释放后继续使用也是错误的。下面这段在链表中循环释放元素的代码非常典型,但却是错误的:

for (p = head; p != NULL; p = p->next)     /* 错误 */
    free(p);

 
正确的方法是在释放之前保存需要的内容

for (p = head; p != NULL; p = q) {
    q = p->next;
    free(p);
}

8.7 给出了一个类似 malloc 的内存管理器的实现,其中分配的内存块可以自由地以任意顺序释放。

7.8.6 数学函数

<math.h> 中定义了超过 20 个数学函数;这里给出一些使用最频繁的。每个函数都要一个或两个double 参数,并返回 double。

sin(x)                x 的正弦,x 为弧度
cos(x)               x 的余弦,x 为弧度
atan2(y,x)         y/2 的反正切,xy为弧度
exp(x)               e 的 x 次方
log(x)                x 的自然对数(x > 0)
log10(x)            x 的常用对数(x > 0)
pow(x,y)            x 的 y 次方
sqrt(x)                x 的平方根( x >= 0)
fabs(x)               x 的绝对值


7.8.7 随机数生成

函数 rand 计算出范围从 0 到 RAND_MAX(在<stdlib.h>中定义)的伪随机整数序列。生成大等于0但小于1的伪随机浮点数的一种方法是

#define frand() ((double) rand() / (RAND_MAX + 1.0))

(如果你的库已经提供了获取浮点随机数的函数,则它可能比上面这个有更好的统计特性。)

函数 srand(unsigned) 设置 rand 的种子。标准建议的可移植的 rand 和 srand 的实现,参见 2.7节。


练习7-9、像 isupper 这样的函数可以实现为节省空间或节省时间。探索两种可能性。


(第七章完)
 


http://www.niftyadmin.cn/n/5381839.html

相关文章

Python循环语句——continue和break

一、引言 在Python编程中&#xff0c;循环是常见的控制流语句&#xff0c;它允许我们重复执行一段代码&#xff0c;直到满足某个条件为止。而在循环中&#xff0c;continue和break是两个非常重要的控制语句&#xff0c;它们可以帮助我们更加灵活地控制循环的行为。 二、contin…

django中session值的数据类型是dict,需要手动save(),更新才会传递到其他页面。

django 项目在一个页面中删除了session中的某一个成员&#xff08;del request.session["test"]["a"]&#xff09;&#xff0c;切换到另外一个页面的时候&#xff0c;session中的那个成员居然还在。让我一阵莫名其妙。 # 对session["test"]进行初…

【算法】基础算法002之滑动窗口(二)

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》《算法》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 目录 前言 5.水果成篮&#xff…

C语言第二十七弹---内存函数

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 内存函数 1、memcpy 使用和模拟实现 2、memmove 使用和模拟实现 3、memset 函数的使用 4、memcmp 函数的使用 总结 前面两弹讲解了字符函数和字符串函数&…

前端技巧之svg精灵图svg-sprite-loader

首先说明精灵图的必要性&#xff0c;其可以让我们只需要向服务器请求一次图片资源&#xff0c;就能加载很多图片&#xff0c;即能够减轻http请求造成的服务器压力。 然后这里要说明的是这个插件是webpack上面的&#xff0c;所以在vue2中比较好用&#xff0c;如果在vue3中&…

Eclipse - Format Comment

Eclipse - Format & Comment 1. Correct Indentation2. Format3. Toggle Comment4. Add Block Comment5. Remove Block CommentReferences 1. Correct Indentation Ctrl A: 选择全部代码 Ctrl I: 校正缩进 or right-click -> Source -> Correct Indentation 2. F…

docker ubuntu tomcat 换源 安装软件

第一种办法参考docker中ubuntu容器更换apt源_ubuntu更改apt源 with dockerfile-CSDN博客 sed -i s/archive.ubuntu.com//mirrors.aliyun.com/g /etc/apt/sources.list sed -i s/security.ubuntu.com//mirrors.aliyun.com/g /etc/apt/sources.list apt update apt install vim…

普中51单片机学习(九)

蜂鸣器 蜂鸣器简介 在单片机应用的设计上&#xff0c;很多方案都会用到蜂鸣器&#xff0c;大部分都是使用蜂鸣器来做提示或报警&#xff0c;比如按键按下、开始工作、工作结束或是故障等等。改变单片机引脚输出波形的频率&#xff0c;就可以调整控制蜂鸣器音调&#xff0c;产…