Странный вывод изменения программы C с перенаправлением

Я пишу программу для решения упражнения 2-2 K&R.

#include<stdio.h>

#define MAXLINE 1000

/* write an equivalent loop without using && or || */
int Getline(char s[], int lim);

int main()
{
    int len;
    char line[MAXLINE];

    while ((len = Getline(line, MAXLINE)) > 0) {
        printf("%s%15s%d\n", line, "length: ", len);
    }

    return 0;
}

int Getline(char s[], int lim)
{
    int flag = 1;
    int i = 0, c = 0;

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

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

Эта программа неправильная ... странным образом. Я запускаю этот код с перенаправлением вроде

./2-2 <in

с файлом в

Get this line.

Тогда вывод на экран бесчисленный

G length: 1

Похоже, программа застряла в цикле. Но когда я прекращаю использовать перенаправление и просто набираю Получите эту строку. в терминал, хотя это все еще неправильно, бесчисленные выходные данные исчезают. Почему?

Есть ли в строке вашего входного файла новую строку? Попробуйте добавить второй пустой.

Yunnosch 03.06.2018 10:38

Вместо этой ерунды flag = 0 используйте, пожалуйста, break - он существует в языке не зря!

Antti Haapala 03.06.2018 10:44

Я знаю break, но он не описан в главе 2 K&R, поэтому я попытался решить упражнение без break.

Rivers Shall 03.06.2018 11:09
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
52
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Проблема здесь:

for (i = 0; flag == 1; ++i) {
                       ^^^
                       i will always increment to at least 1
                       before the for-loop ends
                       so your function will never return 0

Вместо увеличения в цикле for увеличивайте только после вставки нового элемента. Нравиться

    if (flag == 1) {
        s[i] = c;
        ++i;
    }

Вместо цикла for вы можете использовать цикл while, например:

int i = 0;
while (flag == 1)
{
    ...
}

Следующим шагом будет избавление от флага и использование встроенного break. Нравиться:

int i = 0;
while (1)
{
    if (i >= lim - 1) break;

    ...
}

Ваш код будет намного короче и легче читается.

Спасибо! Я сделал такую ​​ошибку в стиле новичка. Но я думаю, что break не был представлен в главе 2 K&R, поэтому мне не следует использовать его в своем решении для упражнений. И проблема в моей функции может быть решена добавлением --i после цикла for.

Rivers Shall 03.06.2018 11:05

Вы также немного усложнили свою функцию. Если вы просто хотите перенаправить строку из файла, сохранить ее в line и убедиться, что это прекращенный (и без конечного '\n', который вы не должны оставлять свисающими со строк, которые вы храните), вы можете сделать что-то довольно простое, например:

int Getline (char *s, int lim)
{
    int i = 0;              /* char count - length */
    while (i < lim - 1) {   /* loop while chars fit */
        int c = getchar();  /* getchar */
        if (c == EOF)       /* validate EOF? */
            goto done;
        if (c == '\n')      /* validate newline */
            continue;
        s[i++] = c;         /* good char, increment len */
    }
    done:;
    s[i] = 0;               /* nul-terminate */
    return i;               /* return length */
}

(Примечание: из вашего комментария о том, что раньше вы не использовали break, тогда простой goto работает так же хорошо)

Пример использования / вывода

Учитывая ваш файл, содержащий строку "Get this line."

$ ./bin/equivloop <dat/in
Get this line.       length: 14

(примечание: если вы сохраните новую строку, длина будет 15, и этот вывод будет на следующей строке)

Другие вопросы по теме