致敬经典 << K&R C >> 之打印输入单词水平直方图和以每行一个单词打印输入 (练习1-12和练习1-13)

发布于:2025-05-18 ⋅ 阅读:(24) ⋅ 点赞:(0)

1. 前言

不知道有多少同学正在自学C/C++, 无论你是一个在校学生, 还是已经是上班族. 如果你想从事或即将从事软件开发这个行业, C/C++都是一个几乎必须要接触的系统级程序开发语言. 虽然现在有Rust更安全的系统级编程语言作为C/C++的替代, 但作为入门, C应该还是要好好学的. C最早由B语言改进而来. 不出意外你应该已经想到了C/UNIX都是贝尔实验室的里奇和汤普逊所开发. 一个C影响了后来一系列开发语言, 一个UNIX影响了后来一系列操作系统. K&R C就是经典C, 那时C还没有标准化, 还没有ANSI标准, 所以K&R就是早期的C标准.

确切的说 K&R C 指的是由 C 语言创始人 Dennis Ritchie 和 Brian Kernighan 在其经典著作《The C Programming Language》(1978年第一版)中描述的早期 C 语言标准。也被称为 "经典 C" 或 "传统 C". Brian Kernighan 就是 K&R C中的K, Hello World程序就是他首先使用的. 当然这本书有第2版, 引入了一些ANSI的C标准. 这本书的练习题除部分少量的过时外, 大部分编程题还是很值得自己实践练习的.我这有两道练习题, 自己写了一下, 虽然不难, 但如果是初学者, 还是可以自己写完, 再看看别人的, 多参考学习.

写这些编程题有个感觉, 就像造车, 发动机要自己造, 变速箱要自己造, 底盘也要自己造, 外观要自己设计, 一切细节都要详细了解, 没有封装, 除了少量标准库函数可用, 一切要自己动手写. 就算是标准库中的函数, 你也完全根据它的功能, 自己去实现, 自己来封装. 那些大师早期哪有现成的库, 都是他们自己写的. 所以要多动手去写, 去实现自己的版本.

第 1 章内容不多, 尽量用本章介绍的内容来完成作业.

2. 练习 1 - 12 习题及代码

下面是两个练习题:

练习1-12  编写一个程序, 以每行一个单词的形式打印其输入.

下面是代码, 因为很短, 所以没有加注释, 另外输入中如果有多个空白符 (制表, 空格), 会忽略:

#include <stdio.h>

int main(void)
{
    int ch;

    while ((ch = getchar()) != EOF) {
        if (ch != ' ' && ch != '\t' && ch != '\n') {
            putchar(ch);
        } else {
            if (ch == '\n') { 
                putchar(ch);
            } else {
                while ((ch = getchar()) == ' ' || ch == '\t') {
                    continue;
                }
                putchar('\n');
                putchar(ch);
            }
        }

    }

    return 0;

运行结果:

3. 练习 1 - 13 习题及代码

下面这道题在我的另几篇文章已实现垂直方向的直方图, 有兴趣的同学可以看另几篇文章.

练习1-13  编写一个程序, 打印输入中单词的直方图. 水平方向的直方图比较容易绘制, 垂直方向的直方图则要困难些.

下面是代码 (代码有一些问题,有兴趣的同学可以改进):

#include <stdio.h>
#define MAX 20      /*统计最长为20个字符的单词*/
#define MAXNUM 26   /*某个长度最多统计25个*/

void initwords(int *pw, int len);
void countwords(int *pw, int len);
void printhtgm(int *pw, int len);
void putpatterns(char ch, int n, int width);
void putspaces(int n);
void putline(int n);
void printXnum(int n);
int main(void)
{
    int words[MAX + 1];          /*统计最长20个字符的单词*/

    initwords(words, MAX + 1);   /*初始化单词数量数组*/
    countwords(words, MAX + 1);  /*统计输入各长度㼿司数量*/
    printhtgm(words, MAX + 1);   /*打印水平直方图*/

    return 0;
}

/*初始化单词数量数组*/
void initwords(int *pw, int len)
{
    int i;
    for (i = 1; i < len; i++) { 
        pw[i] = 0; 
    }
}

/*统计各长度单词数量*/
void countwords(int *pw, int len)
{
    int ch, wordlen, wordin;

    wordlen = wordin = 0;
    while ((ch = getchar()) != '#') {
        if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
            if (wordin == 0) { wordin = 1; }
            if (wordlen < len - 1) { wordlen++; }
        } else if (ch == ' ' || ch == '\t' || ch == '\n') {
            if (wordin == 1) {
                wordin = 0;
                if (pw[wordlen] < MAXNUM - 1) { pw[wordlen]++; }
                wordlen = 0;
            }
        }
    }
    if (pw[wordlen] < MAXNUM - 1) { pw[wordlen]++; }
}

/*打印水平直方图*/
void printhtgm(int *pw, int len)
{
    int i;

    putline(2);
    putspaces(5);
    putchar('Y');
    putline(1);
    for (i = len - 1; i > 0; i--) {
        putspaces(3);
        printf("%2d", i);
        putchar('|');
        putpatterns('*', pw[i], 2);
        putline(1);
    }
    
    putspaces(5);
    putchar('+');
    putpatterns('-', MAXNUM * 2, 1);
    putchar('>');
    putspaces(1);
    putchar('X');    
    putline(1);
    printXnum(20);
    putline(2);   
}

/*打印X轴数字*/
void printXnum(int n)
{
    if (n < 1 || n > MAXNUM) { return; }

    int i;

    putspaces(6);
    for (i = 1; i <= n; i++) { 
        if (i >= 10) { putchar(' '); }
        printf("%2d", i); 
    }
}

/*打印直方图案*/
void putpatterns(char ch, int n, int width)
{
    if (n < 1 || n > MAXNUM * 2) { return; }
    int i;

    for (i = 0; i < n; i++) {
        putspaces(width - 1); 
        putchar(ch); 
    }
}

/*打印Y轴缩进*/
void putspaces(int n)
{
    int i;
    for (i = 0; i < n; i++) {
        putchar(' ');
    }
}

/*空格打印*/
void putline(int n)
{
    int i;
    for (i = 0; i < n; i++) { putchar('\n'); }
}

运行结果:

下面是输入一些测试单词

下面是输入歌曲 << The day you went away  >> 的歌词结果:

4. 结语

喜欢就点赞收藏, 您的支持是我创作的动力.


网站公告

今日签到

点亮在社区的每一天
去签到