K&R《C程序设计语言》p23:打印最长的输入行

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/haishu_zheng/article/details/75212373

零、代码

#include <stdio.h>
#define MAXLINE 1000	// 输入行的最大长度 

int max;				// 保存目前为止最长行的长度

char line[MAXLINE];		// 保存当前的输入行  
char longest[MAXLINE];	// 保存最长的行 

int get_line(void);		
void copy_longest_line(void);		


int main()
{
    int cur_len;		// 当前行的长度
    extern int max;
    extern char longest[];
    
    max = 0;
    while ((cur_len = get_line()) > 0)
    {
        printf("The current line's length is : %d\n", cur_len);
        if (cur_len > max)
        {
			// 如果当前行的长度大于上次保存的最大长度,则最大长度要更新为当前长度
			// 并且要把当前行的内容放到longest数组中,此时longest数组原先的内容会被覆盖掉
            max = cur_len;
            copy_longest_line();
        }
    }
    
    if(max > 0)
    {
		printf("\nThe max length of the input lines is : %d\n", max);
        printf("The longest line is : %s\n", longest);
    }
    
    return 0;
}


// 将当前输入行的内容保存到line数组中
int get_line(void)
{
    int c=0, i=0;
    extern char line[];
    
	/**
	 * 继续循环需要三个条件:
	 * (1) i小于999,因为数组的最大长度为1000(即0~999),line[999]要放换行符'\n',所以输入字符只能放在line[0]~line[998]
	 * (2) 输入的字符不为文件结束符,Windows的文件结束符为ctrl+z,mac/linux/unix的文件结束符为ctrl+d
	 * (3) 输入的字符不为换行符'\n',因为一旦换符,那就是新的一行了
	 */
    for (; i < MAXLINE-1 && (c= getchar()) != EOF && c != '\n'; ++i)
    {
        line[i] = c;
    }
    
    if (c == '\n')
    {
        line[i] = c;
        ++i;
    }
    
	// 换行符的下一个字符是行结束符'\0','\0'不算在行长度内
    line[i] = '\0';
    
    return i;
}


void copy_longest_line(void)
{
    int i = 0;
    extern char line[], longest[]; 
    
	// 先把line[i]赋值给longest[i],再判断longest[i]是不是行结束符'\0'
    while ((longest[i] = line [i]) != '\0')
    {
        ++i;
    }
}

一、运行结果

输入

a

abc

ab

ctrl + z


 

二、分析

0 请先阅读关联博文http://blog.csdn.net/haishu_zheng/article/details/73478039

 

1 定义数组char c[10],可存放十个字符,从c[0]~c[9]。注意计算机是从0开始计数而不是从1开始计数,所以最后一个元素是c[9]而不是c[10]。

 

2 字符与数字是一一对应的。具体而言,就是每个字符都对应着一个ascii编码。

比如:

a对应97,b对应98,其它小写字母以此类推;

A对应65,B对应66,其它大写字母以此类推;

字符‘1’对应49,字符‘2’对应50,其它数字以此类推;

回车符‘\r’对应13,换行符‘\n’对应10;

行结束符‘\0’对应0。

具体可参考 http://blog.csdn.net/haishu_zheng/article/details/75221350

 

所以,整型数组既可以用来存放整型元素,也可以用来存放字符元素;

同理,字符数组既可以用来存放字符元素,也可以用来存放整型元素。

 

3 在C语言中,字符数组是以’\0’作为行结束符的,并且行结束符不算在字符数组的长度内。

例子:输入abc并换行,这在长度为10的字符数组c[10]中是这么放的

a

b

c

\n

\0

这里c[0] = ‘a’, c[1] = ‘b’, c[2] = ‘c’, c[3]= ‘\n’, c[4] = ‘\0’, c[5]~c[9]都为空。

其长度为4,行结束符’\0’不算在长度内。

 

4 get_line函数中有个句子

for (; i < MAXLINE-1 && (c=getchar()) != EOF && c != '\n'; ++i)

等价于

for (i = 0; i < MAXLINE-1 && (c=getchar()) != EOF && c != '\n'; ++i)

因为i = 0;上面已经出现过,所以这里不写也可以。

 

5 本程序的执行过程

(0)最开始max=0;

 

(1)第一次输入a并且换行,get_line()函数的执行顺序为

i = 0时; 输入‘a’,循环的三个条件都满足,先执行line[0] = ‘a’;

再执行i++,i的值变为1

