#c #codeblocks #console-output
Вопрос:
У меня возникла эта странная проблема, когда мой код делает именно то, что я хочу, когда я запускаю его через свой отладчик, но он не работает, когда я запускаю его нормально. Что еще более странно, так это то, что я тоже не получаю ошибки во время выполнения. Вот в чем может быть проблема, но я не уверен на 100% в этом:
void calcMostMissed (double *ptr, int totalContestants, int arrSize)
{
//output header
cout << endl << "MOST MISSED QUESTIONS" << endl;
//check how many times a question is missed and its percentage, then output it if it's above 60%
double curQuest = *ptr;
int freq = 0;
int j = 0;
double percentMissed;
for (int i = 0; i <= arrSize; i ) //loop through the missed questions array
{
if (*(ptr i) > 0) //if pointer is pointing at a question number (extra space in array is set to 0)...
{
if (*(ptr i) == curQuest) //then check how often it occurs in the array
freq ;
}
else //if the pointer is not pointing at a question number anymore...
{
//calculate percent missed and output it if its 60% or greater
percentMissed = (static_cast<double>(freq) / totalContestants) * 100;
if (percentMissed >= 60)
{
cout << static_cast<int>(curQuest) << "t" << fixed << setprecision(2) << percentMissed << "%" << endl;
}
// check if the question's percentage missed has already been calculated and evaluated
j ;
curQuest = *(ptr j);
int r = 0;
while (r < j)
{
if (*(ptr r) == curQuest)
{
if (j < arrSize - 1)
{
j ;
curQuest = *(ptr j);
}
}
r ;
}
if (!(j == arrSize - 1 amp;amp; r == arrSize - 1))
{
i = 0;
}
freq = 0;
}
//if the current question variable has been through all missed question, then leave loop
if (curQuest < 1)
{
break;
}
}
}
Что эта функция должна делать в целом, так это находить процент пропущенных по всем пропущенным вопросам и выводить только те, которые превышают 60% включительно.
Это то, что выводит мой отладчик (и как я хочу, чтобы это выглядело):
Enter name of answer key file: batch7a.txt
Enter name of contestant's answers file: allWrongContestants.txt
oo12345678 - 0.00
1 2 3
C A B
A B C
0012387654 - 0.00
1 2 3
C A B
A B C
0012364213 - 0.00
1 2 3
C A B
A B C
Mean: 0.00
Median: 0.00
Mode: 0.00
MOST MISSED QUESTIONS
1 100.00%
2 100.00%
3 100.00%
This is what a normal execution ouputs:
Enter name of answer key file: batch7a.txt
Enter name of contestant's answers file: allWrongContestants.txt
oo12345678 - 0.00
1 2 3
C A B
A B C
0012387654 - 0.00
1 2 3
C A B
A B C
0012364213 - 0.00
1 2 3
C A B
A B C
Mean: 0.00
Median: 0.00
Mode: 0.00
MOST MISSED QUESTIONS
Process returned 0 (0x0) execution time : 14.442 s
Press any key to continue.
My debugger runs through all the way to the end of my program just fine, but for some reason the normal execution is still flawed. Any suggestions are welcome and I’ll clarify anything that I may have forgotten to mention.
If it helps, I am using Code::Blocks as my IDE
Some other info about my code: there are 3 questions and all contestants scored a 0% on the test, meaning all questions have the incorrect answers.
Output: The numbers are the contestant’s ID, next to that is their score, the list of numbers underneath is the question number they got wrong, underneath that are the contestant’s answers, and under that are the correct answers.
This is the function that calls the calcMostMissed function:
void statReport (double *ptr, int totalScores, double *mmqPtr, int arrSize)
{
//calculate mean of scores
double mean = calcMean(ptr, totalScores);
//calculate median of scores
double median = calcMedian(ptr, totalScores);
//calculate mode of scores
double *mode = calcMode(ptr, totalScores);
//output to console the data
cout << "Mean: " << fixed << setprecision(2) << mean << endl;
cout << "Median: " << median << endl;
cout << "Mode: ";
sort(mode, mode totalScores);
int j = 0;
for (int i = 0; i < totalScores; i )
{
if (*(mode i) != -1)
{
if (j == 0)
{
cout << *(mode i);
}
else
{
cout << ", " << *(mode i);
}
j ;
}
}
cout << endl;
//call calcMissedQuestions function
calcMostMissed(mmqPtr, totalScores, arrSize);
//delete pointers
delete[] mode;
mode = nullptr;
delete[] mmqPtr;
mmqPtr = nullptr;
}
И это основная функция:
int main()
{
string answerKeyName;
string contestantAnswerName;
ifstream answerKeyFile;
ifstream contestantAnswerFile;
//ask for file names
cout << "Enter name of answer key file: ";
cin >> answerKeyName;
cout << "Enter name of contestant's answers file: ";
cin >> contestantAnswerName;
//check if files can be opened properly
answerKeyFile.open(answerKeyName, ios::binary);
contestantAnswerFile.open(contestantAnswerName, ios::binary);
if(!answerKeyFile)
{
cout << "Answer key file could not be opened" << endl;
exit(EXIT_FAILURE);
}
if (!contestantAnswerFile)
{
cout << "Contestant's answers file could not be opened" << endl;
exit(EXIT_FAILURE);
}
//find how many contestant's there are
int i = 0;
string temp;
while (contestantAnswerFile.good())
{
getline(contestantAnswerFile, temp);
if (temp != "")
{
i ;
}
}
contestantAnswerFile.clear();
contestantAnswerFile.seekg(0, ios::beg);
//create contestant's score array
double *scorePtr = new double[i];
//create pointer for all missed questions
double *mmqPtr = nullptr;
int arrSize;
//compare the contestant's answers to the answer key, then fill array with score
double score;
for (int c = 0; c < i; c )
{
score = compareAnswers (contestantAnswerFile, answerKeyFile, mmqPtr, i, arrSize);
*(scorePtr c) = score;
}
//create the statistics report
statReport(scorePtr, i, mmqPtr, arrSize);
//delete dynamically allocated array
delete[] scorePtr;
scorePtr = nullptr;
//close files
answerKeyFile.close();
contestantAnswerFile.close();
return 0;
}
Комментарии:
1.
for (int i = 0; i <= arrSize; i )
Это выглядит подозрительно. Допустимые индексы в массивеarrSize
элементов от 0 доarrSize-1
. Ваша программа получает доступptr[arrSize]
— высока вероятность, что это проявит неопределенное поведение при доступе к индексу за пределами границ.2. Я думаю, что
if (curQuest < 1) break;
условие ближе к концу кода срабатывает на первой итерацииi=0
вышеупомянутого цикла, и, следовательно, ничего не печатается. Это каким-то образом преодолевается при запуске программы gdb. Вам, по крайней мере, нужно будет предоставить входные параметры вашей функции, чтобы определить, что пошло не так, или, что еще лучше, опубликоватьmain
программу.3. @Giogre Я добавил как функцию, вызывающую calcMostMissed, так и основную функцию. Надеюсь, это поможет
Ответ №1:
Ниже я думаю, что проблема в том, где она находится, однако я все еще не могу правильно ее скомпилировать, потому что другие функции и входные файлы не предоставляются, вероятно, правильно, чтобы не усугублять вопрос:
double *mmqPtr = nullptr;
определяется в main()
, затем передается в statReport()
функцию, не будучи связанным с каким-либо объектом. После этого он действует как первый параметр для функции calcMostMissed()
и разыменовывается внутри нее, но по-прежнему является a nullptr
, поэтому это приводит к неопределенному поведению.
Существует также проблема индекса за пределами границ внутри цикла, как указано в комментариях.
Комментарии:
1. Это или что-то в этом роде находится на правильном пути. Программа, запущенная под управлением отладчика, часто будет вести себя по-другому. И один конкретный способ заключается в том, что иногда вся память обнуляется под отладчиком, а не обычно.
2. @davidbak таким образом, среда отладки-это своего рода безопасный режим для UB, вызванный невозможностью инициализации переменных.
3. Некоторые из них ведут себя именно так, да. Что может быть проблематично, как выясняет оперативная группа … ничто так не раздражает, как «заставить вашу программу работать на вашем компьютере» только для того, чтобы проверить ее и узнать, что она ломается в другом месте …