Я довольно плохо знаком с C ++ и программированием в целом, и я использую Visual Studio 2013 Desktop для написания простой программы для сбора и выполнения некоторых операций с данными из файла .CSV. Программа, кажется, компилируется и работает нормально, и просит меня ввести имя для файла, который будет открыт. Как я и предполагал, если я введу неверное имя файла, программа отобразит сообщение об ошибке и завершит работу, однако, если я введу правильное имя, я получу сообщение, которое говорит
«Необработанное исключение в 0x0F16A9E8 (msvcr120d.dll) в TestIO.exe: 0xC0000005: Местоположение чтения нарушения доступа 0xCCCCCCC0.»
С вариантами, чтобы сломать или продолжить. Если я нажимаю «Продолжить», он снова отображает одно и то же сообщение и продолжается бесконечно, пока я не нажму «Break» и не остановлю отладку. Я понятия не имею, что здесь происходит, кто-нибудь может пролить свет на это? Это будет высоко ценится.
Редактировать: вот мой главный (). Надеюсь, это поможет больше, извините, что не включил его раньше.
int main()
{
int numDays = 0, streams;
string* date;
string line, filename;
DailyData* days;
cout << "Enter file name: ";
getline(cin, filename);
ifstream infile;
infile.open(filename);
if (infile.fail())
{
cout << "Error opening input file" << endl;
return 0;
}
while (getline(infile, line))
numDays++;
date = new string[numDays];
for (int i = 0; i < numDays; i++)
getline(infile, date[i]);
days = new DailyData[numDays];
for (int i = 0; i < numDays; i++)
{
getData(date[i], streams);
days[i] = DailyData(date[i], streams);
}
cout << "Max Streams: " << maxStreams(days, numDays) << endl;
cout << "Min Streams: " << minStreams(days, numDays) << endl;
cout << "Avg Streams: " << average(days, numDays) << endl;
cout << "Tot Streams: " << total(days, numDays) << endl;
delete[] days;
delete[] date;
infile.close();
return 0;
}
Редактировать 2: Вот некоторые вещи, которые вы, ребята, просили
void getData(string& d, int& s)
{
int start = 0, end = 0, i = 0;
string p[14];
while (start != string::npos)
{
end = d.find(",", start);
p[i] = d.substr(start, end - start);
start = end + 1;
i++;
}
d = p[0];
s = atoi(p[5].c_str());
}
И вот DailyData с его конструкторами
class DailyData
{
public:
DailyData() :date("NULL"), streams(0){}
DailyData(string d, int s) :date(d), streams(s){}
string getDate(){ return date; }
int getStreams(){ return streams; }
friend ostream& operator << (ostream&, DailyData&);
private:
string date;
int streams;
};
Редактировать 3: я изменил свой код, чтобы использовать векторы вместо массивов. Наряду с изменением int main () я позаботился об изменении аргументов во всех определениях / объявлениях функций. Я все еще получаю ту же ошибку Unhandled Exception, которую я получил изначально. Вот новый фрагмент кода:
vector<string> date;
vector<DailyData> days;
//...
while (getline(infile, line))
{
date.push_back(line);
getData(date.back(), streams);
days.push_back(DailyData(date.back(), streams));
}
numDays = days.size();
Похоже, ваш код вызывает getline для входного файла после того, как вы уже прочитали до конца файла
while (getline(infile, line))
numDays++;
// above reads every line in the file,
// then you call this, even though while(getline) has returned false:
for (int i = 0; i < numDays; i++)
getline(infile, date[i]);
Если вы новичок в программировании, всегда используйте фигурные скобки, чтобы показать тело цикла, чтобы вы могли увидеть, где начинается и заканчивается выполнение блока цикла.
Также на практике лучше всего научиться использовать отладчик. Это будет самая ценная вещь, которую вы когда-либо делаете как программист.
Редактировать:
вот как вы можете использовать динамически изменяемый вектор вместо массива с фиксированным размером:
std::vector<string> dates;
//...
while( getline(infile, line) )
{
dates.push_back(line);
}
Если вам нужна дополнительная информация, ищите вектор C ++.
Edit2:
Теперь, когда код для getData был опубликован, я думаю, что проблема там. Для начала этот код:
while (start != string::npos)
{
end = d.find(",", start);
p[i] = d.substr(start, end - start);
start = end + 1;
i++;
}
выглядит очень опасно.
p[i] = d.substr(start, end - start);
приведет к странному поведению, если end == string :: npos, что будет происходить всякий раз, когда d.find не находит запятую.
аналогично начало = конец + 1 будет не делай то, что ожидаешь, если end == string :: npos
далее p [i] = … будет работать только для значений i меньше 13. Я не вижу никаких проверок, чтобы гарантировать это.
Моим первым предложением было бы проверить, является ли end == string :: npos, и выполнять другие операции, только если это не так.
Надеюсь, это поможет, поведение этого кода сильно зависит от того, как выглядят ваши входные данные, поэтому лучше всего использовать отладчик.