| 
| 
 | Вопрос # 5 197/ вопрос открыт / | 
 |  Здравствуйте, уважаемые эксперты!Как на Си (именно на Си :) ) правильно считать значения из файла в массив (количество элементов заранее не известно)?
 Мой код в приложении, вываливается с ошибкой EXC_BAD_ACCESS в строке fscanf(...);
 Заранее, спасибо.
 Приложение:Переключить в обычный режим // IDE: NetBeans 7.0 Beta 2// MacOS 10.5.8 #include <stdio.h>#include <stdlib.h> int main(void) {    FILE *file;    file = fopen("some.txt", "r");    int *Arr = (int*)malloc(2*sizeof(int));    int Len = 0;     while (!feof(file)) {       fscanf(file, "%d ", Arr[Len]);       Len++;       Arr = realloc(Arr, (Len+1)*sizeof(int));    }    fclose(file);     int i;    for (i = 0; i < Len; i++) {        printf("Arr[%d] = %d", i, Arr[i]);    }    return 0;}
Примечание #1 (14 апреля 2011, 22:02): Это int *Arr = (int*)malloc(2*sizeof(int));заменить на это int *Arr = (int*)malloc(sizeof(int));
 двойка там так, остаток эксперементов :)
 
 
|  |   Вопрос задал: IlluminatI (статус: 2-ой класс)Вопрос отправлен: 14 апреля 2011, 21:59
 Состояние вопроса: открыт, ответов: 1.
 |  Ответ #1. Отвечает эксперт: Вадим К Здравствуйте, IlluminatI!Нужно знать, что fscanf требует адреса переменной, а не значения. после этого все стает на свои места. То есть, нужно просто добавить & в строку с fscanf
 
 fscanf(file, "%d", &Arr[Len]);Но у этого кода есть ещё один недостаток - он выделяет на один элемент больше, чем нужно и забывает освободить память в конце. Поэтому программа должна выглядеть как минимум так 
 #include <stdio.h>
#include <stdlib.h>
 
int main(void) {
    FILE *file;
    file = fopen("some.txt", "r");
    int *Arr = NULL;
    int Len = 0;
 
    while (!feof(file)) {
       Len++;
       Arr = realloc(Arr, Len*sizeof(int));
       fscanf(file, "%d", &Arr[Len-1]);
    }
    fclose(file);
 
    int i;
    for (i = 0; i < Len - 1; i++) {
        printf("Arr[%d] = %d\n", i, Arr[i]);
    }
    free(Arr);
    return 0;
}
|  | Ответ отправил: Вадим К (статус: Академик)Время отправки: 14 апреля 2011, 22:24
 Оценка за ответ: 5
 Комментарий к оценке: спасибо) |  
 Мини-форум вопросаВсего сообщений: 3; последнее сообщение — 15 апреля 2011, 10:35; участников в обсуждении: 2. 
|   | IlluminatI (статус: 2-ой класс), 15 апреля 2011, 00:48 [#1]:У меня еще вопрос. Вот инициализация массивов:
 
 float* InpSignal = {NULL};
float* OutSignal = {NULL};
float* TimeArray = {NULL};Вот функция считывания из файла:
 float* ReadFromFile(char *FileName) {
   FILE *file;
   float *Array;
   file = fopen(FileName, "r");
   if (file == NULL)
       return 0;
 
   int Len = 0;
   while (!feof(file)) {
       Len++;
       Array = realloc(Array, Len*sizeof(float));
       fscanf(file, "%f", &Array[Len-1]);
   }
   fclose(file);
   printf("Done.\n");
 
   return Array;
}А вот вызов:
 InpSignal = ReadFromFile("InputSignal.txt");
OutSignal = ReadFromFile("OutputSignal.txt");      
TimeArray = ReadFromFile("TimeList.txt");После всего этого, все три указателя ссылаются на один и тот же адресс, и значения получаются одни и те же, почему так? И как это можно исправить?
 |  
|   | Вадим К (статус: Академик), 15 апреля 2011, 10:15 [#2]:если это новый вопрос - то нужно и создавать новый вопрос  ответ такой - это побочный эффект. И если немного программу поменять, он может пропасть или сильно видоизменится.
 Итак, первое правило любого программиста на С/С++ - все локальный переменные НУЖНО инициализировать перед использованием. Иначе там МУСОР! Но на практике там оказывается не совсем мусор и значением можно угадать с большой вероятностью.
 Посмотрим на приведенный код. Три раза подряд вызывается одна и та же функция. Поэтому оказывается, что локальные переменные, которые размещаются в стеке, оказываются в тех же местах.
 По какой то случайности в первый раз Arr содержало 0 и realloc в этом случае отработал как обычный malloc.
 В следующий вызов функции Arr будет содержать тот же адрес! Так как памяти на том месте ещё достаточно с большой вероятностью, то и размещать новый массив будет там же...
 
 Как же это исправить? нужно внимательнее посмотреть на тот код, который я дал в ответе и найти одну принципиальную разницу
   Галочка "подтверждения прочтения" - вселенское зло. |  
|   | IlluminatI (статус: 2-ой класс), 15 апреля 2011, 10:35 [#3]:Спасибо, разобрался   |  Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |