> 文档中心 > 100 Days of Code-day31-here is detab‘s dad

100 Days of Code-day31-here is detab‘s dad


修改程序detab以接受制表位列表作为参数。如果没有参数,请使用默认设置。(detab进阶版)

#include#include#define TABINC 8#define MaxLine 100#define YES 1#define NO 0void settab(int argc, char *argv[], char *tab);void detab(char *tab);int tabpos(int pos, char *tab);int main(int argc,char *argv[]){char tab[MaxLine + 1];scanf("%d", &argc);getchar();for (int i = 1; i < argc; i++) {argv[i] = (char *)malloc(MaxLine * sizeof(char));gets(argv[i]);}settab(argc, argv, tab);detab(tab);return 0;}void detab(char *tab){int c, pos = 1;while ((c = getchar()) != EOF){if (c == '\t') {doputchar(' ');//只要一遇到换行符,无论如何也要打印一个空格符while (tabpos(pos++, tab) != YES);//遇到停止位时跳出循环,停止打印空格符}else if(c == '\n'){putchar(c);pos = 1;}else {putchar(c);++pos;}}}//set tab stops in array tab//it is to initialize tab stops//if no arguments are input,we use default tab stops//Or,we use provided tab stopsvoid settab(int argc, char *argv[], char *tab){int i, pos;if (argc <= 1)//default tab stopsfor (i = 1; i <= TABINC; i++)if (i % TABINC == 0)//TABINC整数倍的位置即为制表符停止位tab[i] = YES;elsetab[i] = NO;else {//user-provided tab stopsfor (i = 1; i <= MaxLine; i++)tab[i] = NO;//标记NO意味着该位置不是制表符停止位while (--argc > 0) {pos = atoi(*++argv);//读取输入的参数if (pos > 0 && pos <= MaxLine)//根据输入的参数在对应的位置上设置制表符停止位tab[pos] = YES;}}}//determine if pos is at a tab stopint tabpos(int pos, char *tab){if (pos > MaxLine)//在限定范围外,原本认定不是制表符停止位的位置也会成为停止位//也就是说在范围外不允许将制表符替换成相应指定个数的空格符return YES;elsereturn tab[pos];//pos在1-MaxLine范围内(包括边界),返回其原来的标记}

不输入参数

此时TABINC被定义成常量,等于8
在这里插入图片描述

输入两个参数

此时TABINC就可以看做是变量。而且虽然argc=3,当时第一个参数默认是所输入的命令字符串detab
在这里插入图片描述

思考:

自主设置制表符停止位的缺点:

虽然更具有灵活性,但与此同时也出现了一些问题。当只输入有限的参数时,settab函数只能根据输入设置有限的制表符停止位。那么,当光柱位置超过手动设置的停止位后,其后面输入的内容便无法像自动设置的停止位那样严格的固定输入的内容。
具体例子如下面的程序段所示。

if (c == '\t') {doputchar(' ');//只要一遇到换行符,无论如何也要打印一个空格符while (tabpos(pos++, tab) != YES);//遇到停止位时跳出循环,停止打印空格符

当需要tabpos函数返回一个制表符停止位的标志YES时,却因为手动输入的有限性使得程序继续输出空格符。那么,这意味着只要输入换行符的位置在手动设置的停止位之后,那么当程序捕捉到该字符时,就会持续不断地输出空格符直到光柱位置pos大于MaxLine时(如下面程序段所示),循环才会停止。

int tabpos(int pos, char *tab){if (pos > MaxLine)//在限定范围外,原本认定不是制表符停止位的位置也会成为停止位//也就是说在范围外不允许将制表符替换成相应指定个数的空格符return YES;elsereturn tab[pos];//pos在1-MaxLine范围内(包括边界),返回其原来的标记}