练习 1 - 20 编写程序 detab,将输入中的制表符替换成适当数目的空格,使空格充满到下一个制表符终止的地方。假设制表符终止位的位置是固定的,比如每隔 n 列就会出现一个制表符终止位。n 应该作为变量还是符号常量?
个人关于制表符及制表终止位的理解的一个不是很精确的描述:行按照一定的空格为间隔进行划分,制表符就相当于光标在一行中从当前所在单位间隔跳到下一个单位间隔的起始位置。这个间隔的宽度为你在空行的行首按下 TAB 键是光标移动的列数,不同的系统和软件有所差异。
本程序运行平台的 TAB 对应的宽度为 8 列。因此制表符所占据的空格位置为
8 - (当前行已打印的字符数 % 8)
detab 的实现如下:
void detab(char line[]) {
int cnt = 1;
int idx = 0;
int space = 0;
while (line[idx] != '\0') {
if (line[idx] == '\t') {
space = TAB - cnt % TAB;
while (space >= 0) {
putchar(' ');
--space;
}
++idx;
}
putchar(line[idx++]);
++cnt;
}
}
完整代码清单如下:
/* ex20.c - detab */
#include <stdio.h>
#define LIMIT 1000
#define TAB 8
void display(char line[]) {
int i = 0;
while (line[i] != '\0') {
putchar(line[i]);
++i;
}
putchar('\n');
}
void detab(char line[]) {
int cnt = 1;
int idx = 0;
int space = 0;
while (line[idx] != '\0') {
if (line[idx] == '\t') {
space = TAB - cnt % TAB;
while (space >= 0) {
putchar(' ');
--space;
}
++idx;
}
putchar(line[idx++]);
++cnt;
}
}
int getLine(char line[], int limit) {
int i = 0;
int c;
if ((c = getchar()) == EOF) {
return -1;
}
do {
line[i] = c;
++i;
} while ((c = getchar()) != '\n');
line[i] = '\0';
return (i + 1);
}
int main() {
char line[LIMIT];
while (getLine(line, LIMIT) > 0) {
detab(line);
putchar('\n');
}
return 0;
}
编译运行结果如下:
$ ./ex20.out
1234567890
1234567890
12 12
12 12
123456 123456
123456 123456
1234567812345678
1234567812345678
12345678 12345678
12345678 12345678
123
123
$