Попытка чтения файла и сохранение первого ввода в массиве val и второго ввода в массиве wt (вес)

Мне нужно прочитать файл с именем «data.txt» и сохранить первый вход как значение, а второй соответствующий вход как вес. У меня проблемы с их чтением и сохранением значений.

data.txt (example)

3 25
2 20
1 15
4 40
5 50

Вот с чего я начал:

FILE *myFile;
myFile=fopen("data.txt", "r");


int val[20]={0}; //initialize value array to zero
int wt[20]={0}; 
int W=80; //Set capacity to 80
int i;
int n;

while(!feof(myFile)){ 
  fscanf(myFile, "%1d%1d", &val[i], &wt[i]);
}

n = sizeof(val)/sizeof(val[0]);
printf("%d", knapSack(W, wt, val, n));//prints out the maximum value
fclose(myFile);
return 0;

Я отредактировал приведенный выше код следующим образом:

FILE *myFile;
myFile=fopen("data.txt", "r");


int val[20]={0};
int wt[20]={0};
int W=80; //Set capacity to 80
int i;
int n;

for(i=0;i<sizeof(val);i++){
  fscanf(myFile, "%1d%1d", &wt[i],&val[i]);
}

n = sizeof(val)/sizeof(val[0]);
printf("%d", knapSack(W, wt, val, n));//prints out the maximum value
fclose(myFile);
return 0;

Он продолжает выводить 55, когда я использую входные данные из примера data.txt.


