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

Ваш аккаунт

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

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

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

Ошибка при повторном вызове процедуры...

311
24 ноября 2008 года
plastictown
309 / / 08.01.2006
Здравствуйте, товарищи! Сделал обработчик LBUTTONDOWN
OnKillme(){
...
GetQuestion(...);
...
}. При первом нажатии все отлично, а при втором появляется нечто: при том, что строка считывается из одного и того же файла, результат разный. Код прилагаю. Не смотрите на всяческие нерациональности и глупости в коде( только начинаю). Нужное место отмечено комментарием, переменные tempNewLine и newLine конкретно имеют неверные значения при повторном запуске. Функция GetFileCount используется в GetQuestion, потому кладу и её тоже. Посмотрите, кому не лень, чего там не так.

Код:
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;
};
562
24 ноября 2008 года
tarekon
175 / / 19.08.2003
:eek: Только что на моих глазах жестоко и цинично надругались над языком С++.

Замечания:
1. Работа с указателями.
Перечитайте еще раз, что такое указатель. Конструкция вида
 
Код:
FILE* file = new FILE;
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 была навечно приписана аллокированная область, это неверно.

Если хочется записать в аллокированную область некую строку, то надо пользоваться, например, функцией strcpy:
 
Код:
strcpy( fname, "question-1000.dat" );


2. Закрывать открытое.
Если вы попросили у системы ресурс (память, файл, еще что-то), то не забывайте вернуть его обратно:
 
Код:
CHAR* string = new CHAR[50];
....
delete [] string;
string = 0;     // Это для гарантии, что сдуру string не будет использован дальше. Необязательный, но полезный шаг.


3. Работа со строками.
В языке C/C++ нет понятия "строка"! Указатели на char нельзя сравнивать оператором =, т.к. сравниваться будет не содержимое, а адреса в памяти. Для этого есть функции, например:
 
Код:
if( strcmp( first, second ) == 0 ) {
       // строки равны
}



С учетом всего вышесказанного, правильно будет спрашивать не "почему во второй раз не получилось", а "почему она один раз отработала"?
311
24 ноября 2008 года
plastictown
309 / / 08.01.2006
Премного благодарствую, о повелитель C++! Если бы мне кто-нибудь раньше мог так объяснить как на самом деле обстоят дела... Эх! Тяжелое детство:) Еще раз спасибо, будем учиться.
240
25 ноября 2008 года
aks
2.5K / / 14.07.2006
Цитата: tarekon
:
В языке C/C++ нет понятия "строка"!



Вполне есть, тем более в C++ )

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог