fscanf
означает «сканирование файлов отформатировано », а пользовательские данные примерно как неотформатированные , как вы можете получить.
Вы никогда не должны использовать голые "%s"
форматирование строк данных, когда вы не имеете абсолютного контроля над тем, что можно прочитать.
Лучшее решение - использовать fgets
для чтения строки, поскольку это позволяет предотвратить переполнение буфера.
Затем, когда вы знаете размер вашей строки, это максимальный размер каждой строки, который вам потребуется.Используйте sscanf
для вашего сердца, чтобы получить действительные поля.
И последнее.Вероятно, немного расточительно иметь int*
типы для целых чисел, поскольку вы знаете, что у них уже есть определенный максимальный размер.Я бы использовал вариант без указателя, что-то вроде:
struct Data {
char *sname; char *country;
int a; int b; int c; int d;
char *hsisno;
};
В качестве примера приведу некоторый безопасный код:
#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;
}
, который читает ваш файл исохраняет его в связанном списке.Он выводит:
'Lee' 'AUS' 2 103 2 62 'TRUE'
'Check' 'AUS' 4 48 0 23 'FALSE'
'Mills' 'AUS' 8 236 0 69 'FALSE'
в конце, как и ожидалось.
Я сделал целый ряд ответов о ловушках использования *scanf
функций на неуправляемыхданные (введите user:14860 fgets
в поле поиска выше), некоторые из которых (например, здесь , здесь и здесь ) включают в себя постоянную любимую функциюмой, getLine
, для более безопасного ввода пользователя.