person noobGirlCoding    schedule 27.01.2020    source источник
comment
Не могли бы вы уточнить, какие именно ошибки или неправильное поведение вы видите? наличие проблем - не очень информативное описание. Какие вопросы именно?   -  person kaylum    schedule 27.01.2020
comment
Почему while ( !feof (file) ) всегда неверно?   -  person kaylum    schedule 27.01.2020
comment
Спасибо, он ничего не выводил, поэтому я предположил, что именно так я сохранял val и wt из файла.   -  person noobGirlCoding    schedule 27.01.2020
comment
Вы можете упростить жизнь с помощью struct mydata { int val; int wt; }; Затем вы можете просто создать свой массив strct mydata arr[20] = {{ .val = 0; }}; Теперь вы можете координировать каждый val и wt как один объект, например. arr[0].val и arr[0].wt; и т. д.. Читайте построчно с помощью size_t n = 0; while (fscanf(myfile, "%d %d", &arr[n].val, &arr[n].wt) == 2) { n++; } Теперь у вас есть заполненный массив структуры и количество элементов n.   -  person David C. Rankin    schedule 27.01.2020
comment
OT: относительно: myFile=fopen("data.txt", "r"); всегда проверяйте (!=NULL) возвращаемое значение, чтобы убедиться, что операция прошла успешно.   -  person user3629249    schedule 28.01.2020
comment
это: for(i=0;i<sizeof(val);i++){ будет писать за конец массива val[], потому что sizeof возвращает количество байтов, а не количество целых чисел. Предложить: for(i=0;i<(sizeof(val) / sizeof( val[0] );i++){   -  person user3629249    schedule 28.01.2020
comment
относительно: while(!feof(myFile)){ fscanf(myFile, "%1d%1d", &val[i], &wt[i]); } Это не инициализирует и не увеличивает i, поэтому будет использоваться любое случайное значение в стеке, где находится i   -  person user3629249    schedule 28.01.2020
comment
настоятельно рекомендуем циклу while() использовать возвращаемое значение из fscanf() в качестве управляющего значения, а не feof()   -  person user3629249    schedule 28.01.2020
comment
задавая вопрос о проблеме во время выполнения (как и этот вопрос), опубликуйте минимальный воспроизводимый пример, чтобы мы можем воспроизвести проблему и помочь вам отладить ее   -  person user3629249    schedule 28.01.2020


Ответы (2)


Самая большая проблема, с которой вы сталкиваетесь, заключается в том, что вы не контролируете свой цикл чтения с возвратом самого чтения. Например, в вашем случае вы хотели бы:

int i = 0;
while (fscanf(myFile, "%1d%1d", &wt[i],&val[i]) == 2)
    i++;

В конце вашего чтения i будет содержать количество элементов, прочитанных в ваших массивах.

(примечание: вы не сможете правильно использовать любую функцию ввода, если не проверите возврат...)

Вместо чтения значений в отдельные массивы всякий раз, когда вы координируете несколько значений как один объект (например, каждую пару val и wt), вы должны думать struct. Это позволяет вам координировать оба значения как один объект.

Простым примером в вашем случае может быть:

#include <stdio.h>

#define MAXVAL 20   /* if you need a constant, #define one (or more) */

typedef struct {    /* struct with int val, wt + typdef for conveninece */
    int val, wt;
} mydata;

int main (int argc, char **argv) {

    size_t n = 0;                           /* number of elements read */
    mydata arr[MAXVAL] = {{ .val = 0 }};    /* array of mydtata */
    /* use filename provided as 1st argument (stdin by default) */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) {  /* validate file open for reading */
        perror ("file open failed");
        return 1;
    }

    /* read all pairs of values in file into array */
    while (fscanf (fp, "%d %d", &arr[n].val, &arr[n].wt) == 2)
        n++;

    if (fp != stdin)   /* close file if not stdin */
        fclose (fp);

    for (size_t i = 0; i < n; i++)  /* output values */
        printf ("arr[%zu]  %2d  %2d\n", i, arr[i].val, arr[i].wt);
}

Приведенный выше код делает то же самое, что я предложил для обработки цикла чтения при успешном чтении пары значений из файла. Единственное отличие состоит в том, что он координирует значения val и wt в структуре.

Пример использования/вывода

С вашими данными в файле dat/val_wt.txt вы получите следующий вывод:

$ ./bin/read_val_wt dat/val_wt.txt
arr[0]   3  25
arr[1]   2  20
arr[2]   1  15
arr[3]   4  40
arr[4]   5  50

В то время как выше мы читаем непосредственно с помощью fscanf, вы можете сделать ваше чтение немного более надежным, сначала прочитав каждую строку в массив символов, а затем проанализировав нужные значения из массива символов с помощью sscanf. По сути, вы делаете то же самое, но с помощью fgets/sscanf вы можете сделать независимую проверку (1) чтения строки; и (2) анализ необходимой информации из линии. Если у вас есть неправильная строка, это предотвращает влияние сбоя сопоставления на чтение оставшихся строк во входном файле.

Просмотрите все и дайте мне знать, если у вас есть дополнительные вопросы.

person David C. Rankin    schedule 27.01.2020

Ой, тут много мелких проблем...

Во-первых, даже если это не связано, вы постоянно не можете проверить результат входных функций. Это может привести к скрытым проблемам...

Следующее правило: когда вы не получаете ожидаемого, отслеживайте промежуточные значения.

Случались ли вам эти строки:

// uncomment next block for debugging
printf("n=%d\n);
for (i = 0; i < n; i++) {
    printf("%d %d\n", wt[i], val[i]);
}

Вы бы видели

n = 20
3 2
5 2
2 0
1 1
5 4
4 0
5 5
0

показывая, что:

  • n было 20 (не знаю, ожидали ли вы этого)
  • вы считывали свои значения по одной цифре вместо одного целочисленного значения (из-за форматов %1d)

Мой совет:

for (i = 0; i<sizeof(val); i++) {        // do not try to read more than array capacity
    if (2 != fscanf(myFile, "%d%d", &wt[i], &val[i])) break;  // stop when no more data
}

n = i;     // number of actual values

// uncomment next block for debugging
/*
printf("n=%d\n);
for (i = 0; i < n; i++) {
    printf("%d %d\n", wt[i], val[i]);
}
*/
person Serge Ballesta    schedule 27.01.2020