c程序设计语言第二版学习记录

第一章 导言

1.8 参数——传值调用

核心观点:被调用函数不能直接修改主调用函数中变量的值,除非通过变量地址传参

#include <stdio.h>
void add(int a, int b) {
    a = a + b;
}
void sub(int *a, int b) {
    (*a) = (*a) - b;
}
int main() {
    int a = 2;
    int b = 1;

    /* 只传递值 */
    printf("a = %d, b = %d\n",a,b);
    add(a,b);
    printf("a = %d, b = %d\n",a,b);
    /* 传递该值对应的地址 */
    sub(&a, b);
    printf("a = %d, b = %d\n", a,b);
    return 0;
}

运行结果:

  1. 第一次printf:打印a和b的初值
  2. 第二次printf:main函数通过传值调用完add函数后,打印a和b的值,add函数中改变了a的值,但不改变main函数中a的值
  3. 第三次printf:main函数通过传地址调用完sub函数后,打印a和b的值,sub函数中改变了a的值,同时改变了main函数中a的值

1.9 字符数组

核心代码

读入一组文本行,并把最长的文本行打印出来;其中读入文本行getline和拷贝最长文本行copy动作都需要自己实现

备注:由于stdio系统库里面已经实现了getline函数,所以此处将该函数命名为getline_bak

#include <stdio.h>
#define MAXLINE 100

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

int main()
{
    int len;
    int max;
    char line[MAXLINE];
    char longest[MAXLINE];

    max = 0;
    while ((len = getline_bak(line, MAXLINE)) > 0) {
        if (len > max) {
            copy(longest, line);
            max = len;
        }
    }
    if (max > 0) {
        printf("%s", longest);
    }
    return 0;
}

/* 功能:获取文本行,识别到换行符、文件终止符、文本字符数量超过最大值,则停止记录
 * 返回值:返回文本行的字符串个数
 */
int getline_bak(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;
}
void copy(char to[], char from[])
{
    int i = 0;
    while ((to[i] = from[i]) != '\0')
        i++;
}

运行结果

练习1-16 

修改打印最长文本行的程序的主程序,使之可以打印任意长度的输入行的长度,并且尽可能多的打印文本(即打印所有长度的输入行)

思路:只需要在getline_bak之后统一打印len和line即可

练习1-17

编写一个程序,打印长度大于80个字符的所有输入行

思路:getline之后判断len是否大于80,大于80就打印(这里便于演示运行结果将长度下限改为10,即文本行的长度如果大于10就打印)

练习1-18

编写一个程序,删除每个输入行末尾的空格及制表符,并删除完全是空格的行

思路:在getlinebak函数中判断获取到的字符是否为空格或制表符,如果是就不记录

练习1-19

编写函数reverse(s),将字符串s中的字符顺序颠倒过来,使用该函数编写一个程序,每次颠倒一个输入行中的字符顺序

思路:使用两个数组下标,分别指向数组的开头和结尾,将开头和结尾的字符进行对调,一直到开头的下标大于结尾的下标为止

#include <stdio.h>
#define MAXLINE 100

int getline_bak(char line[], int maxline);
void copy(char to[], char from[]);
void reverse(char s[]);

int main()
{
    int len;
    int max;
    char line[MAXLINE];
    char longest[MAXLINE];

    max = 0;
    while ((len = getline_bak(line, MAXLINE)) > 0) {
        reverse(line);
        printf("len = %d, line = %s\n", len, line);
        if (len > max) {
            copy(longest, line);
            max = len;
        }
    }
    if (max > 0) {
        printf("%s", longest);
    }
    return 0;
}

/* 功能:获取文本行,识别到换行符、文件终止符、文本字符数量超过最大值,则停止记录
 * 返回值:返回文本行的字符串个数
 */
int getline_bak(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;
}
void copy(char to[], char from[])
{
    int i = 0;
    while ((to[i] = from[i]) != '\0')
        i++;
}
void reverse(char s[])
{
    int i, j;
    char tmp;
    while (s[i] != '\0') {
        i++;
    }
    --i;
    if (s[i] == '\n') {
        --i;
    }
    j = 0;
    while (j < i) {
        tmp = s[j];
        s[j] = s[i];
        s[i] = tmp;
        j++;
        i--;
    }
}

运行结果

1.10外部变量与作用域

  1. 定义:创建变量或分配内存单元
  2. 声明:说明变量的性质,但不分配内存单元

内部变量:在函数内部定义的变量

外部变量:在函数外部定义的变量,函数使用该变量前需要使用extern对该变量进行声明

练习1-20

编写detab程序,将输入中的制表符替换成适当数目的空格,使空格充满到下一个制表符终止位的地方,假设制表符终止的位置是固定的,比如每隔n列就会出现一个制表符终止位。n应该作为变量还是符号常量呢?

思路:由于每隔n列就会出现一个制表符终止位,只要识别到制表位就根据终止位的列数来打印空格(由于空格无法看到效果,此处用“_”替代)

#include <stdio.h>
#define TABING 8 //假设制表符终止位每隔8列出现一次
int main()
{
    int c, nb, pos;
    nb = 0;
    pos = 1;
    while ((c = getchar()) != EOF) {
        if (c == '\t') {
            nb = TABING - (pos - 1) % TABING;
            while (nb > 0) {
                putchar('_');
                pos++;
                nb--;
            }
        } else if (c == '\n') {
            putchar(c);
            pos = 1;
        } else {
            putchar(c);
            pos++;
        }
    }
    return 0;
}

运行结果

练习1-21

编写程序entab,将空格串替换为最少数量的制表符和空格,但要保持单词之间的间隔不变,假设制表符终止位的位置与练习1-20的detab程序的情况相同,当使用一个制表符或者空格都可以达到下一个制表符终止位时,选用哪一种替换字符比较好

思路:在字符串长度是制表符终止位长度的倍数时,则使用制表符替代,否则使用空格进行替代(替代前空格使用*,替代后空格使用_表示)

#include <stdio.h>
#define TABING  8

int main()
{
    int c, nb, nt, pos;
    nb = 0;
    nt = 0;
    for (pos = 0; (c = getchar()) != EOF; pos++) {
        if (c == '*') {
            if (pos % TABING != 0) {
                nb++;
            } else {
                nb = 0;
                nt++;
            }
        } else {
            for (;nt > 0; nt--) {
                putchar('\t');
            }
            if (c == '\t') {
                nb = 0;
            } else {
                while (nb > 0) {
                    putchar('_');
                    nb--;
                }
            }
            putchar(c);
            if (c == '\n') {
                pos = 0;
            }
            if (c == '\t') {
                pos = pos + (TABING - (pos - 1) % TABING) - 1;
            }
        }
    }
    return 0;
}

运行结果

​​​​​​​

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值