Esto está mal. strcat concatena cadenas. Incluso si &symbol es un char *, no está terminado en nulo. Deberías usar fgets o fread. También, strcat va a ser lento en su caso de todos modos porque escanea source cada vez que necesita agregar un carácter.
– Alok Singhal
8 de enero de 2010 a las 16:50
Sin mencionar que leer un carácter a la vez será mucho más lento que usar fread.
– Nick Mayer
8 de enero de 2010 a las 16:57
@Nick: No sé acerca de ‘mucho más lento’: debido al almacenamiento en búfer de io y posiblemente a la inserción de las llamadas a funciones, el impacto en el rendimiento no necesariamente debe ser tan grande; utilizando fread() aunque sigue siendo una buena idea
– Cristóbal
8 de enero de 2010 a las 17:07
por cierto: no consideraría un archivo de texto de 1m ‘pequeño’;)
– Cristóbal
8 de enero de 2010 a las 17:09
Busque en mmap() para mapear en memoria el archivo. Tenga cuidado con los desbordamientos de búfer. No use strcat(): incluso si soluciona los problemas con la terminación nula, le da un comportamiento cuadrático que es malo en los archivos de megabytes y un desastre en los archivos de gigabytes.
Es muy lento (está extrayendo el búfer un carácter a la vez).
Si el tamaño del archivo ha terminado sizeof(source)esto es propenso a desbordamientos de búfer.
Realmente, cuando lo miras más de cerca, este código no debería funcionar en absoluto. Como se indica en las páginas man:
los strcat() agrega una copia de la cadena terminada en nulo s2 al final de la cadena terminada en nulo s1, luego agrega un ‘\0’ de terminación.
Está agregando un carácter (¡no una cadena terminada en NUL!) a una cadena que puede o no terminar en NUL. los solamente El momento en que puedo imaginar que esto funcione de acuerdo con la descripción de la página de manual es si cada carácter en el archivo termina en NUL, en cuyo caso esto sería bastante inútil. Así que sí, esto es definitivamente un terrible abuso de strcat().
Las siguientes son dos alternativas para considerar usar en su lugar.
Si conoce el tamaño máximo del búfer con anticipación:
#include <stdio.h>
#include <stdlib.h>
char *source = NULL;
FILE *fp = fopen("foo.txt", "r");
if (fp != NULL) {
/* Go to the end of the file. */
if (fseek(fp, 0L, SEEK_END) == 0) {
/* Get the size of the file. */
long bufsize = ftell(fp);
if (bufsize == -1) { /* Error */ }
/* Allocate our buffer to that size. */
source = malloc(sizeof(char) * (bufsize + 1));
/* Go back to the start of the file. */
if (fseek(fp, 0L, SEEK_SET) != 0) { /* Error */ }
/* Read the entire file into memory. */
size_t newLen = fread(source, sizeof(char), bufsize, fp);
if ( ferror( fp ) != 0 ) {
fputs("Error reading file", stderr);
} else {
source[newLen++] = '\0'; /* Just to be safe. */
}
}
fclose(fp);
}
free(source); /* Don't forget to call free() later! */
Probablemente también desee anular la terminación de su búfer. En su segundo ejemplo de código, dejó espacio para el nulo, pero en realidad no lo configuró; en tu primera, te olvidaste de dejar espacio para el nulo.
–Brian Campbell
8 de enero de 2010 a las 17:10
+1 por el uso de ftell y malloc. Este es el camino a seguir.
– cigarro
8 de enero de 2010 a las 17:25
@Mark: tienes razón, y estoy seguro de que lo sabes, pero sizeof(int) puede ser 1. @Michael, digamos que leo un carácter ‘A’ en symbol. Luego, &symbol (incluso si symbol es char) es un puntero que apunta a 'A' seguida de datos aleatorios. Si symbol es un inty sizeof(int) > 1luego &symbolcuando se convierte en char *puntos a 'A' seguido por 0 o 0dependiendo de la endianidad de la máquina.
– Alok Singhal
8 de enero de 2010 a las 18:49
@Alok, Mark: Olvidé que getc() devuelve un int, no un char. Wow, eso es muy sutil.
– Miguel
8 de enero de 2010 a las 21:55
stackoverflow.com/a/238607/309483: “Si usa ftell, entonces debe abrir el archivo en modo binario. Si lo abre en modo de texto, ftell solo devuelve una “cookie” que solo puede usar fseek”.
– Janus Troelsen
18/10/2012 a las 22:16
Martín Beckett
¡Sí, probablemente serías arrestado por tu terrible abuso de strcat!
Eche un vistazo a getline(), lee los datos una línea a la vez, pero lo más importante es que puede limitar la cantidad de caracteres que lee, para que no se desborde el búfer.
Strcat es relativamente lento porque tiene que buscar el final en toda la cadena en cada inserción de carácter. Normalmente mantendría un puntero al final actual del almacenamiento de cadenas y lo pasaría a getline como la posición para leer la siguiente línea.
Si está en un sistema Linux, una vez que tenga el descriptor de archivo, puede obtener mucha información sobre el archivo usando fstat()
Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos.
Configurar y más información
Esto está mal.
strcat
concatena cadenas. Incluso si&symbol
es unchar *
, no está terminado en nulo. Deberías usarfgets
ofread
. También,strcat
va a ser lento en su caso de todos modos porque escaneasource
cada vez que necesita agregar un carácter.– Alok Singhal
8 de enero de 2010 a las 16:50
Sin mencionar que leer un carácter a la vez será mucho más lento que usar
fread
.– Nick Mayer
8 de enero de 2010 a las 16:57
@Nick: No sé acerca de ‘mucho más lento’: debido al almacenamiento en búfer de io y posiblemente a la inserción de las llamadas a funciones, el impacto en el rendimiento no necesariamente debe ser tan grande; utilizando
fread()
aunque sigue siendo una buena idea– Cristóbal
8 de enero de 2010 a las 17:07
por cierto: no consideraría un archivo de texto de 1m ‘pequeño’;)
– Cristóbal
8 de enero de 2010 a las 17:09
Busque en mmap() para mapear en memoria el archivo. Tenga cuidado con los desbordamientos de búfer. No use strcat(): incluso si soluciona los problemas con la terminación nula, le da un comportamiento cuadrático que es malo en los archivos de megabytes y un desastre en los archivos de gigabytes.
–Jonathan Leffler
8 de enero de 2010 a las 17:45