вторник, 4 февраля 2014 г.

Упражнение 1.21

Напишите программу entab, заменяющую строки из пробелов минимальным числом табуляций и пробелов таким образом, чтобы вид напечатанного текста не изменился. Используйте те же "стопы" табуляции, что и в detab. В случае, когда для выхода на очередной "стоп" годится один пробел, что лучше — пробел или табуляция?

Write a program entab that replaces strings of blanks by the minimum number of tabs and blanks to achieve the same spacing. Use the same tab stops as for detab. When either a tab or a single blank would suffice to reach a tab stop, which should be given preference?

Алгоритм:
1. Запоминать на какой мы позиции;
2. Запоминать количество идущих подряд пробелов;
3. Если подряд идут четыре пробела, то сколько позиций остается до следующего "стопа" табуляции;
4. Делаем проход по всем элементам массива от нулевого и фиксируем номер позиции. Конец прохода (цикла) - символ '\0';
5. Если встречаем пробел (для наглядности меняем пробел на '_'), то увеличиваем счетчик пробелов ++space;
6. Если элемент массива не пробел, то сбрасываем счетчик пробелов;
7. Если количество подряд идущих пробелов равно четырем (количество пробелов в знаке табуляции), то узнаем сколько позиций до следующего стопа;
8. Смещаем оставшиеся символы влево на три позиции.

#include <stdio.h>
#define MAXLINE 1000
#define STOP 4  /* расстояние между "стопами" табуляции */

int getstr(char line[], int maxline);
int bstop(int position);

int main(void)
{
    int len;    /* длина символьного массива */
    char line[MAXLINE]; /* символьный массив */
    int i;      /* позиция в символьном массиве */
    int space;  /* счетчик пробелов */
    int before; /* количество позиций перед следующим "стопом" */
    before = 0;
    int j = 0;

    while ((len = getstr(line, MAXLINE)) > 0)
    {
        printf("Длина строки равна %d\n", len);
        for (i = 0, space = 0; line[i] != '\0'; ++i)
        {
            if (line[i] == '_') {
                ++space;
                printf("Есть пробел. Сейчас подряд %d пробелов\n", space);
                printf("Позиция в строке: %d\n", i);
            }
            else {
                space = 0;
                printf("Подряд пробелов нет\n");
                printf("Позиция в строке: %d\n", i);
            }
            if (space == 4) {
                printf("Есть ЧЕТЫРЕ пробела подряд!\n");
                printf("Позиция в строке: %d\n", i);
                before = bstop(i);
                printf("До следующего \"стопа\" %d позиций\n", before);
                i = i - (space - 1);
                printf("Позиция, куда будет вставлен символ TAB: %d\n", i);
                len = len - (space - 1);
                printf("Длина строки короче на ТРИ символа и равна: %d\n", len);
                line[i] = '\t';
                for (j = i + 1; j < len; ++j)
                    line[j] = line[j + 3];
                space = 0;
                line[len] = '\0';
                }
            printf("\n");
        }
        printf("%s", line);
    }

        return 0;
}

int getstr(char s[], int lim)
{
    int c, 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 bstop(int i)
{
    return STOP - (i % STOP) - 1;
}

Примечание!
В данном решении я не смог сделать:
1. Чтобы напечатанный текст не менялся;
2. Я не обращаю внимание на "стопы" табуляции.

Комментариев нет:

Отправить комментарий