Aquí es mío que yo estaba trabajando en la actualidad para la diversión en C:
Éstos son mis consideraciones:
1) Prohibida la reproducción de caracteres, solo se imprime en la salida estándar. Por lo tanto, dado que no me gusta modificar los argumentos argv [x], y porque me gusta un desafío, quería hacerlo sin modificarlo.No fui por la idea de insertar '\n'
.
2) No quiero
This line breaks here
para convertirse en
This line breaks
here
por lo que cambiar a caracteres '\n'
no es una opción dada este objetivo.
3) Si el ancho de línea se establece en digamos 80, y el 80º carácter está en el medio de una palabra, la palabra completa debe colocarse en la siguiente línea. Entonces, mientras escanea, debe recordar la posición del final de la última palabra que no superó los 80 caracteres.
Así que aquí está el mío, no está limpio; He estado rompiéndome la cabeza durante la última hora tratando de hacer que funcione, agregando algo aquí y allá. Funciona para todos los casos extremos que conozco.
#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;
}
Así que, básicamente, no tengo start
y lastChar
que desea establecer como el comienzo de una línea y el último carácter de una línea. Cuando se configuran, obtengo una salida para excluir todos los caracteres de principio a fin, y luego imprimo un '\n'
, y continúo con la siguiente línea.
Inicialmente todo apunta al comienzo, luego omito palabras con while(!isDelim(*current)) ++current,++chars;
. Mientras hago eso, recuerdo el último personaje que estaba antes de 80 caracteres (lastChar
).
Si, al final de una palabra, he pasado mi número de caracteres (80), entonces salgo del bloque while(chars <= wrapLength)
. Salí todos los caracteres entre start
y lastChar
y un newline
.
Entonces me puse a current
lastChar+1
y pase delimitadores (y si eso me lleva a la final de la cadena, que hemos terminado, return 0
). Establezca start
, lastChar
y current
al comienzo de la línea siguiente.
La parte
if(*current == '\0'){
puts(start);
return 0;
}
es para las cadenas que son demasiado cortos para ser envuelto ni una sola vez. Lo agregué justo antes de escribir esta publicación porque probé una cadena corta y no funcionó.
Siento que esto podría ser factible de una manera más elegante. Si alguien tiene algo que sugerir, me encantaría probarlo.
Y mientras escribía esto, me preguntaba "¿qué va a pasar si tengo una cuerda que es una palabra que es más larga que mi espectro?" Bueno, no funciona. Por lo que añade el
if(lastChar == start)
lastChar = current-1;
antes de la declaración printLine()
(si lastChar
no se ha movido, entonces tenemos una palabra que es demasiado largo para una sola línea, de modo que sólo tenemos que poner todo en la línea de todos modos) .
Retiré los comentarios del código ya que estoy escribiendo esto, pero realmente siento que debe haber una manera mejor de hacer esto que la que tengo que no necesitaría comentarios.
Así que esa es la historia de cómo escribí esto.Espero que pueda ser útil para las personas y también espero que alguien no esté satisfecho con mi código y proponga una forma más elegante de hacerlo.
Cabe señalar que funciona para todos los casos extremos: palabras demasiado largas para una línea, cadenas que son más cortas que una longitud de envolvente y cadenas vacías.
La pregunta no especifica explícitamente que sea para fuentes de ancho fijo, aunque los ejemplos y el uso en un "editor de texto" lo implican. Solo la respuesta de Yaakov Ellis menciona el ajuste de texto para fuentes de ancho no fijo. – Gnubie