2017-02-16 17 views
0

Я делаю программу, которая считывает два набора данных (float) из двух разных TXT-файлов, а затем передает эти данные в два разных массива, которые будут использоваться в дальнейших расчетах. Однако, когда я пытаюсь использовать динамическое распределение более одного раза, что-то идет не так, и данные, похоже, не сохраняются в массиве.Как использовать более одного динамического распределения для программирования на C?

Следующая упрощенная программа, кажется, работает нормально:

#include <stdio.h> 
#include <stdlib.h> 
#include <math.h> 

int main() 
{ 
    float *VarA; 
    int n = 0; 
    int *counter; 
    int i; 
    FILE *input1; 

    input1 = fopen("C:\\Users\\...test.txt","r"); 

    VarA = (float*)calloc(20001, sizeof(float)); 

    for(i = 0; i < 20001; i++) 
    { 
     fscanf(input1,"%f",&VarA[i]); 
     printf("%f\n",VarA[i]); 
    } 

    free(VarA); 

    fclose(input1); 

    return 0; 
} 

успешно показывает данные, хранящиеся в массиве Vara. Однако, если я ввожу новый массив, чтобы подсчитать количество строк в файле (который необходим для моих дальнейших расчетов), я просто получить значение 0,000000 из каждого элемента массива:

#include <stdio.h> 
#include <stdlib.h> 
#include <math.h> 

int main() 
{ 
    float *VarA; 
    int n = 0; 
    int *counter; 
    int i; 
    FILE *input1; 

    input1 = fopen("C:\\Users\\...test.txt","r"); 

    counter = (int*)calloc(100000, sizeof(int)); 

    while(fscanf(input1,"%f",&counter[n]) != EOF) 
    { 
     n++; 
    } 

    free(counter); 

    printf("n = %i\n", n); 

    VarA = (float*)calloc(n, sizeof(float)); 

    for(i = 0; i < n; i++) 
    { 
     fscanf(input1,"%f",&VarA[i]); 
     printf("%f\n",VarA[i]); 
    } 

    free(VarA); 

    fclose(input1); 

    return 0; 
} 

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

+5

'while (fscanf (input1,"% f ", & counter [n])! = EOF)' - вы указываете '% f' при чтении в' int'. Это может привести не только к сохранению неправильного значения, но и к неопределенному поведению в некоторых случаях. – yeputons

+2

Возможный дубликат [Сброс указателя на начало файла] (http://stackoverflow.com/questions/32366665/resetting-pointer-to-the-start-of-file) –

+0

Обратите внимание, что нет необходимости в первом ' calloc() ', поскольку вы можете просто читать в фиктивную переменную и не показывать результат. –

ответ

4

(по крайней мере) две основные проблемы: во-первых,

counter = (int*)calloc(100000, sizeof(int)); 
while(fscanf(input1,"%f",&counter[n]) != EOF) { 
    n++; 
} 
free(counter); 

в основном говорит «Хватай мне кусок памяти, заполнить его данными, как я прочитал файл, а затем выбросить его никогда не использовать его «. Наверное, не то, что вы намеревались. Затем

VarA = (float*)calloc(n, sizeof(float)); 
for (i = 0; i < n; i++) { 
    fscanf(input1,"%f",&VarA[n]); 
    printf("%f\n",VarA[n]); 
} 
free(VarA); 

, который говорит, «захватить большую часть памяти, а затем считывать данные с после конца файла я только что прочитал все, от, положил его туда, а затем выбросить.»

Если вы хотите снова прочитать данные из того же файла, вам придется закрыть его, чтобы открыть его (или «искать» до начала). И если вы хотите что-то сделать с этим, вам придется сделать это до того, как освободите() загрузите память.

+0

Спасибо Ли. Несмотря на ошибку int-float, основная проблема заключалась в том, что я не использовал перемотку (input1). Мне нужно подсчитать количество строк, чтобы узнать размер массива, который я выделил (каждая строка файла имеет только одно число с плавающей точкой). Я решил это, используя: while (fscanf (input1, "% f") == 1) n ++; – user3277482

+0

Обычный способ, который делается в библиотеках (но, вероятно, слишком сложный для ученика), заключается в том, чтобы начать с выделения небольшого числа (например, 16) указателей в массиве, а затем начать чтение файла. Всякий раз, когда массив заполняется, 'realloc' он до 3/2 его текущего размера, скопируйте указатели и продолжайте. Это гарантирует, что количество распределений будет достаточно небольшим (O (log (n)), вы только читаете файл один раз, и все, что он стоит, - это немного потерянная память. Вот как работают, например, динамические массивы Java. –

3
counter = (int*)calloc(100000, sizeof(int)); 
     // ^--- `int*`    ^--- `int` 
          // v--- `int` pointer 
while(fscanf(input1,"%f",&counter[n]) != EOF) 
        // ^--- `float` designator 

Вы видите какие-либо несоответствия здесь? Вы выделили int с, а затем передается указатель на эти int с до fscanf говоря это они float с (вы лёжа к fscanf!). Согласно стандартному проекту C n1570, section 7.21.6.2p10 это представляет собой неопределенное поведение:

Если этот объект не имеет соответствующий тип, или если результат преобразования не могут быть представлены в объекте, поведение не определено.

Мое предложение было бы использовать модификатор подавления * назначения здесь, например:

while (fscanf(input1, "%*f") != 1) n++; 

Обратите также внимание, как я изменил чек от EOF к 1.Вы можете найти более подробную информацию о возвращаемых значениях из fscanfhere (вы действительно должны читать, что перед использованием любого scanf функции о связанных, и остановить гадать, так как угадывание в C может быть вредные).

Кроме того, вы должны rewind файл, как только он достигает EOF, в противном случае каждый вызов fscanf после этой петли возвратит EOF:

rewind(input1); 

P.S. Don't cast malloc in C. Это относится к calloc и realloc.

+0

Thank вы для вашего ответа. Это очень помогло мне, потому что теперь я знаю, что мне не нужно создавать другую переменную, чтобы подсчитать количество строк. И вы правы, мне нужно было использовать перемотку. работает правильно Однако есть две проблемы остающийся Во-первых, это не сработало:.. время (! fscanf (input1, "% * е") = 1) п ++; Однако он работал: время (fscanf (input1, «% f») == 1) n ++; Другое дело: когда я пытаюсь загрузить другой файл, так же, как и с первым, я могу распечатать данные только один из массивов, а не из обоих. Я не знаю, что происходит. – user3277482