我对K& R练习1-22的解决方案有什么问题?

时间:2011-10-09 21:19:44

标签: c kernighan-and-ritchie

C编程语言的练习1-22如下:

  

编写一个程序,将长输入行“折叠”为两个或更多个较短的输入行   在 n -th之前出现的最后一个非空白字符之后的行   输入栏。确保您的程序具有智能性   线条很长,如果之前没有空格或标签   指定的专栏。

这是代码:

#include <ctype.h>
#include <stdio.h>

#define MAXLINE 500
#define FOLD_LENGTH 15

/* _getline:  read a line into s, return length  */ 
size_t _getline(char s[], int lim) 
{ 
    int c; 
    size_t i;

    for (i=0; i < lim-1 && (c=getchar())!=EOF && c!='\n'; ++i) 
        s[i] = c; 
    if (c == '\n') { 
        s[i] = c; 
        ++i; 
    } 
    s[i] = '\0'; 
    return i; 
}

int main()
{
    int c;
    char line[MAXLINE];
    char temp;
    unsigned last_space_idx = 0, i, offset = 0;

    while (_getline(line, MAXLINE) != 0) {
        for (i = 0; line[offset+i] != '\0'; i++) {
            if (i == FOLD_LENGTH) {
                temp = line[offset+last_space_idx];
                line[offset+last_space_idx] = '\0';
                printf("%s\n", line+offset);
                line[offset+last_space_idx] = temp;
                offset = last_space_idx;
                i = 0;
                continue;
            }
            if (isspace(line[offset+i])) {
                last_space_idx = offset+i;
            }
        }
        printf("%s\n", line+offset);
    }
    return 0;
}

这是我正在使用的示例输入:

Penny Lane is in my ears and in my eyes
There beneath
the blue suburban skies

这是我得到的输出:

Penny Lane is
 in my ears and in my ey
 and in my eyes

 eyes

 eyes

 eyes

这里的错误是什么?我真的不知道。

1 个答案:

答案 0 :(得分:7)

很多错误。你这样做:

last_space_idx = offset+i;

但你也这样做:

temp = line[offset+last_space_idx];

这意味着temp = line[(2 * offset) + last_observed_space_relative_to_offset]

您也这样做:

offset = last_space_idx;

这意味着偏移量等于上次观察到的空间,因此在第一个后面的每一行都有一个前面的空格,如下所示:

Penny lane is
 in my ears
 and in my eyes

您的_getline()方法执行此操作:

if (c == '\n') { 
    s[i] = c; 
    ++i; 
}

这意味着任何行返回都会被保留,因此如果您输入There beneath\nthe blue suburban skies,您将获得此输出:

There beneath

the blue suburban skies

最后,您读取的每一行都使用最后一个空格索引和前一行的偏移量。您需要在for循环开始之前重置它们。

这是一个固定版本。我已经整理了一下这个样式,用一个打印子字符串的字符串格式替换了printf()bodge。

#include <stdio.h>

#include <ctype.h>
#include <stdio.h>

#define MAXLINE 500
#define FOLD_LENGTH 15

size_t _getline(char s[], int lim);

/* _getline:  read a line into s, return length  */ 
size_t _getline(char s[], int lim) {

    char c; 
    size_t i;

    for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i) {
        s[i] = c;
    }

    s[i] = '\0'; 
    return i; 
}

int main() {

    char line[MAXLINE];
    unsigned last_space_idx = 0;
    unsigned i;
    unsigned offset = 0;

    while (_getline(line, MAXLINE) != 0) {

        last_space_idx = 0;
        offset = 0;

        for (i = 0; line[offset+i] != '\0'; ++i) {
            if (i == FOLD_LENGTH) {
                printf("%.*s\n", last_space_idx, line + offset);
                offset += last_space_idx + 1;
                i = 0;
            } else if (isspace(line[offset + i])) {
                last_space_idx = i;
            }
        }

        printf("%s\n", line + offset);
    }
    return 0;
}