C语言学习笔记(八)

C语言学习第八天,今天主要学习函数参数和字符数组

1.8 参数——传值调用
在C语言中,被调函数不能直接修改主调函数中变量的值,而智能修改其私有的临时副本的值。传值调用的利大于弊。在调用函数中,参数可以看作是便于初始化的 局部变量,因此额外使用的变量更少,这样程序可以更紧凑简洁。例如下面的这个power函数利用了这个性质:

/* power函数:求底数的n次幂; n>=0*/
int power(int base, int n) {
    int p;

    for (p = 1; n > 0; --n)
        p = p * base;
    return p;
}

其中,参数n用做临时变量,并通过随后执行的for循环语句递减,直到其值为0, 这样就不需要额外引入变量i。power函数内部对n的任何操作不会影响到调用函数中n的原始参数值。
必要时,也可以让函数能够修改主调函数中的变量。这种情况下,调用者需要向被调用函数提供设置值的变量的地址。而被调用函数则需要将对应的函数声明为指针类型,并通过它间接访问变量。
如果是数组的参数,当把数组名用做参数是,传递给函数的值是数组起始元素的位置或地址——它并不复制数组元素本身。在被调用函数中,可以通过数组下标访问或修改数组元素的值。

1.9 字符数组

通过一个程序来说明字符数组及操作字符数组的函数的用法。该程序读如一组文本行,并把最长的文本行打印出来。该算法的基本框架非常简单:
while(还有未处理的行)
if(该行比已处理的最长行还要长)
    保存该行
    保存该行的长度
打印最长行

从上面的框架中很容易看出,程序很自然地分成了若干片段,分别用于读入新行、测试读入行、保存该行,其与部分则控制这一过程。
首先,编写一个独立的函数getline,它读取输入的下以行。我们尽量保持该函数在其他场合也有用。至少getline函数应该在读到文件末尾时返回一个信号;更为有用的涉及时它能够在读入文本行时返回该行的长度,而在遇到文件结束符时返回0。由于0不是有ixiao的行长度,因此可以作为标志文件结束的返回值。每一行至少包含一个字符,只包含换行符的行,其长度为1。
当发现某个新读入的行比以前读入的最长行还要长时,就需要把该行保存起来。也就是说,我们需要用另一个函数copy把新行复制到一个安全的位置。
最后,我们需要在主函数main中控制getline和copy这两个函数。程序如下:

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

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

/* 打印最长的输入行 */
main() {
    int len;    /* 当前行长度 */
    int max;    /* 目前为止发现的最长行的长度 */
    char line[MAXLINE];     /*当前的输入行*/
    char longeset[MAXLINE]; /*用于保存最长的行*/

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

/* getline函数:将一行读入到s中并返回其长度 */
int mygetline(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;
}

原书中的getline函数在<stdio.h>中有定义,此处换成mygetline。
main与getline之间通过一对参数及一个返回值进行数据交换。在getline 函数中,两个参数时通过程序行

int getline(char s[], int lim)

声明的,它把第一个参数s声明为数组,把第二个参数lim声明为整型。声明中提供数组大小的目的是留出存储空间。在getline函数中没有必要指明数组s的长度,这是因为该数组的大小是在main函数中设置的。上述程序行也声明了getline函数的返回值类型为int。由于函数的默认返回值类型为int,因此这里的int可以省略。这也是我们一直看到main函数的返回值省略的原因。
有些函数返回有用的值,而有些函数(如copy)仅用于执行一些动作,并不返回值。copy函数的返回值类型为void,它显示说明该函数不返回任何值。
getline函数把字符'\0'(即空字符,其值为0)插入到它创建的数组的末尾,以标记字符串的结束。这一约定已被C语言采用:所以

"hello\n"

的字符串常量,它以字符数组的形式存储,数组的各元素分别存储字符串的各个字符并以'\0'标志字符串的结束。
[h][e][l][l][0][\n][\0]
printf函数中的格式规范%s规定,对于的参数必须是以这种形式表示的字符串。copy函数的实现正是依赖于输入参数由'\0'结束这一事实,它将'\0'拷贝到输出参数中。

练习1-16 修改打印最长文本的行的程序的主函数main,使之可以打印任意长度的输入行的长度,并尽可能多地打印文本。
练习1-17 编写一个程序,打印长度大于80个字符的所有输入行。
练习1-18 编写一个程序,删除每个输入行末尾的空格及制表符,并删除完全是空格的行。
练习1-19 编写函数reverse(s),将字符串s中的字符顺序颠倒过来。使用该函数编写一个程序,每次颠倒一个输入行中的字符顺序。


_____________________________________________
这个题我没太理解是啥意思
/* 练习1-16  打印任意长度的输入行的长度,并尽可能多的打印文本 */
main() {
    int len;    /* 当前行长度 */
    char line[MAXLINE];     /*当前的输入行*/

    while ((len = mygetline(line, MAXLINE)) > 0)
        printf("%d %s", len, line);
    return 0;
}
_____________________________________________

/* 练习1-17 编写一个程序,打印长度大于80个字符的所有输入行。 */
main() {
    int len;    /* 当前行长度 */
    char line[MAXLINE];     /*当前的输入行*/

    while ((len = mygetline(line, MAXLINE)) > 0)
        if(len > 80)
            printf("%d %s", len, line);
    return 0;
}

_____________________________________________
/* 练习1-18 编写一个程序,删除每个输入行末尾的空格及制表符,并删除完全是空格的行。 */
main() {
    int len;    /* 当前行长度 */
    char line[MAXLINE];     /*当前的输入行*/
    int i;

    while ((len = mygetline(line, MAXLINE)) > 0){
        for (i = len - 1; i >= 0; i--) {
            if (line[i] == ' ' || line[i] == '\t' || line[i] == '\n') {
                line[i] = '\0';
            } else {
                break;
            }
        }
        if (i+1 > 0)
            printf("%d %s\n", i+1, line);
    }
    return 0;
}

_____________________________________________
void reverse(char s[]);

/* 练习1-19 编写函数reverse(s),将字符串s中的字符顺序颠倒过来。使用该函数编写一个程序,每次颠倒一个输入行中的字符顺序。 */
main() {
    int len;    /* 当前行长度 */
    char line[MAXLINE];     /*当前的输入行*/
    int i;

    while ((len = mygetline(line, MAXLINE)) > 0){
        for (i = len - 1; i >= 0; i--) {
            if (line[i] == ' ' || line[i] == '\t' || line[i] == '\n') {
                line[i] = '\0';
            } else {
                break;
            }
        }
        if (i+1 > 0) {
            reverse(line);
            printf("%d %s\n", i+1, line);
        }
    }
    return 0;
}
void reverse(char s[]) {
    int i, len;
    char c;

    /* 首先得确定字符串的长度 */
    i = len = 0;
    while(s[len] != '\0')
        len++;

    /* 再进行翻转, */
    for(i = 0; i < len/2; i++) {
        c = s[i];
        s[i] = s[len-1-i];
        s[len-1-i] = c;
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值