Динамическое fscanf в массив - PullRequest
0 голосов
/ 10 декабря 2018

Я пытаюсь поместить некоторый текст в структурную часть моего массива - это массив, который принимает часть текста.

Например, моя структура:

struct animal
{
    char animal_Type[11];
    int age;
    int numberOfLegs;
    int walksPerDay;
    char favoriteFood[];
};

Я будузатем введите такие данные, как:

dog,2,4,2,biscuits,wet
cat,5,4,0,biscuits,wet,dry,whiskers
bird,1,2,0,birdseed,biscuits,bread,oats,worms,insects,crackers

У меня есть рабочее решение, которое помещает все значения до прогулок в день в структуру, однако я хочу иметь возможность помещать продукты в любимую еду.У меня есть динамический массив для этого, но я не уверен, как читать оставшийся текст в массив FavoritesFood.

Используемый код:

fp = open("animals.txt","r");
struct animal *animal = malloc(sizeof(sturct animal)*3);
int i = 0;
if(fp != NULL) {
     while(i < 3) {
fscanf(fp,"%s %d %d %d %s",
     animal[i].animal_Type,
     animal[i].age,
     animal[i].numberOfLegs,
     animal[i].walksPerDay,
     animal[i].favoriteFood); // need to be able to enter the string of food into here
i++
}

Как мне поступить?это?

1 Ответ

0 голосов
/ 11 декабря 2018

Во-первых, ваш struct не соответствует тому, что вы сказали в комментариях.

char favoriteFood[];

Выше приведен массив char, поэтому он не может содержать списокиз любимых блюд, за исключением, если бы это была одна строка.А так как размер массива не указан, вы не сможете заполнить его так же, как вы.Вместо этого вам действительно нужно:

char **favoriteFood;
unsigned int favoriteFoodSize;

. Это позволит вам создать расширяющийся список строк, который будет соответствовать любым данным, которые вам нужны.

Что касается чтения, то лучшим способом было бычтобы прочитать всю строку, используя fgets, а затем использовать что-то вроде strtok, чтобы разбить строку на ваш символ-разделитель.Сначала определите очень большую строку для хранения всей строки и char * для хранения каждого поля.

char buffer[1024];
char *token;

А затем для основного цикла будет что-то вроде этого:

while(fgets(buffer,1024,fp)) {
    token=strtok(buffer,",");
    strcpy(beasts[i].animal_Type,token);

    token=strtok(NULL,",");
    beasts[i].age = atoi(token);

    /* etc... */
}

Вам нужно проверить, является ли token когда-либо NULL, чтобы справиться с возможностью коротких линий и обрабатывать это соответственно.А также убедитесь, что строка, скопированная в animal_Type, не длиннее 10 символов ... или, альтернативно, сделайте ее char *, чтобы вы могли иметь строку любого размера.

Для favoriteFoodвам нужно будет использовать realloc, чтобы увеличить его размер, чтобы вместить каждую добавленную новую еду, и продолжать проходить через строку, пока у вас не закончатся токены.

token=strtok(NULL,",");
if(token) {
    beasts[i].favoriteFood=malloc(sizeof(char *));
    beasts[i].favoriteFood[0]=strdup(token); // Need to index using 0 as favoriteFoodSize won't have a value yet
    beasts[i].favoriteFoodSize=1;

    token=strtok(NULL,",");
    while(token) {
        beasts[i].favoriteFood=realloc(beasts[i].favoriteFood,(beasts[i].favoriteFoodSize+1)*sizeof(char *));
        beasts[i].favoriteFood[beasts[i].favoriteFoodSize]=strdup(token);
        beasts[i].favoriteFoodSize++;

        token=strtok(NULL,",");
    }
}

Последняя еда будет иметь\n в нем, так как fgets сохраняет его в буфере, который он читает, так что вы можете использовать его, чтобы сказать, закончили ли вы обработку всех продуктов (вам также нужно будет удалить его из последнего продукта).Или, если у вас его нет, вы знаете, что строка была длиннее, и вам нужно будет читать больше. Но это кажется маловероятным на основе ваших примеров данных.

А так как у вас много памятиВы должны убедиться, что вы проверили возвращаемые значения, чтобы убедиться, что у вас недостаточно памяти.

...