Перевод: Напишите программу detab, заменяющую символы табуляции во вводимом тексте нужным числом пробелов (до следующего "стопа" табуляции). Предполагается, что "стопы" табуляции расставлены на фиксированном расстоянии друг от друга, скажем, через n позиций. Как лучше задавать n - в виде значения переменной или в виде именованной константы?
Оригинал: Write a program detab that replaces tabs in the input with the proper number of blanks to space to the next tab stop. Assume a fixed set of tab stops, say every n columns. Should n be a variable or a symbolic parameter?
Количество пробелов до следующего "стопа" будем получать по алгоритму: от расстояния между стопами отнимаем результат остатка от деления позиции символа табуляции на расстояние между "стопами". Предположим, что "стопы" табуляции расположены на расстоянии пяти позиций друг от друга.
Пусть 7-й символ будет символом табуляции. Арифметическая операция остаток от деления 7 % 5 = 2, а 5 - 2 = 3. Получаем, что до следующего "стопа" табуляции остается 3 позиции.
Пусть 11-й символ будет символом табуляции. Арифметическая операция остаток от деления 11 % 5 = 1, а 5 -1 = 4. Получаем, что до следующего "стопа" табуляции остается 4 позиции.
- 11 % 5 = 1
- 11 = 5 * 2 + 1
$ vim ex_1_20.c
#include <stdio.h>
#define MAXLINE 1000 /* максимальный размер вводимой строки */
#define STOP 5 /* расстояние "стопов" табуляции друг от друга */
int getstr(char line[], int maxline);
int main(void)
{
int len;
char line[MAXLINE];
int i, j;
int symbols; /* количество символов, выведенных на экран */
int test = 0; /* количество символов, выведенных на экран, до следующего "стопа" табуляции */
while((len = getstr(line, MAXLINE)) > 0)
{
for(i = 0, symbols = 0; line[i] != '\0'; ++i)
{
if(line[i] == '\t')
{
test = STOP - (symbols % STOP);
for (j = 0; j < test; ++j)
{
putchar('|'); /* для наглядности будем использовать символ '|' вместо пробела */
++symbols;
}
}
else
{
putchar(line[i]);
++symbols;
}
}
}
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;
}
$ cc -g -O0 -Wall -o detab ex_1_20.c
$ ./detab<Tab>
|||||
1<Tab>
1||||
11<Tab>
11|||
111<Tab>
111||
1111<Tab>
1111|
11111<Tab>
11111|||||