Salut tout le monde, j'écris un interpréteur BF en C et j'ai rencontré un problème de lecture des fichiers. J'avais l'habitude d'utiliser scanf pour lire la première chaîne, mais vous ne pouviez pas avoir d'espaces ou de commentaires dans votre code BF.
Voici maintenant ce que j'ai.
char *readFile(char *fileName)
{
FILE *file;
char *code = malloc(1000 * sizeof(char));
file = fopen(fileName, "r");
do
{
*code++ = (char)fgetc(file);
} while(*code != EOF);
return code;
}
Je sais que le problème se pose dans la façon dont j'attribue le caractère suivant dans le fichier au pointeur de code, mais je ne suis tout simplement pas sûr de ce que c'est.
Ma connaissance du pointeur fait défaut, ce qui est le point de cet exercice. L'interprète fonctionne très bien, tous utilisant des pointeurs, j'ai juste un problème pour y lire des fichiers.
(Je vais implémenter uniquement la lecture "+ -> <[].") Dans le fichier plus tard, bien que si quelqu'un a un bon moyen de le faire, ce serait bien si vous me le fais savoir!)
Merci d'avance
Il y a un certain nombre de problèmes avec votre code:
char *readFile(char *fileName)
{
FILE *file;
char *code = malloc(1000 * sizeof(char));
file = fopen(fileName, "r");
do
{
*code++ = (char)fgetc(file);
} while(*code != EOF);
return code;
}
code
chaque fois que vous lisez un caractère et vous renvoyez code
à l'appelant (même s'il ne pointe plus vers le premier octet du bloc de mémoire tel qu'il a été renvoyé par malloc
).fgetc(file)
en char
. Vous devez vérifier EOF
avant de transtyper le résultat en char
.Il est important de conserver le pointeur d'origine renvoyé par malloc
afin de pouvoir le libérer plus tard. Si nous ignorons la taille du fichier, nous pouvons toujours y parvenir avec les éléments suivants:
char *readFile(char *fileName)
{
FILE *file = fopen(fileName, "r");
char *code;
size_t n = 0;
int c;
if (file == NULL)
return NULL; //could not open file
code = malloc(1000);
while ((c = fgetc(file)) != EOF)
{
code[n++] = (char) c;
}
// don't forget to terminate with the null character
code[n] = '\0';
return code;
}
Il existe différents appels système qui vous donneront la taille d'un fichier; un exemple courant est stat
.
Développer le code ci-dessus de @dreamlax
char *readFile(char *fileName) {
FILE *file = fopen(fileName, "r");
char *code;
size_t n = 0;
int c;
if (file == NULL) return NULL; //could not open file
fseek(file, 0, SEEK_END);
long f_size = ftell(file);
fseek(file, 0, SEEK_SET);
code = malloc(f_size);
while ((c = fgetc(file)) != EOF) {
code[n++] = (char)c;
}
code[n] = '\0';
return code;
}
Cela vous donne la longueur du fichier, puis procède à sa lecture caractère par caractère.
Voici un moyen simple d'ignorer tout, sauf les personnages de brainfuck valides:
#define BF_VALID "+-><[].,"
if (strchr(BF_VALID, c))
code[n++] = c;
le fichier est ouvert et non fermé pour chaque appel à la fonction également
Je pense que le problème le plus important est que vous incrémentez code
pendant que vous lisez des trucs, puis que vous retournez la valeur finale de code
, c'est-à-dire que vous retournerez un pointeur vers le fin de la chaîne. Vous voudrez probablement faire une copie de code
avant la boucle, et la retourner à la place.
De plus, les chaînes C doivent être terminées par null. Vous devez vous assurer que vous placez un '\0'
Directement après le dernier caractère que vous lisez.
Remarque: Vous pouvez simplement utiliser fgets()
pour obtenir la ligne entière en une seule fois.
L'un ou l'autre devrait faire l'affaire -
char *readFile(char *fileName)
{
FILE *file;
char *code = malloc(1000 * sizeof(char));
char *p = code;
file = fopen(fileName, "r");
do
{
*p++ = (char)fgetc(file);
} while(*p != EOF);
*p = '\0';
return code;
}
char *readFile(char *fileName)
{
FILE *file;
int i = 0;
char *code = malloc(1000 * sizeof(char));
file = fopen(fileName, "r");
do
{
code[i++] = (char)fgetc(file);
} while(code[i-1] != EOF);
code[i] = '\0'
return code;
}
Comme les autres affiches l'ont souligné, vous devez vous assurer que la taille du fichier ne dépasse pas 1000 caractères. N'oubliez pas non plus de libérer la mémoire lorsque vous avez fini de l'utiliser.
Le problème est double: a) vous incrémentez le pointeur avant de vérifier la valeur lue, et b) vous ignorez le fait que fgetc () renvoie un int au lieu d'un char.
Le premier est facilement réparable:
char *orig = code; // the beginning of the array
// ...
do {
*code = fgetc(file);
} while(*code++ != EOF);
*code = '\0'; // nul-terminate the string
return orig; // don't return a pointer to the end
Le deuxième problème est plus subtil - fgetc retourne un int qui que la valeur EOF peut être distinguée de toute valeur chsr possible. La correction utilise un int temporaire pour EOF = check et probablement une boucle while régulière au lieu de do/while.