Керниган/Ритчи упражнение 1.22 - C (СИ)
Формулировка задачи:
"Упражнение 1.22. Напишите программу, печатающую символы входного потока так, чтобы строки текста не
выходили правее n-й позиции. Это значит, что каждая строка, длина которой превышает n, должна печататься
с переносом на следующие строки. Место переноса следует "искать" после последнего символа, отличного от
символа-разделителя, расположенного левее n-й позиции. Позаботьтесь о том, чтобы ваша программа вела
себя разумно в случае очень длинных строк, а также когда до n-й позиции не встречается ни одного символа
пробела или табуляции."
При выполнении программы ошибка такого рода на скриншоте
Решение задачи: «Керниган/Ритчи упражнение 1.22»
textual
Листинг программы
#include <stdio.h>
#include <stdlib.h>
#define N 20
#define TAB 4
//если табуляция больше 4-х пробелов введите нужное значение
int isSpace(char );
void myPrint(char *, int );
int main()
{
char str[BUFSIZ];
int i = 0, j, k;
puts("Enter text:");
while((str[i] = getchar()) != '\n'){
if(str[i] == '\t'){
for(int m = 0; m < TAB; m++, i++)//заменяем \t на пробелы,т.к. таб считается одним символом
str[i] = ' '; //а при печати занимает место как 4 символа и строка может вылезти сильно вправо
i--;
if(i > N)
i = N;
}
if(i == N){
if(isSpace(str[i])){//если N-позиция пробельный символ,
myPrint(str, i); //то печатаем строку и делаем перенос
str[0] = str[i]; //символ с N-позиции переносим в начало следущей строки
i = 1; //и её начнем заполнять со второго элемента
}
else{ //если N-позиция внутри слова
k = i - 1;
while(k && !isSpace(str[k]))//то ищем ближайший пробельный символ слева
k--;
if(!k){//если во всей строке не нашлось пробельных символов
myPrint(str, i);//печатаем ее "как есть"
str[0] = str[i];
i = 1;
}
else{ //если пробельный символ есть,
myPrint(str, k + 1);//то печатаем строку до него включительно
for(j = 0, k++; k <= i; )//а оставшийся конец строки
str[j++] = str[k++]; //копируем в начало следующей
i = j;
}
}
}
else
i++;
}
if(i) //допечатываем остаток буфера < N
myPrint(str, i);
return 0;
}
int isSpace(char c)
{
if(c == ' ' || c == '\t' || c == '\n')
return 1;
return 0;
}
void myPrint(char *s, int size)
{
for(int i = 0; i < size; i++)
putchar(*(s + i));
putchar('\n');
}
Объяснение кода листинга программы
- Ввод текста с клавиатуры.
- Вводится строка
str[BUFSIZ], которая будет использоваться для хранения введенного текста. - Инициализируются три указателя:
iуказывает на текущий символ в строке,jиkиспользуются в функцииmyPrintдля индексации символов в строке. - В цикле
whileсчитывается каждый символ из введенной строки и сохраняется в массивеstr. Если символ является табуляцией (\t), то он заменяется на пробел. - Если текущий символ является пробелом, то вызывается функция
myPrintдля печати строки до него и включая его. Затем первый символ следующей строки копируется в начало следующей строки. - Если текущий символ не является пробелом, то его индекс увеличивается на единицу.
- Если длина строки достигает 20 символов, то она печатается с помощью функции
myPrint. - Если текущий символ является символом новой строки (
\n), то он игнорируется. - Если в строке не осталось символов, но есть пробелы, то вызывается функция
myPrintдля печати оставшихся пробелов. - Функция
isSpaceпроверяет, является ли символ пробелом. - Функция
myPrintиспользуется для печати строки из массиваstr. - В функции
myPrintиспользуется циклforдля печати каждого символа строки. - В функции
myPrintиспользуется функцияputcharдля вывода каждого символа на экран. - В конце каждой строки выводится символ новой строки (
\n).