2014-01-11 2 views
1

«Запишите программу entab, которая заменяет строки пробелов на минимальное количество вкладок и пробелов для достижения одинакового интервала. Используйте те же табуляции, что и для detab. Когда либо вкладка, либо один пустой достаточно для достижения табуляции, которой следует отдавать предпочтение? "Учебная книга для ответов K & R 1.21

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

#include <stdio.h> 
#define TABINC 8 

main() 
{ 
int c, nb, nt, pos; 

nb = 0; 
nt = 0; 
for (pos = 1; (c =getchar()) != EOF; ++pos) 
    if (c == ' '){ 
     if (pos % TABINC != 0) 
      ++nb; 
     else { 
      nb = 0; 
      ++nt; 
     } 
    } 
    else { 
     for (; nt > 0; --nt) 
      putchar('\t'); 
     if (c == '\t') 
      nb = 0; 
     else 
      for (; nb > 0; --nb) 
       putchar(' '); 
     putchar(c); 
     if (c == '\n') 
      pos = 0; 
     else if (c == '\t') 
      pos = pos + (TABINC - (pos - 1) % TABINC) - 1; 
    } 
} 

Часть Я не понимание заключается в следующем:

else if (c == '\t') 
    pos = pos + (TABINC - (pos - 1) % TABINC) - 1; 

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

То, что я действительно не понимаю, - это то, как эта формула работает или как она придумала это. это общая формула, которая возникает при программировании? Это полезно? У него есть имя?

Редактировать: Я понимаю, что делает оператор modulo. Извините, я не уточнил это.

Я ценю любой вход.

ответ

0

У этого нет названия или что-то в этом роде.
Подробно:

Прежде всего, сколько поз должно быть увеличено в зависимости от пос% TABINC,
т.е.. TABINC равно 8, поэтому если pos является кратным от 8, добавьте 8,
, если pos% 8 равно 1 (например, 9, 17 ...), затем добавьте 7,
, если pos% 8 равно 2 (10, 18. ..) добавить 6 и так далее.

Полный список:
поз% 8 -> номер, чтобы добавить
0 -> 8
1 -> 7
2 -> 6
3 -> 5
4 -> 4
5 -> 3
6 -> 2
7 -> 1

Это было бы 8 - pos%8 или, более общий TABINC - pos%TABINC

Важно: Отрицательное число по модулю что-то в C математически не правильно
В C, для a,b >= 0: (-a)%b == -(a%b)

Что добавляется в коде (TABINC - (pos - 1) % TABINC) - 1
С некоторой основной математикой и выше самом деле, это
(TABINC - (pos - 1) % TABINC) - 1
= TABINC - ((pos - 1) % TABINC)) - 1
= TABINC - ((pos % TABINC) - 1) - 1
= TABINC + 1 - (pos % TABINC) - 1
= TABINC - (pos % TABINC)
, который является таким же, как моя короткая формула выше, только более сложная, без всякой причины.

1

Нет специального названия для этой формулы - это относительно простой способ применения математики из начальной школы к повседневным проблемам. Вот что происходит: '\t' персонаж продвигает pos на несколько позиций в диапазоне от одного до TABINC включительно.

  • Когда pos кратна TABINC, вы прыгаете полный TABINC
  • Когда pos один ниже следующего кратного TABINC, вы прыгаете на один,
  • Когда pos это два ниже следующего кратного TABINC, вы прыгаете на два,
  • и так далее - когда pos является x, где 0 < x < TABINC ниже следующего кратного TABINC, вы дзю Т. пл x

Теперь задача вычисления скачка сводится к вычислению разности между pos и следующим кратным TABINC. Это можно сделать, вычислив остаток от деления pos и TABINC и вычитая оставшийся остаток от TABINC. Это делается с помощью оператора %.

С pos является одним основанием *, первое, что делает эта формула, делает его основанием на основе нуля для вычисления остатка. Затем формула вычисляет остаток, что является математическим способом сказать «количество позиций выше последнего TABINC stop». Теперь вам нужно вычесть остаток от TABINC, чтобы получить результат.

* Назначение pos=0 на открытие '\n', казалось бы, противоречит утверждению, что pos является один основе. Тем не менее, заголовок цикла выполняет pos++ после каждой итерации, поэтому следующая итерация цикла видит pos=1 на следующей итерации.

Смежные вопросы