K&R习题1-20:制表符转指定数量空格的代码异常问题
修复K&R习题1-20的制表符转空格代码
我一眼就看出你的代码问题出在哪了——你把制表符直接硬替换成4个空格,但习题要求的是把制表符替换成足够的空格,让光标对齐到下一个制表位(比如当前位置到下一个4的倍数的位置缺几个补几个),另外还有几处小的越界和冗余问题,导致输入This is\ta test.时输出不符合预期。
具体错误点
- 制表符替换逻辑错误:你没有计算当前位置到下一个制表位的空格数,而是固定补4个。比如
This is结束后光标在第7位(索引从0开始),下一个制表位是第8位,这时候只需要补1个空格,而不是4个——这就是你输出不对的核心原因。 - 数组越界判断不合理:你用
index < MAX_SIZE -5来限制空格填充,这个数字完全是拍脑袋的,应该动态判断剩余空间,确保不会超出数组的最大长度(要留位置给终止符\0)。 - 冗余代码:main函数里的
extern char longest[]完全没用,属于多余的代码;getline_里的extern char line[]也没必要,因为line是全局变量,函数可以直接访问。 - index更新逻辑有漏洞:原代码在填充空格时的循环条件可能导致index计算错误,比如如果数组快满了,x会提前终止,这时候index的更新虽然是对的,但循环条件本身就不对。
修复后的代码
#include <stdio.h> #define MAX_SIZE 1000 #define TAB_STOP 4 char line[MAX_SIZE]; int getline_(void); int main() { int len; while ((len = getline_()) > 0) printf("Line: %s", line); return 0; } int getline_(void) { int chr, index; int needed_spaces; // 把index的递增放到循环体内,方便灵活控制 for (index = 0; index < (MAX_SIZE - 1) && ((chr = getchar()) != EOF) && chr != '\n'; ) { if (chr == '\t') { // 计算当前位置到下一个制表位需要的空格数 // 下一个制表位 = ((当前索引 / 制表位宽度) + 1) * 制表位宽度 needed_spaces = ((index / TAB_STOP) + 1) * TAB_STOP - index; // 逐字符填充空格,同时确保不越界 while (needed_spaces > 0 && index < MAX_SIZE - 1) { line[index++] = ' '; needed_spaces--; } } else { // 普通字符直接存入数组,index自增 line[index++] = chr; } } // 处理换行符,同样要检查越界 if (chr == '\n' && index < MAX_SIZE - 1) { line[index++] = chr; } // 加上字符串终止符 line[index] = '\0'; return index; }
修复关键点解释
- 正确计算空格数:通过
((index / TAB_STOP) + 1) * TAB_STOP - index精准算出当前位置到下一个制表位需要的空格数,确保对齐正确。比如index=7、TAB_STOP=4时,下一个制表位是8,所以只需要1个空格。 - 严格的越界保护:在填充空格和处理换行符时,都检查index是否小于
MAX_SIZE -1,保证最后有位置放\0,避免数组溢出。 - 简化index管理:把index的递增从for循环的第三个表达式移到循环体内,这样处理制表符时可以灵活控制index的增长,逻辑更清晰。
- 清理冗余代码:删掉了没用的extern变量,让代码更简洁。
现在测试输入This is\ta test.,输出会是正确对齐的Line: This is a test.(中间的制表符被替换成1个空格,刚好对齐到下一个制表位)。
内容的提问来源于stack exchange,提问作者Ahmed Mohamed
相关产品推荐
相关产品推荐

