nt CTests_01View::getFileCount(char* fname){
MSG message;
FILE* file=new FILE;
file=fopen(fname,"r");
if(!file){
AfxMessageBox("getFileCount:Can't open file");
return 0;
}
CHAR* temp=new CHAR[255];
int count=0;
while(!feof(file)){
fgets(temp,250,file);
//strset(temp,0);
count++;
if(::PeekMessage(&message,NULL,0,0,PM_REMOVE)){
::TranslateMessage(&message);
::DispatchMessage(&message);
}
};//end while
fclose(file);
return count;
};
void CTests_01View::GetQuestion(char* category){
CHAR* fname=new CHAR[50]; //Имя файла с вопросами
FILE* infile=new FILE; //Открываемый файл
MSG message; //Сообщение для повышения дружелюбности программы:))
CCheckDialog dlg_check; //Диалог с галочками
CStringDialog dlg_string; //Диалог с полем ввода
CRadioDialog dlg_radio; //Диалог с переключателями
CString lines[6]; //Массив из 6-ти строк
CHAR* newLine=new CHAR[255]; //Строка, считанная из файла
strset(newLine,0); //Заполнение строки
CHAR* tempNewLine=new CHAR[200]; //Промежуочная переменная
strset(tempNewLine,0);
CString ss;
UINT numbers[4];
UINT xc1,xc2=0;
UINT xctemp=0;
int i,j,c=0;
UINT strLength=0;
//-------Выбор файла с вопросами----------//
if(category=="+"){//Выше 1000 вольт
fname="questions+1000.dat";//Имя файла с вопросами
}
if(category=="-"){//До 1000 вольт
fname="questions-1000.dat";//Имя файла с вопросами
}
//-------Выбор файла с вопросами----------//
infile=fopen(fname,"r"); //Открываем файл
if(!infile){//Ошибка открытия файла
AfxMessageBox("GetQuestion:Файл с вопросами не открывается.");
return;
}
int fileCount=getFileCount(fname);//Количество строк в файле
int numOfQuestions=(int)(fileCount/6);//Количество вопросов в файле
if(numOfQuestions!=0){
if(numOfQuestions<5){
ss.Format("%d %d",numOfQuestions,fileCount);
//AfxMessageBox(ss);
AfxMessageBox("GetQuestion:\nНевозможно выполнить тестирование.\nВ файле меньше пяти вопросов.");
return;
};
if(numOfQuestions>=5 && numOfQuestions<=10){
strLength=0;
nMark=0;//Оценка
for( c=1; c<=5; c++){
for(i=0; i<=5; i++){
strset(newLine,0);//Заполнить строку символом с кодом 0
strset(tempNewLine,0);
fgets(newLine,255,infile);
strLength=strlen(newLine);
//ss.Format("%s",newLine);
//AfxMessageBox(ss);
strncpy(tempNewLine,newLine,strLength-1);
//__________________ERROR!!!__________________________________________________________//
//lines.Empty();
lines.Format("%s",tempNewLine);
//AfxMessageBox(lines);
}
if(lines[0]=="radio\0"){
numbers[0]=0;
numbers[1]=1;
numbers[2]=2;
numbers[3]=3;
xc1,xc2=0;
xctemp=0;
for(i=0; i<=20; i++){
xc1=rand()%4;
xc2=rand()%4;
xctemp=numbers[xc1];
numbers[xc1]=numbers[xc2];
numbers[xc2]=xctemp;
};
//AfxMessageBox("radio");
dlg_radio.m_question=lines[1];
dlg_radio.text1=lines[numbers[0]+2];
dlg_radio.text2=lines[numbers[1]+2];
dlg_radio.text3=lines[numbers[2]+2];
dlg_radio.text4=lines[numbers[3]+2];
dlg_radio.DoModal();
for( j=0; j<=3; j++)
if(numbers[j]==0)
break;
if(dlg_radio.m_answer==j)
nMark+=1;
//ss.Format("%f",nMark);
//AfxMessageBox(ss);
} else
if(lines[0]=="check\0"){
//AfxMessageBox("check");
numbers[0]=0;
numbers[1]=1;
numbers[2]=2;
numbers[3]=3;
xc1,xc2=0;
xctemp=0;
for( i=0; i<=20; i++){
xc1=rand()%4;
xc2=rand()%4;
xctemp=numbers[xc1];
numbers[xc1]=numbers[xc2];
numbers[xc2]=xctemp;
};
dlg_check.m_question=lines[1];
dlg_check.text1=lines[numbers[0]+2];
dlg_check.text2=lines[numbers[1]+2];
dlg_check.text3=lines[numbers[2]+2];
dlg_check.text4=lines[numbers[3]+2];
dlg_check.DoModal();
if(dlg_check.m_answer1)
if(numbers[0]==0 || numbers[0]==1)
nMark+=0.5;
if(dlg_check.m_answer2)
if(numbers[1]==0 || numbers[2]==1)
nMark+=0.5;
if(dlg_check.m_answer3)
if(numbers[2]==0 || numbers[2]==1)
nMark+=0.5;
if(dlg_check.m_answer4)
if(numbers[3]==0 || numbers[3]==1)
nMark+=0.5;
} else
if(lines[0]=="string\0"){//------------String-----------------//
dlg_string.m_question=lines[1];
dlg_string.text1=lines[2];
dlg_string.text2=lines[3];
dlg_string.text3=lines[4];
dlg_string.text4=lines[5];
dlg_string.m_answer="";
dlg_string.DoModal();
if(dlg_string.m_answer==dlg_string.text1 ||
dlg_string.m_answer==dlg_string.text2 ||
dlg_string.m_answer==dlg_string.text3 ||
dlg_string.m_answer==dlg_string.text4 )
nMark+=1;
//ss.Format("%f",nMark);
//AfxMessageBox(ss);
//AfxMessageBox("string");
} else {
AfxMessageBox("GetQuestion:Неизвестный тип вопроса");
AfxMessageBox(lines[0]);
return;
}
//for(i=0; i<6; i++)
// lines="";
//strset(newLine,0);
//strset(tempNewLine,0);
//3 строчки повышения дружелюбности:)
if(::PeekMessage(&message,NULL,0,0,PM_REMOVE)){
::TranslateMessage(&message);
::DispatchMessage(&message);
}
};
//Question* quest=new Question[numOfQuestions+1];
//CString lines[6];
//char* newLine=new char[];
}
else
AfxMessageBox("GetQuestion:В файле нет ни одного вопроса");
}
ss.Format("%1.1f",nMark);
AfxMessageBox(ss);
fclose(infile);
//delete infile;
};
Ошибка при повторном вызове процедуры...
OnKillme(){
...
GetQuestion(...);
...
}. При первом нажатии все отлично, а при втором появляется нечто: при том, что строка считывается из одного и того же файла, результат разный. Код прилагаю. Не смотрите на всяческие нерациональности и глупости в коде( только начинаю). Нужное место отмечено комментарием, переменные tempNewLine и newLine конкретно имеют неверные значения при повторном запуске. Функция GetFileCount используется в GetQuestion, потому кладу и её тоже. Посмотрите, кому не лень, чего там не так.
Код:
Замечания:
1. Работа с указателями.
Перечитайте еще раз, что такое указатель. Конструкция вида
Код:
FILE* file = new FILE;
file = fopen(...);
file = fopen(...);
означает следующее:
1) Выделить область памяти размером FILE
2) Записать в переменную file адрес этой области памяти
3) Открыть файл
4) Записать в переменную file адрес на структуру, содержащую информацию о только что открытом файле.
Шаг №4 целиком стирает информацию об аллокированной на шаге 1 памяти. Таким образом, мы получаем утечку памяти.
Правильно писать:
Код:
FILE* file = fopen(...);
Тогда в свежесозданную переменную типа "указатель на FILE" будет записан адрес структуры "информация об открытом файле".
Аналогично и с
Код:
CHAR* fname = new CHAR[50];
fname = "questions-1000.dat";
fname = "questions-1000.dat";
На первом шаге аллокируем область, на втором шаге стираем информацию о ней. Вместо этого записываем в переменную fname адрес строки "questions-1000.dat" (да, эта строка тоже располагается по какому-то адресу в оперативной памяти).
Не надо думать, что после первого шага к переменной fname была навечно приписана аллокированная область, это неверно.
Если хочется записать в аллокированную область некую строку, то надо пользоваться, например, функцией strcpy:
Код:
strcpy( fname, "question-1000.dat" );
2. Закрывать открытое.
Если вы попросили у системы ресурс (память, файл, еще что-то), то не забывайте вернуть его обратно:
Код:
CHAR* string = new CHAR[50];
....
delete [] string;
string = 0; // Это для гарантии, что сдуру string не будет использован дальше. Необязательный, но полезный шаг.
....
delete [] string;
string = 0; // Это для гарантии, что сдуру string не будет использован дальше. Необязательный, но полезный шаг.
3. Работа со строками.
В языке C/C++ нет понятия "строка"! Указатели на char нельзя сравнивать оператором =, т.к. сравниваться будет не содержимое, а адреса в памяти. Для этого есть функции, например:
Код:
if( strcmp( first, second ) == 0 ) {
// строки равны
}
// строки равны
}
С учетом всего вышесказанного, правильно будет спрашивать не "почему во второй раз не получилось", а "почему она один раз отработала"?
Премного благодарствую, о повелитель C++! Если бы мне кто-нибудь раньше мог так объяснить как на самом деле обстоят дела... Эх! Тяжелое детство:) Еще раз спасибо, будем учиться.
Цитата: tarekon
:
В языке C/C++ нет понятия "строка"!
В языке C/C++ нет понятия "строка"!
Вполне есть, тем более в C++ )