i = 1时; 输入换行符’\n‘ ,循环条件有一个不满足,结束循环

继续执行if(c == ‘\n’),这个条件是成立的,所以line[1] = ‘\n’,i++,i的值变为2

继续执行line[2] = ‘\0’

继续执行return 2。返回的2就是当前行的长度。

 

此时main()函数中cur_len=2,max=0, cur_max > max成立,执行max = cur_len,即max由原先的0更新为 2。再执行copy_longest_line()函数。

 

copy_longest_line()函数中,

longest[0] = line[0] = ‘a’

longest[1] = line[1] = ‘\n’

longest[2] = line[2] = ‘\0’循环结束

 

(2)第二次输入abc并换行,get_line()函数的执行顺序为

while语句中,

i = 0时,line[0] = ‘a’,i++,i的值变为1;

i = 1时,line[1] = ‘b’,i++,i的值变为2;

i = 2时,line[2] = ‘c’,i++,i的值变为3;

i = 3时,line[3] = ‘\n’,循环结束;

 

if语句中

line[3] = ‘\n’, i++, i的值变为4

 

line[4] = ‘\0’;

 

return 4;

 

main()函数中,

cur_len的值为get_line()的返回值4,上次得到的max值为2,cur_len>max,max=cur_len=4,即max的值由原先的2更新为4,并执行copy_longest_line()函数。

 

copy_longest_line()函数中,

longest[0] = line[0] = ‘a’;

longest[1] = line[1] = ‘b’;

longest[2] = line[2] = ‘c’;

longest[3] = line[3] = ‘\n’;

longest[4] = line[4] = ‘\0’;

循环结束。

 

(3)第3次输入ab并换行,执行get_line()函数,

line[0] = ‘a’;

line[1] = ‘b’;

line[2] = ‘\n’;

line[3] = ‘\0’;

return 3;

因为cur_len=3, max=4, cur_len>max不成立,所以max仍为上次得到的4不作改变,并且copy_longest_line()函数不被执行。

 

6 本程序中,全局变量max,line[1000], longest[1000]的定义和使用都在同一个文件中,并且是先定义后使用,所以实际上所有的extern语句都可以去掉。

但是若全局变量的定义在一个文件内(比如test1.c),使用在另一个文件内(比如test2.c),那么extern语句不能省。

 

代码:

#include <stdio.h>
#define MAXLINE 1000	// 输入行的最大长度 

int max;				// 保存目前为止最长行的长度

char line[MAXLINE];		// 保存当前的输入行  
char longest[MAXLINE];	// 保存最长的行 

int get_line(void);		
void copy_longest_line(void);		


int main()
{
    int cur_len;		// 当前行的长度

    max = 0;
    while ((cur_len = get_line()) > 0)
    {
        printf("The current line's length is : %d\n", cur_len);
        if (cur_len > max)
        {
			// 如果当前行的长度大于上次保存的最大长度,则最大长度要更新为当前长度
			// 并且要把当前行的内容放到longest数组中,此时longest数组原先的内容会被覆盖掉
            max = cur_len;
            copy_longest_line();
        }
    }
    
    if(max > 0)
    {
		printf("\nThe max length of the input lines is : %d\n", max);
        printf("The longest line is : %s\n", longest);
    }
    
    return 0;
}


// 将当前输入行的内容保存到line数组中
int get_line(void)
{
    int c=0, i=0;
    
	/**
	 * 继续循环需要三个条件:
	 * (1) i小于999,因为数组的最大长度为1000(即0~999),line[999]要放换行符'\n',所以输入字符只能放在line[0]~line[998]
	 * (2) 输入的字符不为文件结束符,Windows的文件结束符为ctrl+z,mac/linux/unix的文件结束符为ctrl+d
	 * (3) 输入的字符不为换行符'\n',因为一旦换符,那就是新的一行了
	 */
    for (; i < MAXLINE-1 && (c= getchar()) != EOF && c != '\n'; ++i)
    {
        line[i] = c;
    }
    
    if (c == '\n')
    {
        line[i] = c;
        ++i;
    }
    
	// 换行符的下一个字符是行结束符'\0','\0'不算在行长度内
    line[i] = '\0';
    
    return i;
}


void copy_longest_line(void)
{
    int i = 0;
    
	// 先把line[i]赋值给longest[i],再判断longest[i]是不是行结束符'\0'
    while ((longest[i] = line [i]) != '\0')
    {
        ++i;
    }
}

运行结果:


 

展开阅读全文

没有更多推荐了,返回首页