K& R练习1-20编程语言第2版

时间:2014-11-01 19:50:16

标签: c kernighan-and-ritchie

我应该在这个计划中做些什么。我不明白。
问题是:编写一个程序detab,用适当的数字替换输入中的选项卡 空格到下一个制表位。假设一组固定的制表位,比如每n列。 n应该是变量还是符号参数?
我首先用空格('')替换标签(' \ t')。 但我想这是错误的做法。 请指教?
顺便说一下应该是什么?变量或符号参数?

到目前为止

代码:

#include<stdio.h>
#define TAB 5
int main() {
    int i, c;
    while((c = getchar()) != EOF) {
        if(c == '\t') {
            for(i = 0; i < TAB; ++i)
                putchar(' ');
        } else
            putchar(c);
    }
    return 0;
}

在本练习发布的所有问题中,我无法理解其含义。


这是我的最终代码,请告诉我它是否有任何问题/错误。我认为它应该正常工作..
感谢@Nit,@ Chrono Kitsune,@ dasblinkenlight以及其他所有帮助过的人。

#include<stdio.h>
#define TAB 8
int main() {
int c, count = 0, space = 0;
while((c = getchar()) != EOF) {

    if(c == '\t') {
        space = (TAB - (count % TAB));
        while(space > 0){
            putchar(' ');
            count++;
            space--;
        }
    }
    else{
        putchar(c);
        ++count;
    }

    if(c == '\n')
        count = 0;
}
return 0;
}

3 个答案:

答案 0 :(得分:4)

您正在做的不是练习要求您做的事情:您应该插入不同数量的空格,而不是为每个标签插入固定数量的空格,具体取决于到目前为止在线上打印了多少空格

你如何获取每个标签的空格数并不重要 - 你使它成为预处理器常量的方式非常好。但是,无论在TAB找到'\t'的哪个位置,都要生成'\t'空格,而不是计算需要计算打印多少“常规”字符,并计算出count时需要多少空格{ {1}}。

为目前为止打印的字符创建变量'\n'。将其初始化为零,然后每次看到putchar字符时将其重置为零。致电count++时,也请'\t'

现在,当您看到标签TAB - (count % TAB) 时,计算下一个制表位的距离。表达式是

{{1}}

这就是你需要打印的空间。

这应该是足够的信息让您返回并修复您的程序 - 我认为您只需要编写另外五行代码(不计算您需要插入的花括号的行)以完成此练习

答案 1 :(得分:1)

第一步是理解问题。当我一遍又一遍地阅读它时,起初我无法理解它到底要我做什么。这是因为在我搜索有关 tab 的更多信息之前,有些概念对我来说并不清楚或不熟悉。首先,什么是制表符,什么是制表位?在许多上下文中,制表符是由转义序列 \t 表示的字符。就像其他字符(例如字母或数字)一样,它是一个字符,但有特殊用途,因此它不是宽空格或 4 或 8 个空格,因为它看起来像。显示为一个宽空格或 4 或 8 个空格正是它的设计目的,它将多行上的每个制表符分隔的文本组对齐,使该区域看起来像一个表格,但在该级别的下方,软件看到它只是一个特点。制表位是按下 Tab 键时光标所在行上的位置。这些位置根据显示 Tab 字符的宽度或字符(或列,均指同一概念)的宽度或数量固定在行上。例如,在 Windows 记事本上,Tab 的默认宽度为 8 个字符,当您键入 Tab 键时,光标将移动到第 8、第 16、第 24... 个字符的后面。您可以在第一行输入 0 以更清楚地看到效果:

00000000000000000000000000000000
    Ivan    Hello   World
This    is  a   table
delimited   by  tab

现在重新阅读这个问题,我很清楚这是用空格替换制表符,同时保持原始表格外观。然后您可以开始编写代码来计算每个 Tab 需要多少个空格。这是我为这个练习提供的完整代码:

#include <stdio.h>

#define MAX_LENGTH 1000
#define LINE_NUM 100
#define TAB_WIDTH 8

int readLine(char line[], int maxLength);
void copy(char from[], char to[]);
void detab(char line[], char result[]);

main() {
    printf("Input: \n");
    char lines[LINE_NUM][MAX_LENGTH];
    char line[MAX_LENGTH];
    char result[MAX_LENGTH];
    int lineId = 0, length = 0;
    while ((length = readLine(line, MAX_LENGTH)) != 0) {
        detab(line, result);
        copy(result, lines[lineId]);
        lineId++;
    }
    
    printf("Output: \n");
    for (int i = 0; i <= lineId; i++) {
        printf("%s\n", lines[i]);
    }
}

int readLine(char line[], int maxLength) {
    char ch;
    int length = 0;
    while ((ch = getchar()) != EOF && ch != '\n' && length < maxLength) {
        line[length] = ch;
        length++;
    }
    if (ch == '\n') {
        line[length] = '\0';
    }
    return length;
}

void copy(char from[], char to[]) {
    int i = 0;
    while (from[i] != '\0') {
        to[i] = from[i];
        i++;
    }
    to[i] = '\0';
}

void detab(char line[], char result[]) {
    int i = 0;
    char ch;
    int column = 0;
    int spaces;
    int nextTabStop;
    while ((ch = line[i++]) != '\0') {
        if (ch == '\t') {
            spaces = TAB_WIDTH - column % TAB_WIDTH;
            nextTabStop = column + spaces;
            for (; column < nextTabStop; column++) {
                result[column] = ' ';
            }
        } else {
            result[column] = ch;
            column++;
        }
    }
    result[column] = '\0';
}

答案 2 :(得分:1)

首先,尝试熟悉 '\t'(TAB 字符),看看打印时会发生什么

'\t' + ','
'.' + '\t' + ','
'..' + '\t' + ','

等等。您会看到有固定数量的初始 '.' ,其中 '\t' 后的 ',' 字符位于同一位置,这意味着 '\t' 长度不固定,因此如果您尝试将其替换为固定数量的 ' ' 字符(空格),输出将与输入不同。

了解这一点,您的任务是创建一个程序,用空格替换所有 '\t' 字符,因此您必须计算为您读取的每个 '\t' 字符打印所需的空格数。这就是我迄今为止所做的。

#include <stdio.h>
#define WSPT 8 // white spaces per tab

main () {
    int c, counter;
    counter = 0; // distance from the previous tab stop
    while((c = getchar()) != EOF) {
        if(c == '\t') {
            for(int i = 0; i < WSPT - counter; ++i) 
                putchar(' '); // print white spaces until reach the next tab stop
            counter = 0; // you are again at the start of a tab stop
        } else {
            putchar(c); 
            if(c != '\n')
                counter = (counter + 1) % WSPT; // move 1 step
            else
                counter = 0; // you are again at the start of a tab stop
        }
    }
}