Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Помогите с void*


Автор: Zakhar_Shan 15.8.2012, 08:45
Есть программка которая с бинарного файлика считывает данные. Тип данных не известен.  Пока не дойдешь до секции файла, где и будет содержаться инфа о типе содержащихся данных. Для каждой секции файла, программка создает объект класса, и вписывает туда значения, так как тип изначально не известен то в классе массив значений определен как:
Код

void* vals;

После того, как тип дальнейших данных выясняется, массив vals, определяется под конкретные данные:
Код

void defineArray(int count){
    switch(typeOfValue){
        case charType:{
            vals = calloc(count,BYTES_IN_CHAR);
        };break;
        case intType:{
            vals = calloc(count,BYTES_IN_INT);
        };break;
        case realType:{
            vals = calloc(count,BYTES_IN_REAL);
        };break;
        case doubleType:{
            vals = calloc(count,BYTES_IN_DOUBLE);
        };break;
    };
}


В случаях с intType, realType и doubleType все норм. А вот когда дело касается charType, все плохо. Данные типа char в файлике это записи по 8 символов (константа BYTES_IN_CHAR=8). 
При определении считывание значения в класс, оно пишется при помощи метода:
Код

void KeyWord::defineCharVal(char *val, int ind){
    char *arr  = (char*)vals;
    for (int i = 0; i < BYTES_IN_CHAR; i++) {
        arr[ind*BYTES_IN_CHAR+i]=val[i];
    }
    delete[] val;

}


а считывается:
Код

char* KeyWord::getCharVal(int ind, int &count){
    char *arr = (char*)vals;
    count = BYTES_IN_CHAR;
    char *ret = new char[BYTES_IN_CHAR];
    for (int i = 0; i < count; i++) {
       ret[i]=arr[ind*BYTES_IN_CHAR+i];
    }
    return ret;
}

Так вот, в defineCharVal приходит нормальное значение, а вот считывается фигня...
Помогите плиз, что может быть не так? Ведь с другими типами все норм...


Автор: borisbn 15.8.2012, 10:00
т.к. память выделяется жёстко под BYTES_IN_CHAR байт,
Цитата(Zakhar_Shan @  15.8.2012,  08:45 Найти цитируемый пост)
vals = calloc(count,BYTES_IN_CHAR);

а запись (и чтение) м.б. больше
Цитата(Zakhar_Shan @  15.8.2012,  08:45 Найти цитируемый пост)
arr[ind*BYTES_IN_CHAR+i]=val[i];

то всё это будет работать только если ind == 0. Во всех остальных случаях м.б. всё что угодно

Автор: Cheloveck 15.8.2012, 10:02
Из приведённого кода мало, что понятно. Но, во-первых, при считывании файла, обычно, используют не void *, а char *. Во-вторых, используй http://cplusplus.com/reference/clibrary/cstring/memcpy/ вместо своих подозрительных циклов.

Автор: Zakhar_Shan 15.8.2012, 10:52
Цитата(borisbn @ 15.8.2012,  10:00)
т.к. память выделяется жёстко под BYTES_IN_CHAR байт,
Цитата(Zakhar_Shan @  15.8.2012,  08:45 Найти цитируемый пост)
vals = calloc(count,BYTES_IN_CHAR);

а запись (и чтение) м.б. больше
Цитата(Zakhar_Shan @  15.8.2012,  08:45 Найти цитируемый пост)
arr[ind*BYTES_IN_CHAR+i]=val[i];

то всё это будет работать только если ind == 0. Во всех остальных случаях м.б. всё что угодно

На сколько я понимаю, запись 
Код

vals = calloc(count,BYTES_IN_CHAR);

равносильно выделению памяти count * BYTES_IN_CHAR. т.е. для count=10 и BYTES_IN_CHAR=8 выделится 80 байт?

Добавлено через 2 минуты и 1 секунду
Цитата(Cheloveck @ 15.8.2012,  10:02)
Из приведённого кода мало, что понятно. Но, во-первых, при считывании файла, обычно, используют не void *, а char *. Во-вторых, используй http://cplusplus.com/reference/clibrary/cstring/memcpy/ вместо своих подозрительных циклов.

memcpy копирует с 0 элемента массива, если можно было бы копернуть с n-го... Цены бы не было...

Автор: borisbn 15.8.2012, 11:01
Цитата(Zakhar_Shan @  15.8.2012,  10:52 Найти цитируемый пост)
равносильно выделению памяти count * BYTES_IN_CHAR. т.е. для count=10 и BYTES_IN_CHAR=8 выделится 80 байт?

да. всё правильно. я не усмотрел этот count (давно не пользуюсь calloc)
Цитата(Zakhar_Shan @  15.8.2012,  10:52 Найти цитируемый пост)
memcpy копирует с 0 элемента массива, если можно было бы копернуть с n-го...

Код
memcpy( &dest[ n ], &src[ m ], ...

вообще-то, в коде не видно особых проблем. поставь assert( ind <= count ), что-ли...
или выкладывай весь код

Автор: bsa 15.8.2012, 11:05
Цитата(Zakhar_Shan @  15.8.2012,  11:52 Найти цитируемый пост)
memcpy копирует с 0 элемента массива, если можно было бы копернуть с n-го... Цены бы не было... 
Если бы ты не пользовался void*, то мог бы использовать запись: memcpy(dest + Nd, src + Ns, size);

Автор: Zakhar_Shan 15.8.2012, 11:42
Цитата(borisbn @ 15.8.2012,  11:01)
Цитата(Zakhar_Shan @  15.8.2012,  10:52 Найти цитируемый пост)
равносильно выделению памяти count * BYTES_IN_CHAR. т.е. для count=10 и BYTES_IN_CHAR=8 выделится 80 байт?

да. всё правильно. я не усмотрел этот count (давно не пользуюсь calloc)
Цитата(Zakhar_Shan @  15.8.2012,  10:52 Найти цитируемый пост)
memcpy копирует с 0 элемента массива, если можно было бы копернуть с n-го...

Код
memcpy( &dest[ n ], &src[ m ], ...

вообще-то, в коде не видно особых проблем. поставь assert( ind <= count ), что-ли...
или выкладывай весь код

Да код весь смысла нет выкладывать, даже не знаю что может там пригодиться... Могу сказать, сто методы:
Код

int  getIntVal( int ind){
    int *arr = (int*)vals;
    return arr[ind];

и
Код

void  defineIntVal(int val, int ind){
    int *arr = (int*)vals;
    arr[ind] = val;
}

Работают адекватно...

Автор: Zakhar_Shan 15.8.2012, 14:24
Ошибку нашел  smile , все действительно оказалось в другой части кода, но выкладывать его не было смысла. т.к. Кода много. Спасибо Cheloveck, borisbn и bsa за помощь smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)