Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Помогите с вещественными числами.

16K
11 марта 2006 года
ReaLeter
4 / / 11.03.2006
Ниже приведен код, в кратце - сохраняет введеннное вещественное число на диск, по нажатию кнопки загружает его в Edit1.

По идее все должно быть тихо и гладко, все числа сохраняет/загружает, вот только при вводе числа 2766077 при загрузке выдает NAN - нечисло , обьясните пожалуйста в чем глюк. Еще есть одно число незапомнил точно какое ввожу nnnnnnnnnn,15 а при загрузке выдает nnnnnnnnnn,1 =(.

void __fastcall TForm1::SaveClick(TObject *Sender)
{
union okpo
{
double num;
char str[8];
};
union okpo uokpo;
uokpo.num=StrToFloat(Edit1->Text);
AnsiString fspr;
FILE *fs;
fs=fopen("temp.txt", "w");
for(int i=0;i<8;i++)
{
fputc(uokpo.str, fs);
}
fclose(fs);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::LoadClick(TObject *Sender)
{
union okpo
{
double num;
char str[8];
};
union okpo uokpo;
FILE *fs;
fs=fopen("temp.txt", "r");
for(int i=0;i<8;i++)
{
uokpo.str=fgetc(fs);
}
fclose(fs);
Edit1->Text=uokpo.num;
}
294
11 марта 2006 года
Plisteron
982 / / 29.08.2003
Цитата:
Originally posted by ReaLeter
Ниже приведен код, в кратце - сохраняет введеннное вещественное число на диск, по нажатию кнопки загружает его в Edit1.

По идее все должно быть тихо и гладко, все числа сохраняет/загружает, вот только при вводе числа 2766077 при загрузке выдает NAN - нечисло , обьясните пожалуйста в чем глюк. Еще есть одно число незапомнил точно какое ввожу nnnnnnnnnn,15 а при загрузке выдает nnnnnnnnnn,1 =(.

void __fastcall TForm1::SaveClick(TObject *Sender)
{
union okpo
{
double num;
char str[8];
};
union okpo uokpo;
uokpo.num=StrToFloat(Edit1->Text);
AnsiString fspr;
FILE *fs;
[COLOR=firebrick] fs=fopen("temp.txt", "wb");[/COLOR]
for(int i=0;i<8;i++)
{
fputc(uokpo.str, fs);
}
fclose(fs);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::LoadClick(TObject *Sender)
{
union okpo
{
double num;
char str[8];
};
union okpo uokpo;
FILE *fs;
[COLOR=firebrick] fs=fopen("temp.txt", "rb");[/COLOR]
for(int i=0;i<8;i++)
{
uokpo.str=fgetc(fs);
}
fclose(fs);
Edit1->Text=uokpo.num;
}



AFAIR, надо так, как я красным выделил.
Объяснить, почему?

16K
11 марта 2006 года
ReaLeter
4 / / 11.03.2006
Цитата:
Originally posted by Plisteron
AFAIR, надо так, как я красным выделил.
Объяснить, почему?



Спасибо огромное, работает. Обьяснение тоже было бы очень кстати для понимания сути =)

294
11 марта 2006 года
Plisteron
982 / / 29.08.2003
Цитата:
Originally posted by ReaLeter
Спасибо огромное, работает. Обьяснение тоже было бы очень кстати для понимания сути =)


Когда ты пишешь:

 
Код:
union okpo
{
double num;
char str[8];
};
union okpo uokpo;
uokpo.num=StrToFloat(Edit1->Text);

У тебя в массиве str записано 8 байт с различными значениями от '\x0' до '\xFF'. Конкретные значения, будем считать, нам неизвестны, они зависят, понятно, от текста в Edit1.
Открываем файл на чтение конструкцией fs=fopen("temp.txt", "r"); -- файл открывается на чтение в текстовом режиме, т.е. принимается, что строка заканчивается на '\x0A', по достижении значения '\x1A' (EOF, сиречь End-of-File) чтение файла прекращается. В твоём случае EOF твоей восьмибайтовой строки был достигнут уже на втором байте (видимо, такое числовое значение было введено в Edit1).
Конструкции fs=fopen("temp.txt", "wb"); и fs=fopen("temp.txt", "rb"); говорят, что файл надо открывать в двоичном виде и читать не до EOF, а до реального конца файла вместе с любыми non-ASCII-символами.
Кстати, я бы немного по-другому юнион сделал, приблизительно так:
Код:
typedef union union_okpo
{
    double num;
    char str[sizeof(double)];
} okpo;

FILE   *fs;
okpo    uokpo         = StrToFloat(Edit1->Text);
// ^^^ Кстати, а если юзер нечисловое значение  в Edit1 введёт?
size_t  howmuch_bytes = sizeof(okpo);

if((fs = fopen("temp.txt", "wb")) != NULL && fwrite(&uokpo, howmuch_bytes, 1, fs) == howmuch_bytes * 1)
/* Если будет массив окпов (или окпей?), то вместо единичек в fwrite() и в howmuch_bytes * 1
 будет размерность массива */
{
    /* Всё  записано нормально, едем дальше */
    fclose(fs);
}
else
{
    /* Обработка ошибки записи*/
}

Дальше аналогично с чтением.
16K
11 марта 2006 года
ReaLeter
4 / / 11.03.2006
Цитата:
Originally posted by Plisteron
файл надо открывать в двоичном виде и читать не до EOF, а до реального конца файла


Спасибо за разяснение.

Цитата:
Originally posted by Plisteron

Кстати, я бы немного по-другому юнион сделал, приблизительно так:
Код:
typedef union union_okpo
{
    double num;
    char str[sizeof(double)];
} okpo;

FILE   *fs;
okpo    uokpo         = StrToFloat(Edit1->Text);
// ^^^ Кстати, а если юзер нечисловое значение  в Edit1 введёт?
size_t  howmuch_bytes = sizeof(okpo);

if((fs = fopen("temp.txt", "wb")) != NULL && fwrite(&uokpo, howmuch_bytes, 1, fs) == howmuch_bytes * 1)
/* Если будет массив окпов (или окпей?), то вместо единичек в fwrite() будет размерность массива */
{
    /* Всё нормально, едем дальше */
}
else
{
    /* Обработка ошибки записи*/
}

Дальше аналогично с чтением.



sizeof() мне неподходит так как есть существующий файл с четкой структурой одной записи - 2 байта номер int, 8 байт второй номер float, 8 байт окпо float, 30 байт название в кодировке DOS и т.д. Проверку на нечисловое проверяю при наборе в Edit1.
Спасибо за fwrite(&uokpo, howmuch_bytes, 1, fs) избавлюсь от цикла =), жалко одно, так как юнионы разных размеров и чар массив в одной записи, что нельзя одну запись в файл скопом вывести =(.

294
11 марта 2006 года
Plisteron
982 / / 29.08.2003
Цитата:
Originally posted by ReaLeter
Спасибо за разяснение.


sizeof() мне неподходит так как есть существующий файл с четкой структурой одной записи - 2 байта номер int, 8 байт второй номер float, 8 байт окпо float, 30 байт название в кодировке DOS и т.д. Проверку на нечисловое проверяю при наборе в Edit1.
Спасибо за fwrite(&uokpo, howmuch_bytes, 1, fs) избавлюсь от цикла =), жалко одно, так как юнионы разных размеров и чар массив в одной записи, что нельзя одну запись в файл скопом вывести =(.


Млын...

 
Код:
typedef struct my_hard_record
{
    int    number;
    double number2;
    okpo   uokpo;
    char   name[30];
    int    i_t_d;
} hard_record;

hard_record x;

И записываешь всю структуру одним fwrite();

а sizeof применена для того, чотбы код переносимый получить. Это под Win32 double 8 байт занимает, а вдруг ты, например, под IBM AS400 или Itanium прогу пишешь? Кто знает, сколько байт там double?
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог