Taygrim
¿Cómo verificar si un carácter es un carácter de nueva línea en cualquier codificación en C?
Tengo una tarea para escribir la mía. WC programa. Y si uso solo si (s[i] == '\n')
tiene otra respuesta que la original WC si lo llamo a sí mismo.
Aquí está el código:
typedef struct
{
int newline;
int word;
int byte;
} info;
info count(int descr)
{
info kol;
kol.newline = 0;
kol.word = 0;
kol.byte = 0;
int len = 512;
char s[512];
int n;
errno = 0;
int flag1 = 1;
int flag2 = 1;
while(n = read(descr, s, len))
{
if(n == -1)
error("Error while reading.", errno);
errno = 0;
kol.byte+=n;
for(int i=0; i<n; i++)
{
if(flag1)
{
kol.newline++;
flag1 = 0;
}
if(isblank(s[i]) || s[i] == '\n')
flag2 = 1;
else
{
if(flag2)
{
kol.word++;
flag2 = 0;
}
}
if(s[i] == '\n')
flag1 = 1;
}
}
return kol;
}
Funciona bien para todos los archivos de texto, pero cuando lo llamo al archivo que obtuve después de compilarlo, no da la respuesta. WC da.
La forma de comprobar si un personaje s[i]
es un carácter de nueva línea es simplemente:
if (s[i] == '\n')
Si está leyendo un archivo que se abrió en modo de texto (incluido stdin
), cualquier representación que utilice el sistema subyacente para marcar el final de una línea se traducirá a una sola '\n'
personaje.
Dices que estás tratando de escribir el tuyo wc
programa, y comparando con '\n'
está obteniendo resultados diferentes a los del sistema wc
. No nos has contado lo suficiente como para adivinar por qué sucede eso. Muéstranos tu código y cuéntanos exactamente qué está pasando.
Es posible que tenga problemas si está leyendo un archivo que está codificado de manera diferente, por ejemplo, tratando de leer un archivo de texto en formato Unix en un sistema Windows. Pero entonces wc
tendria el mismo problema.
-
C novato está aquí ‘\n’ no es
"\n"
😀– Contador م
3 de abril de 2019 a las 0:58
-
Este enlace puede ayudar a alguien más adelante. Se trata de no omitir espacios en blanco al leer un archivo.
-Gabriel Arghire
9 de marzo de 2021 a las 15:15
-
@JusticeBringer Quizás, pero el enlace es específico de C++, no de C.
–Keith Thompson
9 de marzo de 2021 a las 19:15
-
De hecho, tienes razón, no le presté atención a eso. Todavía no sabes quién va a necesitar esto más tarde.
-Gabriel Arghire
10 de marzo de 2021 a las 8:45
Hay varios caracteres de nueva línea en ASCII y Unicode.
Los más famosos son \r
y \n
, de ASCII. Técnicamente, estos son retorno de carro y salto de línea. Windows usa ambos juntos \r\n
(técnicamente, el retorno de carro significa ir a la columna 0, el salto de línea significa ir a la siguiente línea, pero nada que yo sepa obedece eso en la práctica), Unix usa solo \n
. Algunos sistemas operativos (no comunes) usan solo \r
.
La mayoría de las aplicaciones se detienen allí y no sufren por ello. Lo que sigue es más teórico.
Unicode complica las cosas. U+000A y U+000B son idénticos a \r
y \n
(misma representación binaria en UTF-8). Luego está U+0085 “siguiente línea”, U+2028 “separador de línea” y U+2029 “separador de párrafo”. También puede verificar la pestaña vertical (U + 000B) si desea verificar todo. Mira aquí: http://en.wikipedia.org/wiki/Newline#Unicode
-
@xtofpernaud, bueno, sé que había un truco con impresoras muy antiguas para hacer que sobreimprimieran caracteres para dibujar, ¡pero en realidad me refería a cualquier cosa que todavía se use generalmente!
– Dave
31 de marzo de 2013 a las 19:58
-
\r\n todavía se usa, por ejemplo, todos los protocolos basados en línea (p. ej., SMTP, IMAP, POP3) y otros (p. ej., encabezados HTTP) usan \r\n como final de línea. Y también si envía datos a un terminal a bajo nivel, estoy bastante seguro de que aún se requiere \r para regresar en la columna 0.
– cerveza
31/03/2013 a las 20:15
-
Si está leyendo en modo texto, no tiene que preocuparse por nada más que
'\n'
. Se traducirá cualquier representación que use el sistema operativo.–Keith Thompson
31/03/2013 a las 20:15
-
@Ale: La terminal es interesante; suena una campana para hacer barras de progreso. HTTP no tiene ninguna forma de manejar un
\r
o\n
por sí solo, por lo que solo significa que se comporta como ventanas, en lugar de obedecer el significado literal de los caracteres.– Dave
31 de marzo de 2013 a las 20:20
-
@KeithThompson: el modo de texto no necesariamente normaliza todo. También puede hacer que los caracteres EOF provoquen el final del archivo literal, por lo que no siempre es lo mejor para usar (personalmente, prefiero manejar los finales de línea yo mismo)
– Dave
31 de marzo de 2013 a las 20:22
Cerveza inglesa
Que yo sepa, no existe una función estándar como la isXXXXX()
unos (el más cercano es isspace()
, lo que también es válido para otras condiciones (espacio, tabulador, avance de formulario…). Simplemente comparar con ‘\n’ debería resolver su problema; dependiendo de lo que considere que es un carácter de nueva línea, es posible que también desee verificar ‘\r’ (retorno de carro). El estándar UNIX como separador de línea es ‘\n’, Mac (antes de OS X) usaba ‘\r’ (ahora ‘\n’ es más común, pero algunas aplicaciones todavía usan ‘\r’, por ejemplo, MS Office), DOS/Windows usa la secuencia “\r\n”.
-
Mac OS X utiliza
\n
y no\r
.– Jonathan Leffler
31 de marzo de 2013 a las 19:54
-
No en todas las aplicaciones (ver, por ejemplo, archivos CSV exportados por Excel en OS X)
– cerveza
31/03/2013 a las 20:00
-
@Ale eso es probablemente más porque Microsoft no notó que había cambiado en la actualización… en general es
\n
ahora, pero no importa porque siempre debe verificar cualquier cosa. Nunca se sabe cuándo un usuario ha copiado un archivo de otro sistema operativo.– Dave
31 de marzo de 2013 a las 20:02
-
Correcto, MS no se dio cuenta de que ahora OS X tal vez esté basado en UNIX 😉 Aclaré mi respuesta.
– cerveza
31 de marzo de 2013 a las 20:04
-
Si está leyendo en modo texto, no tiene que preocuparse por nada más que
'\n'
. Se traducirá cualquier representación que use el sistema operativo.–Keith Thompson
31/03/2013 a las 20:15
Te refieres a
'\n'
?– Inútil
31 de marzo de 2013 a las 19:41
‘\n’ funciona solo en codificación ASCII. me refiero a algo como esdigito() función
– Taygrim
31 de marzo de 2013 a las 19:42
Llama
read(descr)
dóndedescr
es presumiblemente un descriptor de archivo. ¿Cómo se abrió? Y cómo ¿Su salida difiere de la dewc
y en qué entrada?–Keith Thompson
1 de abril de 2013 a las 3:09
descr
se abre en otra parte del programaint descr = open(argv[i], 0);
. Diferencia:wc: 5 27 2520 count.o
my_wc: 6 17 2520 count.o
. En la entrada doy este compilado congcc -std=c99 -c -o count.o count.c
– Taygrim
1 de abril de 2013 a las 6:11
parece que está llamando a wc en un archivo binario… como no está hecho para esto, no estoy seguro de que produzca ningún resultado significativo. Tal vez el problema esté relacionado con líneas “no terminadas” (por ejemplo, si la última no termina con una nueva línea).
– cerveza
1 de abril de 2013 a las 7:59