我正在做一個有幾個特定要求的作業。必須有一個名爲TestScores的類,它以分數數組爲參數。如果任何分數爲負數或大於100,則它會引發異常。最後,它必須具有返回所有分數的平均值的成員函數。我沒有足夠的聰明才能找到一種只將數組傳遞給構造函數的方法,所以我還添加了一個int值來說明數組的大小。分段錯誤和神祕的循環行爲
運行代碼(我甚至還沒有到處去測試例外),我不斷收到Segmentation fault錯誤。 Valgrind的和gdb已相當無益,輸出信息,如:
==9765== Jump to the invalid address stated on the next line
==9765== at 0x2200000017: ???
更神祕(至少對我來說),在爲客戶端代碼迴路,我的遞增器,我,不知何故會從0碰着一個在創建TestScores對象後,看似隨機的兩位數字。在之前的版本中,在我開始使用rand()來填充數組之前,我只是沒有增加,並且做了無限循環的事情。
這裏的TestScores.cpp的內容:
#include <iostream>
using std::cout;
using std::endl;
#include "TestScores.h"
#include <stdexcept>
using std::runtime_error;
// Constructor.
TestScores::TestScores(int a[], int s):
_SIZE(s), _scores()
{
// Look at each item in a[], see if any of them are invalid numbers, and
// only if the number is ok do we populate _scores[] with the value.
for (int i = 0; i < _SIZE; ++i)
{
if (a[i] < 0)
{
throw runtime_error ("Negative Score");
}
else if (a[i] > 100)
{
throw runtime_error ("Excessive Score");
}
_scores[i] = a[i];
cout << _scores[i] << " ";
}
cout << endl;
}
// Finds the arithmetic mean of all the scores, using _size as the number of
// scores.
double TestScores::mean()
{
double total = 0;
for (int i = 0; i < _SIZE; ++i)
{
total += _scores[i];
}
return total/_SIZE;
}
// median() creates an array that orderes the test scores by value and then
// locates the middle value.
double TestScores::median()
{
// Copy the array so we can sort it while preserving the original.
int a[_SIZE];
for (int i = 0; i < _SIZE; ++i)
{
a[i] = _scores[i];
}
// Sort the array using selection sort.
for (int i = 0; i < _SIZE; ++i)
{
int min = a[i];
for (int j = i + 1; j < _SIZE; ++j)
{
if (a[j] < min)
{
min = a[j];
a[j] = a[i];
a[i] = min;
}
}
}
// Now that array is ordered, just pick one of the middle values.
return a[_SIZE/2];
}
而這裏的客戶端代碼:
#include <iostream>
#include "TestScores.h"
#include <stdexcept>
#include <cstdlib>
#include <ctime>
using std::exception;
using std::cout;
using std::endl;
int main()
{
const int NUM_STUDENTS = 20,
NUM_TESTS = 4;
int test [NUM_TESTS][NUM_STUDENTS];
// Make random seed to populate the arrays with data.
unsigned seed = time(0);
srand(seed);
// Populate the scores for the individual tests graded for the semester.
// These will all be values between 0 and 100.
for (int i = 0; i < NUM_TESTS; ++i)
{
for (int j = 0; j < NUM_STUDENTS; ++j)
{
test[i][j] = rand() % 100;
cout << test[i][j] << " ";
}
cout << endl;
}
// Now we have the data, find the mean and median results for each test.
// All values should be valid, but we'll handle exceptions here.
for (int i = 0; i < NUM_TESTS; ++i)
{
cout << "For Test #" << i + 1 << endl;
try
{
cout << "i = " << i << endl; // i = 0 here.
TestScores results(test[i], NUM_STUDENTS);
cout << "i = " << i << endl; // i = some random number here.
cout << "Mean: " << results.mean() << endl;
cout << "Median:" << results.median() << endl << endl;
}
catch (exception &e)
{
cout << "Error, invalid score: " << e.what() << endl;
}
cout << "For Test #" << i + 1 << endl;
}
return 0;
}
編輯: 請求頭,以及:
#ifndef TEST_SCORES_H
#define TEST_SCORES_H
class TestScores
{
private:
const int _SIZE;
int _scores[];
public:
// Constructor
TestScores(int a[], int);
double mean() const,
median() const;
};
#endif
我玩弄數組動態,並沒有初始化數組爲空,哪個解決了我的問題,這就是我最終轉入的問題。這導致我遇到了一些後續問題。
在開始動態之前,我嘗試給它初始化數組_scores,並嘗試給它一個應該已經初始化的大小值。這導致編譯器問題。我和老師討論過這個問題,他說除非有硬連線的全局常量,否則你不能爲數組分配空間。也就是說,您無法在構造函數中傳遞大小值來初始化數組。這是真的嗎?如果是這樣,爲什麼?
回想一下,在我看來,如果需要很多值,動態數組會更好,因爲這樣您就不需要內存中的連續空間塊。所以,如果你正在製作小型數組,看起來像浪費空間和時間打造動態數組。這是不是真的?我應該從現在開始做所有的數組嗎?這種經驗當然改變了我對常規數組的用途的看法,至少在涉及到類的時候。另外,雖然我完全相信這個任務,但是我覺得我通過傳遞一個大小參數來違背精神(因爲字面問題陳述寫道:「類構造函數應該接受一組測試分數作爲它的參數「)。除了硬連線的全局常量或大小參數外,有沒有辦法傳遞數組?我發誓我花了一個小時試圖想辦法做到這一點。
你能發佈'TestScores.h'嗎? – QuantumMechanic 2012-04-12 16:18:35
無論如何,分數是多少? – leftaroundabout 2012-04-12 16:20:00
如果您使用的是gcc,請在所有內容中添加「-g」和「-O0」標誌,然後再次運行valgrind:它可能會顯示代碼行號。 – pzanoni 2012-04-12 16:20:31