Je traite de petits fichiers texte que je veux lire dans un tampon pendant que je les traite, donc j'ai trouvé le code suivant:
...
char source[1000000];
FILE *fp = fopen("TheFile.txt", "r");
if(fp != NULL)
{
while((symbol = getc(fp)) != EOF)
{
strcat(source, &symbol);
}
fclose(fp);
}
...
Est-ce la bonne façon de mettre le contenu du fichier dans le tampon ou est-ce que j'abuse strcat()
?
J'itère ensuite à travers le tampon ainsi:
for(int x = 0; (c = source[x]) != '\0'; x++)
{
//Process chars
}
char source[1000000];
FILE *fp = fopen("TheFile.txt", "r");
if(fp != NULL)
{
while((symbol = getc(fp)) != EOF)
{
strcat(source, &symbol);
}
fclose(fp);
}
Il y a pas mal de problèmes avec ce code:
sizeof(source)
, cela est sujet à des débordements de tampon.La fonction
strcat()
ajoute une copie de la chaîne terminée par un caractère nul s2 à la fin de la chaîne terminée par un caractère nul s1, puis ajoute un "\ 0" se terminant.
Vous ajoutez un caractère (pas une chaîne terminée par NUL!) À une chaîne qui peut ou non se terminer par NUL. Le niquement fois que je peux imaginer que cela fonctionne selon la description de la page de manuel est si chaque caractère du fichier se termine par NUL, auquel cas ce serait plutôt inutile. Alors oui, c'est certainement un terrible abus de strcat()
.
Voici deux alternatives à envisager à la place.
Si vous connaissez à l'avance la taille maximale du tampon:
#include <stdio.h>
#define MAXBUFLEN 1000000
char source[MAXBUFLEN + 1];
FILE *fp = fopen("foo.txt", "r");
if (fp != NULL) {
size_t newLen = fread(source, sizeof(char), MAXBUFLEN, fp);
if ( ferror( fp ) != 0 ) {
fputs("Error reading file", stderr);
} else {
source[newLen++] = '\0'; /* Just to be safe. */
}
fclose(fp);
}
Ou, si vous ne le faites pas:
#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! */
Oui - vous seriez probablement arrêté pour votre terrible abus de strcat!
Jetez un œil à getline (), il lit les données ligne par ligne, mais surtout, il peut limiter le nombre de caractères que vous lisez, afin de ne pas déborder le tampon.
Strcat est relativement lent car il doit rechercher la fin de la chaîne entière à chaque insertion de caractère. Vous devriez normalement garder un pointeur vers la fin actuelle du stockage de chaîne et le passer à getline comme position de lecture de la ligne suivante.
Voir cet article de JoelOnSoftware pour savoir pourquoi vous ne voulez pas utiliser strcat
.
Regardez fread pour une alternative. Utilisez-le avec 1 pour la taille lorsque vous lisez des octets ou des caractères.
Pourquoi n'utilisez-vous pas simplement le tableau de caractères que vous avez? Cela devrait le faire:
source[i] = getc(fp);
i++;
Si vous êtes sur un système Linux, une fois que vous avez le descripteur de fichier, vous pouvez obtenir beaucoup d'informations sur le fichier en utilisant fstat ()
http://linux.die.net/man/2/stat
donc vous pourriez avoir
#include <unistd.h>
void main()
{
struct stat stat;
int fd;
//get file descriptor
fstat(fd, &stat);
//the size of the file is now in stat.st_size
}
Cela évite de chercher au début et à la fin du fichier.
Non testé, mais devrait fonctionner .. Et oui, il pourrait être mieux implémenté avec fread, je laisse cela comme un exercice au lecteur.
#define DEFAULT_SIZE 100
#define STEP_SIZE 100
char *buffer[DEFAULT_SIZE];
size_t buffer_sz=DEFAULT_SIZE;
size_t i=0;
while(!feof(fp)){
buffer[i]=fgetc(fp);
i++;
if(i>=buffer_sz){
buffer_sz+=STEP_SIZE;
void *tmp=buffer;
buffer=realloc(buffer,buffer_sz);
if(buffer==null){ free(tmp); exit(1);} //ensure we don't have a memory leak
}
}
buffer[i]=0;
Il me semble que vous voulez faire peur: