Если ширина линии установлена, скажем, 80, а 80-й символ находится в середине слова, все слово должно быть помещено в следующую строку. Поэтому при сканировании вы должны запоминать позицию конца последнего слова, длина которого не превышает 80 символов.
Так вот мой, он не чистый; Я вот уже час ломаю себе голову, пытаясь заставить его работать, добавляя кое-что тут и там. Он работает для всех известных мне крайних случаев.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int isDelim(char c){
switch(c){
case '\0':
case '\t':
case ' ' :
return 1;
break; /* As a matter of style, put the 'break' anyway even if there is a return above it.*/
default:
return 0;
}
}
int printLine(const char * start, const char * end){
const char * p = start;
while ( p <= end )
putchar(*p++);
putchar('\n');
}
int main ( int argc , char ** argv ) {
if( argc <= 2 )
exit(1);
char * start = argv[1];
char * lastChar = argv[1];
char * current = argv[1];
int wrapLength = atoi(argv[2]);
int chars = 1;
while( *current != '\0' ){
while( chars <= wrapLength ){
while ( !isDelim( *current ) ) ++current, ++chars;
if( chars <= wrapLength){
if(*current == '\0'){
puts(start);
return 0;
}
lastChar = current-1;
current++,chars++;
}
}
if( lastChar == start )
lastChar = current-1;
printLine(start,lastChar);
current = lastChar + 1;
while(isDelim(*current)){
if( *current == '\0')
return 0;
else
++current;
}
start = current;
lastChar = current;
chars = 1;
}
return 0;
}
В общем, у меня есть start
и lastChar
, которые я хочу установить как начало строки и последний символ строки. Когда они установлены, я выводил на стандартный вывод все символы от начала до конца, затем выводил '\n'
и перехожу к следующей строке.
Сначала все указывает на начало, затем я пропускаю слова с while(!isDelim(*current)) ++current,++chars;
. Когда я это делаю, я вспоминаю последний символ, который был до 80 символов (lastChar
).
Если в конце слова я пропустил свое количество символов (80), я выхожу из блока while(chars <= wrapLength)
. Я вывожу все символы между start
и lastChar
и newline
.
Затем я устанавливаю current
на lastChar+1
и пропускаю разделители (и если это приведет меня к концу строки, мы закончили, return 0
). Установите start
, lastChar
и current
в начало следующей строки.
В
if(*current == '\0'){
puts(start);
return 0;
}
часть предназначена для строк, которые слишком короткие, чтобы их можно было обернуть даже один раз. Я добавил это непосредственно перед написанием этого поста, потому что я попробовал короткую строку, и она не сработала.
Я чувствую, что это можно было бы сделать более элегантным способом. Если у кого-то есть что предложить, я хотел бы попробовать.
И когда я писал это, я спрашивал себя, что произойдет, если у меня будет строка, состоящая из одного слова, длиннее моей длины оболочки. Ну, это не работает. Итак, я добавил
if( lastChar == start )
lastChar = current-1;
перед оператором printLine()
(если lastChar
не переместился, значит, у нас есть слово, которое слишком длинное для одной строки, поэтому нам просто нужно поместить все это в строку в любом случае).
Я убрал комментарии из кода, так как пишу это, но я действительно чувствую, что должен быть лучший способ сделать это, чем тот, который у меня есть, который не нуждался бы в комментариях.
Вот и история о том, как я написал эту вещь. Я надеюсь, что он может быть полезен людям, и я также надеюсь, что кто-то будет недоволен моим кодом и предложит более элегантный способ сделать это.
Следует отметить, что он работает для всех крайних случаев: слова слишком длинные для строки, строки короче одного wrapLength и пустые строки.