Напишите программу, печатающую символы входного потока так,
чтобы строки текста не выходили правее n-й позиции. Это значит, что каждая
строка, длина которой превышает n, должна печататься с переносом на следующие
строки. Место переноса следует "искать" после последнего символа,
отличного от символа-разделителя, расположенного левее n-й позиции.
Позаботьтесь о том, чтобы ваша программа вела себя разумно в случае очень
длинных строк, а также когда до n-й позиции не встречается ни одного символа пробела
или табуляции.
Write a
program to “fold” long input lines into two or more shorter lines after the
last non-blank character that occurs before the n-th column of input.
Make sure your program does something intelligent with very long lines, and if
there are no blanks or tabs before the specified column.
Данные:
FOLD
– номер крайней позиции;
blank
– позиция крайнего знака разделителя и (или) позиция, куда будет вставлен
символ новой строки;
fragment – буфер для хранения фрагмента строки, которая
не выходит за крайнюю правую позицию;
len – длина строки;
Алгоритм:
- Цикл: есть ли еще строка?
- Если строка длиннее чем крайняя правая позиция, то на случай отсутствия знаков разделителей в строке, перенос будем делать на крайней позиции (blank = FOLD – 1), единицу отнимаем, потому что счетчик позиций начинается с ноля. Далее, необходимо найти позицию пробела или табуляции в строке до крайней правой позиции. Искать будем в обратном порядке, от крайней позиции до нулевой (for (i = FOLD - 1; i > 0; --i)). Если в строке встречается пробел или табуляция, запоминаем номер позиции (blank = i). Принудительно выходим из цикла (i = 0);
- На позицию blank ставим символ новой строки line[blank] = '\n';
- Копируем фрагмент строки до позиции blank в специальное место char fragment[FOLD + 1];
- Выводим нужный фрагмент текста на экран;
- Смещение массива. Для исключения из строки уже выведенного на экран фрагмента;
- Уменьшение длины строки чтоб она соответствовала полученной в результате смещения.
- Если длина строки меньше крайней правой позиции, то просто выводим эту строку.
- В качестве условия цикла будем использовать длину строки. Если длина строки меньше крайней правой позиции, то переменной длины присвоим 0. Условием цикла будет неравенство длины нулю.
$ vim ex_1_22.c
#include <stdio.h>
#define MAXLINE 1000
#define FOLD 50 /* крайняя правая позиция */
int getstr(char s[], int maxline);
void copy(char to[], char from[]);
int main(void)
{
int len, i, j, x;
char line[MAXLINE];
char fragment[FOLD + 1]; /* буфер должен хранить весь фрагмент */
int blank; /* позиция последнего знака разделителя */
while ((len = getstr(line, MAXLINE)) > 0)
{
while(len != 0) /* можно было бы использовать другую переменную*/
{
/* printf("Начальная длина введенной строки: %d\n", len); */
if (len > FOLD)
{
blank = FOLD - 1; /* на случай, если в введенной строке нет разделителей */
for (i = FOLD - 1; i > 0; --i)
{
if (line[i] == ' ' || line[i] == '\t') {
blank = i;
/* printf("%d\n", blank); */
i = 0; /* Принудительный выход из цикла */
}
}
/* printf("За символом %c на позиции %d будет новая строка\n", line[blank], blank); */
line[blank] = '\n';
copy(fragment, line);
printf("%s", fragment);
for (x = 0; x <= FOLD; ++x)
fragment[x] = '\0';
/* Исключаем выведенный на экран фрагмент из строки */
for (j = 0; j <= len; ++j)
line[j] = line[j + blank + 1]; /* +1 для исключения '\n' */
len = len - blank; /* уменьшаем длину строки */
/* printf("Длина строки без сегмента: %d\n", len); */
/* printf("%s", line); */
}
else
{
printf("%s", line);
len = 0; /* конец цикла */
}
}
}
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;
}
void copy(char to[], char from[])
{
int i;
i = 0;
while ((to[i] = from[i]) != '\n')
++i;
}
#define MAXLINE 1000
#define FOLD 50 /* крайняя правая позиция */
int getstr(char s[], int maxline);
void copy(char to[], char from[]);
int main(void)
{
int len, i, j, x;
char line[MAXLINE];
char fragment[FOLD + 1]; /* буфер должен хранить весь фрагмент */
int blank; /* позиция последнего знака разделителя */
while ((len = getstr(line, MAXLINE)) > 0)
{
while(len != 0) /* можно было бы использовать другую переменную*/
{
/* printf("Начальная длина введенной строки: %d\n", len); */
if (len > FOLD)
{
blank = FOLD - 1; /* на случай, если в введенной строке нет разделителей */
for (i = FOLD - 1; i > 0; --i)
{
if (line[i] == ' ' || line[i] == '\t') {
blank = i;
/* printf("%d\n", blank); */
i = 0; /* Принудительный выход из цикла */
}
}
/* printf("За символом %c на позиции %d будет новая строка\n", line[blank], blank); */
line[blank] = '\n';
copy(fragment, line);
printf("%s", fragment);
for (x = 0; x <= FOLD; ++x)
fragment[x] = '\0';
/* Исключаем выведенный на экран фрагмент из строки */
for (j = 0; j <= len; ++j)
line[j] = line[j + blank + 1]; /* +1 для исключения '\n' */
len = len - blank; /* уменьшаем длину строки */
/* printf("Длина строки без сегмента: %d\n", len); */
/* printf("%s", line); */
}
else
{
printf("%s", line);
len = 0; /* конец цикла */
}
}
}
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;
}
void copy(char to[], char from[])
{
int i;
i = 0;
while ((to[i] = from[i]) != '\n')
++i;
}
$ cc -g -O0 -Wall -o a.out ex_1_22.c
$ ./a.out
C has changed too, although only modestly, and it has spread far beyond its origins as the language of the UNIX operating system. The growing popularity of C, the changes in the language over the years, and the creation of compilers by groups not involved in its design, combined to demonstrate a need for a more precise and more contemporary definition of the language than the first edition of this book provided. In 1983, the American National Standards Institute (ANSI) established a committee whose goal was to produce ‘‘an unambiguous and machine-independent definition of the language C’’, while still retaining its spirit. The result is the ANSI standard for C.
C has changed too, although only modestly, and it
has spread far beyond its origins as the language
of the UNIX operating system. The growing
popularity of C, the changes in the language over
the years, and the creation of compilers by
groups not involved in its design, combined to
demonstrate a need for a more precise and more
contemporary definition of the language than the
first edition of this book provided. In 1983, the
American National Standards Institute (ANSI)
established a committee whose goal was to produce
‘‘an unambiguous and machine-independent
definition of the language C’’, while still
retaining its spirit. The result is the ANSI
standard for C.
программа работает только с короткими строками, а если ввести к примеру:
ОтветитьУдалить123 456 78901234567890 qwer 1
при ограничении строки в 10 символов - начинает глючить. Сам столкнулся с такой проблемой и не могу придумать как ее исправить. И возможно ли вообще ее исправить на данном этапе изучения Си?
По-моему, проще надо относиться к сложным (на первый взгляд) задачам
ОтветитьУдалить#include
#include "text1.h"
#include "text2.h"
#include "text3.h"
#include "text4.h"
/**
В этом решении будем вставлять \n вместо последнего перед MAXLENHTH пробела
В файлах textN.h лежат тестируемые строки в формате обычного массива char
char paraN[]="any text xxxxxxxx any text xxxxxxxxxxxxxxxxx any text \n";
При тестировании прийдется ручками заменять N в paraN ьем, что вы напишете в инклудах
*/
#define MAXLENHTH 80 /* длина строки в параграфе не более 50 позиций */
#define MAXPARAGRAF 10000 /* приемлемый размер параграфа */
#define MAXLINESIZE 1000
int getpara(char array[], char dest[], int start);
int main(void)
{
char text[MAXPARAGRAF];
char para[MAXPARAGRAF];
char formatted[MAXLINESIZE];
int paralength = 0;
int nextstart = 0;
int lastblank = 0; /* позиция последнего пробела перед MAXLENHTH */
int linescount = 1;
char c;
int i;
nextstart = getpara(para1, para, nextstart);
printf("\n\nOriginal text\n%s\nLength=%d\n", para1, nextstart);
printf("\n\nFirst for us \n%s\nLength=%d\n", para, nextstart);
for (i=0; i < nextstart; i++)
{
c = para[i];
if ( c == ' ')
{
lastblank = i;
}
if ( i > MAXLENHTH * linescount )
{
linescount++;
para[lastblank] = '\n';
lastblank = 0;
}
}
printf("\n\nREADY for us \n%s\nLength=%d\n", para, nextstart);
return nextstart;
}
int getpara(char array[], char dest[], int start)
{
int i;
char c;
for (i=start; c=array[i] != '\n'; i++)
{
dest[i] = array[i];
}
if (c=='\n')
{
dest[i] = c;
++i;
}
return i;
}