Неожиданное завершение программы в Qt при попытке отобразить файл csv
Не судите строго, это лабораторная работа...
Мне нужно разработать на Qt программу для визуализации табличных данных и вычисления по ним статистических метрик. По нажатию на кнопку "Load data" данные из файла должны быть загружены. В таблице должны отобразиться данные. В результате считывания файла должно быть отображено информационное окно с общим количеством строк в файле, количеством строк содержащих ошибку и количеством успешно считанных строк. В таблице должны быть отображены только те структуры, строки которых, не содержат пустых полей или ошибок в полях. Но при нажатии на кнопку load data происходит неожиданное завершение программы, причем данные считываются в list вроде бы корректно.
Код в mainwindow.cpp:
void MainWindow::onPushButtonLoadDataClicked() {
AppParams params;
params.filename = allocateString(context.filename);
doOperation(Validate, &context, ¶ms);
if (context.fileStatus) {
doOperation(LoadData, &context, ¶ms);
displayDataInTable();
QMessageBox::information(this, "Information", "Count of lines: " + QString::number(context.lines) + "\nSuccess read: " + QString::number(context.successRead) + "\nFailed read: " + QString::number(context.failedRead));
}
else
QMessageBox::critical(this, "ERROR", "Error");
freeString(params.filename);
}
void MainWindow::displayDataInTable() {
ui->tableWidget->clear();
ui->tableWidget->setColumnCount(7);
ui->tableWidget->setHorizontalHeaderItem(0, new QTableWidgetItem("year"));
ui->tableWidget->setHorizontalHeaderItem(1, new QTableWidgetItem("region"));
ui->tableWidget->setHorizontalHeaderItem(2, new QTableWidgetItem("npg"));
ui->tableWidget->setHorizontalHeaderItem(3, new QTableWidgetItem("birth_rate"));
ui->tableWidget->setHorizontalHeaderItem(4, new QTableWidgetItem("death_rate"));
ui->tableWidget->setHorizontalHeaderItem(5, new QTableWidgetItem("gdw"));
ui->tableWidget->setHorizontalHeaderItem(6, new QTableWidgetItem("urbanization"));
int i = 0;
for (Iterator it = context.begin; it.current != context.end.current; next(&it)) {
for (int j = 0; j < 7; j++) {
ui->tableWidget->setItem(i, j, new QTableWidgetItem(QString::fromLatin1(it.current->data->values[j])));
}
i++;
}
}
тут считывается файл
typedef struct CsvReadResult {
List* list;
int linesNum;
int successReadNum;
int failedReadNum;
} CsvFileReadResult ;
int getValuesNum(char* source) {
int result = 1;
for (size_t i = 0; i < strlen(source); i++) {
if (source[i] == ',')
result++;
}
return result;
}
char** getArrayBySeparator(char* source) {
char** arr = createArrayOfStrings(getValuesNum(source));
char* buffer = allocateString("");
int current = 0;
size_t bufferLength = 0;
for (size_t i = 0; i < strlen(source); i++) {
if (source[i] == ',') {
arr[current] = buffer;
buffer = allocateString("");
bufferLength = 0;
current++;
}
else {
if (source[i] != '\n') {
int newLength = bufferLength + 1;
char* newBuffer = (char*)realloc(buffer, newLength + 1);
if (newBuffer != NULL) {
buffer = newBuffer;
buffer[bufferLength] = source[i];
buffer[bufferLength + 1] = '\0';
bufferLength++;
}
}
}
}
arr[current] = buffer;
return arr;
}
int validateRecord(CsvRecord* record) {
int result = SUCCESS;
int count = 7;
if (record->valuesNum != count)
result = ERROR;
else {
int readStatus = 0;
double temp;
readStatus += sscanf(record->values[2], "%lf", &temp);
readStatus += sscanf(record->values[3], "%lf", &temp);
readStatus += sscanf(record->values[4], "%lf", &temp);
readStatus += sscanf(record->values[5], "%lf", &temp);
readStatus += sscanf(record->values[6], "%lf", &temp);
if (readStatus != count - 2)
result = ERROR;
}
return result;
}
int csvReadHeader(CsvRecord* dest, char* filename) {
int result = SUCCESS;
if (dest != NULL) {
FILE* file = fopen(filename, "r");
if (file != NULL) {
char* buffer = (char*)calloc(MAX_LEN, sizeof(char));
fgets(buffer, MAX_LEN, file);
fclose(file);
buffer[strlen(buffer) - 1] = '\0';
char* bufferString = allocateString(buffer);
int count = getValuesNum(bufferString);
char** arrayOfValues = getArrayBySeparator(bufferString);
dest->valuesNum = count;
dest->values = arrayOfValues;
freeString(bufferString);
free(buffer);
}
} else {
result = ERROR;
}
return result;
}
CsvReadResult* readResult(char* filename, char* region) {
CsvReadResult* result = NULL;
CsvRecord* header = allocateCsvRecord();
csvReadHeader(header, filename);
FILE* file = fopen(filename, "r");
if (file!=NULL) {
result = (CsvReadResult*)calloc(1, sizeof(CsvReadResult));
result->linesNum = -1;
result->failedReadNum = -1;
result->successReadNum = -1;
result->list = createList(header);
char* buffer = (char*)calloc(MAX_LEN, sizeof(char));
while (!feof(file)) {
result->linesNum++;
fgets(buffer, MAX_LEN, file);
char* bufferString = allocateString(buffer);
CsvRecord* currentRecord = allocateCsvRecord();
currentRecord->valuesNum = getValuesNum(bufferString);
currentRecord->values = getArrayBySeparator(bufferString);
if (validateRecord(currentRecord)==SUCCESS) {
currentRecord->active = 1;
result->successReadNum++;
if (region == NULL) {
listPushBack(result->list, currentRecord);
}
else if (!stringCmp(currentRecord->values[1], region))
listPushBack(result->list, currentRecord);
else
freeCsvRecord(currentRecord);
}
else {
result->failedReadNum++;
freeArrayOfStrings(currentRecord->values, currentRecord->valuesNum);
freeCsvRecord(currentRecord);
}
freeString(bufferString);
}
free(buffer);
fclose(file);
}
else
freeArrayOfStrings(header->values, header->valuesNum);
return result;
}
list:
typedef struct CsvRecord{
char** values;
int valuesNum;
int active;
} CsvRecord;
typedef struct Node {
CsvRecord* data;
struct Node* next;
} Node;
typedef struct List {
Node* first;
} List;
typedef struct Iterator {
Node* current;
} Iterator;
CsvRecord* allocateCsvRecord() {
CsvRecord* result = NULL;
result = (CsvRecord*)calloc(1, sizeof(CsvRecord));
return result;
}
void freeCsvRecord(CsvRecord* record) {
free(record);
}
List* createList(CsvRecord* record) {
List* result = (List*)calloc(1, sizeof(List));
Node* startNode = (Node*)calloc(1, sizeof(Node));
startNode->data = record;
startNode->next = NULL;
result->first = startNode;
return result;
}
void listPushBack(List* list, CsvRecord* record) {
Node* last = list->first;
while (last->next) {
last = last->next;
}
Node* tmp = (Node*)calloc(1, sizeof(Node));
tmp->data = record;
tmp->next = NULL;
last->next = tmp;
}
void freeList(List* list) {
Node* p = list->first;
while (p != NULL) {
Node* next = p->next;
freeArrayOfStrings(p->data->values, p->data->valuesNum);
freeCsvRecord(p->data);
free(p);
p = next;
}
free(list);
}
Iterator beginActive(List* list) {
Iterator iterator;
Node* firstActive = NULL;
if (list != NULL) {
Node* p = list->first;
while (p->next) {
if (p->data->active) {
firstActive = p;
break;
}
p = p->next;
}
}
if (firstActive != NULL) {
iterator.current = firstActive;
}
return iterator;
}
Iterator endActive(List* list) {
Iterator iterator;
Node* lastActive = NULL;
Node* p = list->first;
while (p != NULL) {
if (p->data->active == 1) {
lastActive = p;
}
p = p->next;
}
iterator.current = lastActive;
return iterator;
}
void next(Iterator* it) {
it->current = it->current->next;
}