Что не так с моим решением для упражнения K & R 1-22? - PullRequest
3 голосов
/ 10 октября 2011

Упражнение 1-22 из Язык программирования C выглядит следующим образом:

Напишите программу, чтобы "сложить" длинные строки ввода в две или более короткие строки после последнего непустого символа, который встречается перед n столбец ввода. Убедитесь, что ваша программа делает что-то умное с очень длинными строками, и если нет пробелов или вкладок перед указанный столбец.

Это код:

#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 Ответ

7 голосов
/ 10 октября 2011

много ошибок. Вы делаете это:

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 () строковым форматом, который будет печатать подстроку.

#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;
}
...