第1章 简介
1.5 字符输入和输出
如下两个输入和输出函数,是基础版本,它们可以以扩充出很多版本
int getchar(void)
int putchar(int char)
1.5.3 行统计
#include <stdio.h> void main() { int ch, nl = 0; while ((ch = getchar()) != EOF) if (ch == '\n') ++nl; printf("nl = %d\n", nl); }
个人理解,如果该行没有换行符,就EOF,应该算一行,修改如下
#include <stdio.h> void main() { int ch, nl = 1, cnt = 0; while ((ch = getchar()) != EOF) { if (ch == '\n') { nl++; cnt = 0; } else { cnt++; } } if (cnt == 0) nl--; printf("\nnl = %d\n", nl); }
1.5.4 单词计数
在1.5.4 单词计数中,梳理一下功能拆分的思路。几个小功能,分开处理,相互之间没有关联
练习题
练习 1_8 编写统计空格、制表符、换行符个数的程序
#include <stdio.h> void main() { int ch = 0; int n_blank = 0, n_tap = 0, n_enter = 0; while(EOF != (ch = getchar())) { if (' ' == ch) n_blank++; else if ('\n' == ch) n_enter++; else if ('\t' == ch) n_tap++; } printf("n_blank=%d, n_tap=%d, n_enter=%d\n", n_blank, n_tap, n_enter); }
练习1-9 编写一个程序,将输入复制到输出,并将其中多个连续的空格合并成一个。
void main() { int ch = 0, c_last = 'a'; // c_last 的初始值不是空格字符就可以 while(EOF != (ch = getchar())) { if (' ' != ch) { putchar(ch); } else if (' ' != c_last) { putchar(ch); } c_last = ch; } }
然后可以通过 || 进行程序简化
void main() {
int ch = 0, c_last = 'a';
while(EOF != (ch = getchar())) {
if (' ' != ch || ' ' != c_last) {
putchar(ch);
}
c_last = ch;
}
}
上述处理是题解答案,可认为使用双指针分别保留了上一个字符和当前字符。而我的思路如下
void main() { int ch = 0, flag = 0; while(EOF != (ch = getchar())) { if (' ' != ch) { putchar(ch); flag = 0; } else if (0 == flag) { putchar(ch); flag = 1; } } }
1.9 字符数组
读入一组文本行,并打印最长的文本行
#include <stdio.h>
int get_line(char *s, int limit);
void copy(char *to, char *from);
#define MAXLINE 10 //一行可以保存的最大字符数
void main() {
int len = 0, max = 0;
char line[MAXLINE], char tgt[MAXLINE];
while ((len = get_line(line, MAXLINE)) > 0) {
if (len > max) {
max = len;
copy(tgt, line);
}
}
if (max > 0)
printf("max=%d,%s\n", max, tgt);
}
int get_line(char *s, int limit) {
int ch = 0, len = 0;
while (len < limit - 1 && (ch=getchar()) != EOF && ch != '\n')
s[len++] = ch;
if (ch == '\n')
s[len++] = ch;
s[len] = '\0';
return len;
}
void copy(char *to, char *from) {
for (int i = 0; '\0' != (to[i]=from[i]); i++);
}
练习1-17 编写一个程序,打印长度大于80个字符的所有输入行。
该程序 只需要在 main() 的处理逻辑中,判断 get_line() 的返回值 大于 80,打印该行即可
#include <stdio.h> #define MAXLINE 1000 //一行可以保存的最大字符数 int get_line(char *s, int limit);void main() { int len = 0; char line[MAXLINE]; while ((len = get_line(line, MAXLINE)) > 0) { if (len > 80) printf("%s\n", line); } }
1_18 编写一个程序,对于输入行末尾的空格和制表符进行删除,然后打印; 如果该行都是空格,就不会打印了
#include <stdio.h> #define MAXLINE 1000 //一行可以保存的最大字符 int get_line(char *s, int limit); // 该函数和 1-9 中的get_line 一样
int _remove(char *s, int len) { /* 按照上下文,s[len-1] = '\0'; s[len-2] = '\n' */
for (len -= 2; len >= 0 && (s[len] == '\t' || s[len] == ' '); len--); if (len >= 0) { s[++len] = '\n'; s[++len] = '\0'; } return len; } void main() { int len = 0, cnt; // cnt 用来表示删除空格之后的效果 char line[MAXLINE]; while ((len = get_line(line, MAXLINE)) > 0) { printf("len = %d, ", len); if ((cnt = _remove(line, len)) > 0) { printf("cnt=%d, %s", cnt, line); } } }
1_19 编写一个 reverse(s)函数,将输入的文本行,翻转后进行输出
#include <stdio.h> #define MAX_LINE 1000 int get_line(char *s, int limit); void reverse(char *s, int len) {
// 该函数如果无len参数,需要先找到字符串末尾 for(int idx = 0; s[idx]; idx++); 如果s[--idx] = '\n', 还需要--idx for (int left = 0, right = len - 2; left < right; left++, right--) { char tmp = s[left]; s[left] = s[right]; s[right] = tmp; } } void main() { int ch, len = 0; char line[MAX_LINE] = {}; while ((len = get_line(line, MAX_LINE)) > 0) { reverse(line, len); printf("%s", line); } }
练习 1_20 编写 detab,将输入中的制表符替换成适当数目的空格,使空格充满到下一个制表符终止的地方
#include <stdio.h> #define TAB 4 // 首先理解,tab对齐的位置和当前位置有关,需要用空格替换。 // 然后依次处理输入的字符,进行分类讨论。 // pos位置的tab可转化成 TAB-pos%TAB个空格 // 每种情况的pos 变化不同,需要单独设置 void main() { int ch, pos = 0; while(EOF != (ch = getchar())) { if (ch == '\t') { int n_blank = TAB - pos % TAB; // pos = (pos / TAB + 1) * TAB; while (n_blank-- > 0) { putchar(' '); ++pos; // 如果每行有字符个数限制, 此处可修改为 if(++pos == LIMIT) {putchar('\n'); pos = 0; break;} } } else if (ch == '\n') { putchar(ch); pos = 0; else { putchar(ch); ++pos; // 如果每行有字符个数限制,此处可修改为 if (++pos == LIMIT) {putchar('\n'); pos = 0;} } } }
练习 1_21 编写entab, 将空格串替换成最少数量的制表符和空格
#include <stdio.h> // 将多个空格替换成 tab #define TABINC 4 void main() { int ch, nb = 0, nt = 0, pos; for (pos = 1; EOF != (ch = getchar()); pos++) { if (' ' == ch) { if (pos % TABINC != 0) { nb++; } else { nt++; nb = 0; } } else { for (; nt > 0; --nt) // 使用while(nt-- > 0) 进行循环,nb会等于-1 putchar('\t'); if ('\t' == ch) nb = 0; else for (; nb > 0; --nb) putchar(' '); putchar(ch); if ('\n' == ch) { pos = 0; } else if (ch == '\t') { pos = pos + (TABINC - (pos - 1) % TABINC) - 1; } } } }
如果只需一个空格就能达到下一个制表符,当前处理是替换成一个制表符,因为这有助于避免特殊情况
分类:
C语言 / K & R
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)