fscanf
signifie « scan de fichiers au format » et les données de l'utilisateur est sur le point de non formaté que vous pouvez obtenir.
Vous ne devez jamais utiliser des chaînes de format "%s"
nues sur des données où vous ne disposez pas d'un contrôle absolu sur ce qui peut être lu.
La meilleure solution consiste à utiliser fgets
pour lire une ligne car cela vous permet d'empêcher le débordement de la mémoire tampon.
Ensuite, une fois que vous connaissez la taille de votre ligne, c'est la taille maximale de chaque chaîne dont vous aurez besoin. Utilisez sscanf
à votre guise pour obtenir les champs réels.
Une dernière chose. Il est probablement un peu inutile d'avoir int*
types pour les entiers, puisque vous savez qu'ils ont déjà une taille maximale spécifique. J'utilise la variante non-pointeur, quelque chose comme:
struct Data {
char *sname; char *country;
int a; int b; int c; int d;
char *hsisno;
};
A titre d'exemple, voici un code sûr:
#include <stdio.h>
#include <string.h>
// Here's all the stuff for a linked list of your nodes.
typedef struct sData {
char *sname; char *country; char *hsisno;
int a; int b; int c; int d;
struct sData *next;
} Data;
Data *first = NULL; Data *last = NULL;
#define MAXSZ 100
int main (void) {
char line[MAXSZ], sname[MAXSZ], country[MAXSZ], hsisno[MAXSZ];
int a, b, c, d;
FILE *fIn;
Data *node;
// Open the input file.
fIn = fopen ("file.in", "r");
if (fIn == NULL) {
printf ("Cannot open file\n");
return 1;
}
// Process every line.
while (fgets (line, sizeof(line), fIn) != NULL) {
// Check line for various problems (too short, too long).
if (line[0] == '\0') {
printf ("Line too short\n");
return 1;
}
if (line[strlen (line)-1] != '\n') {
printf ("Line starting with '%s' is too long\n", line);
return 1;
}
line[strlen (line)-1] = '\0';
// Scan the individual fields.
if (sscanf (line, "%s %s %d %d %d %d %s",
sname, country, &a, &b, &c, &d, hsisno) != 7)
{
printf ("Line '%s' didn't scan properly\n", line);
return 1;
}
// Allocate a new node to hold data.
node = malloc (sizeof (Data));
if (node == NULL) {
printf ("Ran out of memory\n");
return 1;
}
node->sname = strdup (sname);
node->country = strdup (country);
node->a = a;
node->b = b;
node->c = c;
node->d = d;
node->hsisno = strdup (hsisno);
node->next = NULL;
if (first != NULL) {
last->next = node;
last = node;
} else {
first = node;
last = node;
}
}
fclose (fIn);
// Output the list for debugging.
node = first;
while (node != NULL) {
printf ("'%s' '%s' %d %d %d %d '%s'\n",
node->sname, node->country, node->a, node->b,
node->c, node->d, node->hsisno);
node = node->next;
}
return 0;
}
qui se lit dans votre fichier et le stocke dans un liste liée. Il sort:
'Lee' 'AUS' 2 103 2 62 'TRUE'
'Check' 'AUS' 4 48 0 23 'FALSE'
'Mills' 'AUS' 8 236 0 69 'FALSE'
à la fin, comme prévu.
Je l'ai fait toute une série de réponses sur les pièges de l'utilisation *scanf
fonctions sur des données non contrôlées (entrer user:14860 fgets
dans la zone de recherche ci-dessus), dont certains (here, here et here, par exemple) inclure une fonction préférée éternelle du mien, getLine
, pour une entrée plus sûre de l'utilisateur.
J'utilise habituellement strtok mais il peut y avoir un meilleur moyen – GWW