从头学C(10)字符数组

0

接着上一节,来学习下数组作为参数的用法。字符数组是C语言中最常用的数组类型,

第一章 导言 >> 1.9 字符数组

目的:编写一个程序,使其可以读入一组文本行,并打印其中最长的文本行。

解决:稍微想想,其实该算法的框架不算复杂:

while(还有未处理的行,则读取该行)
{
        if(该行比已处理的最长行还要长)
        {
                保存该行
                保存该行的长度
        }
}
打印最长的文本行

有了这个框架,所以我们至少会需要以下两个函数:

  • getline():读入新的一行,同时返回该行的长度
  • copy():复制行,用于保存当前已知的最长行

这里还需要考虑特殊的情况:

  • 假如该行只有一个回车(注意并不是文件结束标识符),那么getline()应该返回1,表明该行长度为1
  • 假如到达文件结束符,那么getline()应该返回0,表明该行不是有效行

这样我们就能根据getline()的返回值来判断是否还有未处理的行了。

下面是详细代码:

#include <stdio.h>
#define MAXLINE 1000    /* 允许的单行的最大长度h */

int my_getline(char line[], int maxline);
void copy(char to[], char from[]);

/* 打印最长的行 */
main()
{
        int len;                /* 当前行长度 */
        int max;                /* 目前已处理的最长行的长度 */
        char line[MAXLINE];     /* 当前的输入行 */
        char longest[MAXLINE];  /* 用于保存最长的行 */

        max = 0;
        while((len = my_getline(line, MAXLINE)) > 0 )
                if(len > max){
                        max = len;
                        copy(longest, line);
                }
        if(max > 0)     /* 存在这样的行 */
                printf("%s", longest);
        return 0;
}

/* my_getline:读取新的一行到s中,并返回其长度 */
int my_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: 将from复制到to,这里假定to足够大 */
void copy(char to[], char from[])
{
        int i;

        i = 0;
        while((to[i]= from[i]) != '\0')
                ++i;
}

在第4行中,我们声明了my_getline函数,并把参数s声明为数组,参数lim声明为整型,函数返回值也声明为整型(函数的返回值默认是int型,所以其实这个声明中的int可以省略)。

在my_getline()函数中,利用了一个for循环,通过getchar()依次读入各个字符,只要字符个数小于(MAXLINE – 1)并且当前字符不是回车符(即换行符‘\n’),该行的字符就会依次存入字符数组s[ ]的各个单元中。

细心的童鞋会发现,当读到换行符后,会在字符数组s[ ]的末尾额外添加一个’\0’字符。这是因为在C语言中,用’\0’(也叫空字符,其值为0)来标记字符串的结束,所以当我们看到类似“hello\n”的字符串常量时,它将以字符数组的形式存储,并以’\0’标志字符串的结束,存储单元图如下所示:

字符串常量

而且,在printf函数中,以%s格式输出的参数必须是以这种形式表示的字符串

my_getline()的最后,通过return返回该行的长度,注意,返回字符串长度时并没有计算’\0’在内,但是’\n’是包含在内的,即空字符不是普通文本的一部分。

第5行,将copy函数声明为无返回值的函数,是因为该函数仅仅执行复制行的动作,并不需要返回什么值。在copy函数中我们也可以注意到,它也是以遇到空字符’\0’为跳出while循环的条件。

其实,这个程序在传递参数方面还是有隐藏的问题的,童鞋们可以自己先想想看~

最后,个人觉得还有一些需要注意的地方:

  1. 声明一个函数的参数为数组时,不能漏掉数组的两个中括号([ ]);
  2. 在调用参数为数组的函数时,赋给被调函数的参数只需数组名即可,而不需要两个中括号([ ]);

Leave A Reply