致敬经典 << KR C >> 之打印输入单词水平直方图和以每行一个单词打印输入 (练习1-12和练习1-13)
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. 结语
喜欢就点赞收藏, 您的支持是我创作的动力.