Упражнение 1-21 K&R - Умственное непонимание

"Невозможное" осуществление K&R.

"Запишите программу entab, который заменяет строки пробелов минимальным количеством вкладок и пробелов для достижения того же интервала. Используйте те же позиции табуляции, скажите каждый n столбцы. N должен быть переменной или символьным параметром?"

Проблема, которую я имею, я не уверен в том, как даже сделать это правильно. Я знаю, что это не является очень объяснительным, но это - в значительной степени проблема здесь. Большинство примеров, которые я видел, считало много пробелов и заменило те ряды вкладкой, но это не то, что ее выяснение, я считаю, что понимаю то, что ее выяснение, но в настоящее время чувствуют себя не могущими сделать это.

Мог любой помогать :)

Править: Код, который я написал до сих пор, может быть найден здесь.

6
задан Georg Fritzsche 19 June 2010 в 19:33
поделиться

4 ответа

Насколько я понимаю, вам не нужно знать, в чем проблема или как ее решить, чтобы ответить на этот вопрос. Вопрос, кажется, спрашивает, понимаете ли вы, когда следует использовать переменные вместо "символических параметров". Я не совсем понимаю, что подразумевается под "символическим параметром"; похоже, это устаревшая номенклатура.

Тем не менее, решение первой части вопроса (замена пробелов на символы табуляции) довольно простое. Вспомните деление и остатки.

0
ответ дан 8 December 2019 в 13:44
поделиться

Если ваш вопрос звучит так: "Что это мне нужно сделать?" Думаю, я могу помочь, перефразировав исходный вопрос (поставив тот же вопрос по-другому).

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

Например, с остановками табуляции через каждые 8 символов и отображением пробелов как '.', а табуляции как '-';

input;
".foo:...bar;......#comment"
output;
".foo:-bar;-..#comment"

input;
".......-foo:.....bar;......#comment"
output;
"-foo:-.bar;-...#comment"

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

Edit Я посмотрел на ваш код и думаю, что он сложнее, чем нужно. Мой совет - делайте это по одному символу за раз. Нет необходимости буферизировать всю строку. По мере чтения каждого символа ведите счет столбцов ('\n' обнуляет его, '\t' увеличивает его на 1 или более, другие символы увеличивают его). Когда вы видите пробел (или табуляцию), ничего не выдавайте сразу, начните процесс энтаббинга, выдайте ноль или более табуляций, а затем пробелы (при '\n' или символе, не являющемся пробелом, в зависимости от того, что наступит раньше).

Последняя подсказка заключается в том, что машина состояний может значительно упростить написание, проверку, тестирование и чтение такого алгоритма.

Edit 2 В бесстыдной попытке заставить ОП принять мой ответ, я пошел дальше и фактически сам написал решение, основанное на подсказках, которые я предложил выше, и моем комментарии в обсуждении.

// K&R Exercise 1-21, entab program, for Stackoverflow.com
#include <stdio.h>
#define N 4     // Tabstop value. Todo, make this a variable, allow
                //  user to modify it using command line

int main()
{
    int col=0, base_col=0, entab=0;

    // Loop replacing spaces with tabs to the maximum extent
    int c=getchar();
    while( c != EOF )
    {

        // Normal state
        if( !entab )
        {

            // If whitespace goto entab state
            if( c==' ' || c=='\t' )
            {
                entab = 1;
                base_col = col;
            }

            // Else emit character
            else
                putchar(c);
        }

        // Entab state
        else
        {

            // Trim trailing whitespace
            if( c == '\n' )
            {
                entab = 0;
                putchar( '\n' );
            }

            // If not whitespace, exit entab state
            else if( c!=' ' && c!='\t' )
            {
                entab = 0;

                // Emit tabs to get close to current column position
                //  eg base_col=1, N=4, col=10
                //  base_col + 3 = 4 (1st time thru loop)
                //  base_col + 4 = 8 (2nd time thru loop)
                while( (base_col + (N-base_col%N)) <= col )
                {
                    base_col += (N-base_col%N);
                    putchar( '\t' );
                }

                // Emit spaces to close onto current column position
                // eg base_col=1, N=4, col=10
                //  base_col -> 8, and two tabs emitted above
                //  base_col + 1 = 9 (1st time thru this loop)
                //  base_col + 1 = 10 (2nd time thru this loop)
                while( (base_col + 1) <= col )
                {
                    base_col++;
                    putchar( ' ' );
                }

                // Emit buffered character after tabs and spaces
                putchar( c );
            }
        }

        // Update current column position for either state
        if( c == '\t' )
            col += (N - col%N); // eg col=1, N=4, col+=3
        else if( c == '\n' )
            col=0;
        else
            col++;

        // End loop
        c = getchar();
    }
    return 0;
}
15
ответ дан 8 December 2019 в 13:44
поделиться

Я согласен с вашей оценкой. Недостаточно будет заменить все n пробелов табуляцией; например, если n == 4, то "hi blank blank blank blank blank" нужно заменить не на "hi tab", а скорее на "hi tab blank blank blank".

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

Что касается "переменная vs. символьный параметр", то оба варианта, безусловно, жизнеспособны, но я могу назвать одно существенное преимущество использования переменной: вы можете запускать программу для разных значений n без перекомпиляции.

1
ответ дан 8 December 2019 в 13:44
поделиться

Я бегло просмотрел ваш код, и ничто не бросается мне в глаза так явно неправильно.

Так что я бы посоветовал либо выполнить пошаговое рассмотрение нескольких примеров ввода в отладчике, исследуя значения переменных по ходу работы, либо добавить целую кучу отладочных операторов печати. В любом случае ваша цель - найти точку, в которой состояние программы начинает отклоняться от того, что вы ожидали или планировали.

0
ответ дан 8 December 2019 в 13:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: