The C Programming Language(第 2 版) 笔记 / 1 介绍 / 1.9 字符数组

目录、参考文献


1.9 字符数组

字符数组是 C 语言中最常用的数组类型
下面我们通过编写一个程序来说明字符数组以及操作字符数组的函数用法
该程序读入一组文本行,并把最长的文本行打印出来
该算法的基本框架:

while (还有未处理的行) 
    if (该行比已处理的最长行还要长) 
        保存该行为最长行
        保存该行的长度
打印最长的行

从上面的框架中很容易看出,程序很自然地分成了若干片断
分别用于读入新行、测试读入的行、保存该行,其余部分则控制这一过程

首先,我们编写一个独立的函数 getline,它读取输入的下一行
我们尽量保持该函数在其它场合也有用
getline 函数应该在读到文件末尾时返回一个信号
更为有用的设计是,它能够在读入文本行时返回该行的长度,而在遇到文件结束符时返回 0
由于 0 不是有效的行长度,因此可以作为标志文件结束的返回值
每一行至少包括一个字符,只包含换行符的行,其长度为 1

当发现某个新读入的行比以前读入的最长行还要长时,就需要把该行保存起来
也就是说,我们需要用另一个函数 copy 把新行复制到一个安全的位置

最后,我们需要在主函数 main 中控制 getline 和 copy 这两个函数

#include <stdio.h> 
#define MAXLINE 1000 /* maximum input line length */

int getline(char line[], int maxline); 
void copy(char to[], char from[]); 
/* print the longest input line */ 
main() 
{ 
    int len; /* current line length */ 
    int max; /* maximum length seen so far */ 
    char line[MAXLINE]; /* current input line */ 
    char longest[MAXLINE]; /* longest line saved here */
    
    max = 0; 
    while ((len = getline(line, MAXLINE)) > 0) 
        if (len > max) { 
            max = len; 
            copy(longest, line); 
        } 
    if (max > 0) /* there was a line */ 
        printf("%s", longest); 
    return 0; 
}

/* getline: read a line into s, return length */ 
int getline(char s[],int lim) 
{ 
    int c, i; 
    for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i) 
        s[i] = c; 
    if (c == '\n') { 
        s[i] = c; 
        ++i; 
    } 
    s[i] = '\0'; 
    return i; 
}

/* copy: copy 'from' into 'to'; assume to is big enough */ 
void copy(char to[], char from[]) 
{ 
    int i;
    i = 0; 
    while ((to[i] = from[i]) != '\0') 
        ++i; 
}

程序的开始对 getline 和 copy 这两个函数进行了声明,这里假定它们都存放在同一个文件中

main 与 getline 之间通过一对参数及一个返回值进行数据交换
在 getline 函数中,两个参数是通过程序行

int getline(char s[], int lim)

声明的,它把第一个参数 s 声明为数组,把第二个参数 lim 声明为整型
声明中提供数组大小的目的是留出存储空间
在 getline 函数中没有必要指明数组 s 的长度,这是因为该数组的大小是在 main 函数中设置的
如同 power 函数一样,getline 函数使用了一个 return 语句将值返回给其调用者
上述程序行也声明了 getline 函数的返回值类型为 int
由于函数的默认返回值类型为 int,因此这里的 int 可以省略

有些函数返回有用的值,而有些函数(如 copy)仅用于执行一些动作,并不返回值
copy 函数的返回值类型为 void,它显式说明该函数不返回任何值

getline 函数把字符 ‘\0’(即空字符,其值为 0)插入到它创建的数组的末尾以标记字符串的结束
这一约定已被 C 语言采用:当在 C 语言程序中出现类似于

"hello\0"

的字符串常量时,它将以字符数组的形式存储
数组的各元素分别存储字符串的各个字符,并以 ‘\0’ 标志字符串的结束

image

printf 函数中的格式规范 %s 规定,对应的参数必须是以这种形式表示的字符串
copy 函数的实现正是依赖于输入参数由 ‘\0’ 结束这一事实

值得一提的是,即使是上述这样很小的程序,在传递参数时也会遇到一些麻烦的设计问题
例如,当读入的行长度大于允许的最大值时,main 函数应该如何处理
getline 函数的执行是安全的,无论是否到达换行符字符,当数组满时它将停止读字符
main 函数可以通过测试行的长度以及检查返回的最后一个字符来判定当前行是否太长,然后再根据具体的情况处理
为了简化程序,这里不考虑这个问题

调用 getline 函数的程序无法预先知道输入行的长度,因此 getline 函数需要检查是否溢出
另一方面,调用 copy 函数的程序知道(也可以找出)字符串的长度,因此该函数不需要进行错误检查


目录、参考文献

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值