Привет народ!
Помогите кто-нибудь, не могу разобраться с записью и чтением файлов, с помощью WinApi
функций (FileOpen(<2 параметра>) , FileRead(<3 параметра>) и FileWrite(<3 параметра>)). Открываю файл, считываю оттуда символ , дальше хочу изменить его на какой-либо другой при помощи switch() :
---------------------//<Отрывок проги>
void __fastcall TMainForm::GetChar()
{
char buf[1]; // можно заменить на char *buf; - без разницы
int fo,fw;
fo=FileOpen(OpenDialog1->FileName ,OF_READ); // можно во время работы проги выбрать файл
fw=FileOpen(Edit1->Text ,OF_WRITE); // можно во время работы проги выбрать файл
while(true)
{
FileRead(fo, buf ,1);
switch(buf) // тут постоянно ошибка
{
case 'q':buf='й'; break; // тут постоянно ошибка
case 'w':buf='q';break; // тут постоянно ошибка
case 'e':buf='p';break; // тут постоянно ошибка
}
if(feof) break;
FileWrite(fw, buf , 1); // тут постоянно ошибка
}
Close(fo); Close(fw);
}
но т.к. тип второго параметра у FileRead(<3 параметра>) и FileWrite(<3 параметра>) есть <void *Buffer> и < const void *Buffer>, что не является значением <LValue>, поэтому компилятор пишет ошибку : "Switch parameters must be LValue."
Если эти API ф-ии заменить поточными fopen(fo,"r"); fgetc(fo); fwrite(fr); то файлы при этом должны быть строго определены и во время работы проги нельзя самому их выбрать (FILE *fo, *fw - тип <const char>), а от этого она только проигрывает (хотя ошибка с switch() - ами пропадает).
Работаю в C++Builder 6.0.
Операционка MS WinXP.
Подскажите кто-нибудь можно ли как-то разрешить эту проблему, пожалуйста!!!
------------------------
Заранее признателен Владмир.
Помогите с fopen(), FileOpen()
Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain
У тебя buf описан как массив. Массив в операторе switch, разумеется, использовать нельзя.
Код: Выделить всё
switch(buf[0])
{
case 'q':buf[0] ='й'; break;
case 'w':buf[0] ='q';break;
case 'e':buf[0] ='p';break;
}
Разница есть и большая. *buf - лишь указатель. Который без инициализации указывает на совершенно произвольную область памяти. Если попробовать туда что-то записать, память будет разрушена.char buf[1]; // можно заменить на char *buf; - без разницы
2 BBB:
Не очень помогло, но всё равно спасибо.
Пардон, конечно же разница есть, я имел ввиду что компилятор это проглатывает и не пишет ошибки.
Не очень помогло, но всё равно спасибо.
BBB писал(а): Разница есть и большая. *buf - лишь указатель.
Пардон, конечно же разница есть, я имел ввиду что компилятор это проглатывает и не пишет ошибки.
-
- Сообщения: 1213
- Зарегистрирован: 26 фев 2004, 13:24
- Откуда: Pietari, Venäjä
- Контактная информация:
Так ты сделал switch(buf[0]) ?Владмир писал(а):2 BBB:
Не очень помогло, но всё равно спасибо.
Конечно не пишет, он конвертирует массив в указатель на первый элемент при вызовах функций. Если передаешь уже указатель, то нужды конвертировать нет. Только проблема в том, что этот указатель не инициализирован.Владмир писал(а): Пардон, конечно же разница есть, я имел ввиду что компилятор это проглатывает и не пишет ошибки.
2B OR NOT(2B) = FF
Absurd писал(а):Так ты сделал switch(buf[0]) ?
Нет, ведь массив должен содержать минимум 1 элемент, но это всё равно массив и в switch()'е та же ошибка.
Absurd писал(а): Конечно не пишет, он конвертирует массив в указатель на первый элемент при вызовах функций. Если передаешь уже указатель, то нужды конвертировать нет. Только проблема в том, что этот указатель не инициализирован.
А как его инициализировать? С помощью "this" ? (я немного путаюсь в массивах и указателях...)
Массив "чего-то" (например, char-ов) - это набор из нескольких этих "чего-то". Т.е.Владмир писал(а):я немного путаюсь в массивах и указателях...)
char ac [10] - набор 10-ти перемеррых типа char.
Указатель на "что-то" - это адрес памяти (число), по которой находится переменная типа "что-то".
Пример из жизни. Улица - это массив домов. Указатель на некий дом - это бумажка, на которой написан адрес этого дома.
Вообще говоря, меня тоже несколько смущает эта СИ-шная "вольность" - смещивать (на уровне языка) понятия "массив" и "указатель". Сам начинал с Паскаля, там такого "бардака" нет. В результате этого в Cи возможны ошибки из-за невнимательности или недопонимания. Например, в пр-ру, куда по смыслу тербуется передать буфер (массив) можно передать указатель, и все накроется медным тазом.
-
- Сообщения: 1213
- Зарегистрирован: 26 фев 2004, 13:24
- Откуда: Pietari, Venäjä
- Контактная информация:
В С/C++ и во всех современных языках (Java, C#, Perl, etc) индексация массивов всегда идет с нуля (0). Массив типа char buff[1] имеет всего один элемент с индексом 0. Массив типа char buff[2] имеет два элемента с индексами 0 и 1. Итд по индукции.Владмир писал(а):Нет, ведь массив должен содержать минимум 1 элемент, но это всё равно массив и в switch()'е та же ошибка.
Выражение "buff[0]" в обоих случаях означает элемент массива (то есть просто char), а не сам массив.
Код: Выделить всё
#include <iostream>
int main(int argc, char** argv) {
char buff[1] = {'a'};
switch (buff[0]) {
case 'a':
std::cout<<"Success!!!\n";
break;
default:
std::cout<<"Fail =(((((((\n";
}
return 0;
}
С помощью операции "Взять адрес '&'" но это изврат в нашем случае - даю только как пример.Владмир писал(а): А как его инициализировать? С помощью "this" ? (я немного путаюсь в массивах и указателях...)
Код: Выделить всё
char c;
char *buff = &c;
2B OR NOT(2B) = FF
-
- Сообщения: 1213
- Зарегистрирован: 26 фев 2004, 13:24
- Откуда: Pietari, Venäjä
- Контактная информация:
Offtopic: зато в Паскале нельзя написать обобщенную функцию, которая к примеру сортирует массив любой длины состоящей из любых структур, что бесит.BBB писал(а):Сам начинал с Паскаля, там такого "бардака" нет.
2B OR NOT(2B) = FF
Absurd писал(а): ... Выражение "buff[0]" в обоих случаях означает элемент массива (то есть просто char), а не сам массив.
Замечательно компилируется и выдает "Success!!!". Не знаю как ты там изнасиловал CBuilder что он у тебя не работает.Код: Выделить всё
switch (buff[0]) { case 'a': std::cout<<"Success!!!\n"; break; default: std::cout<<"Fail =(((((((\n"; }
Ну конечно же это я виноват, проглядел, что у меня: "switch(&buf[0])" , Спасибо!
-------------------------------------------
А вообще у меня получилось почти всё со switch().
Прорамма читает символ, меняет его, записывает изменённый в другой файл,
НО записывает только 1 символ, не зависимо сколько их в читаемом файле!
---------не много подкоректировал:
char buf[1];
int all=0; // счетчик цикла-для проверки
char *buf1;
while(!eof(fr))
{
FileRead(fr,&buf[0],1);
switch(buf[0])
{
case 'q':buf1="й" ; break;
case 'w':buf1="q" ;break;
case 'e':buf1="p" ;break;
}
FileWrite(fw, buf1 , 1);
all++;
}
FileClose(fr);
FileClose(fw);
Label1->Caption=IntToStr(all);
}
--------------------------------
"all" - у меня всегда 0, т.е. цикл не проходит ни разу, значит он сразу находит в читаемом файле
"eof()" ! Хотя этот файл не пуст. Или "fr" это не идентификатор файла?
Подскажите, как правильно определять конец файла?