I'm writing a function (*rwObjects()
) that will read a formatted file and save it's strings, one object at a time. Unfortunately, it's for my studies which have a restriction - stdio.h, stdlib.h and string.h is practically all I can use.
Here's the problem: whenever I run the code, when it gets to the fclose(input)
, VS17 says my project's triggered a breakpoint, and then opens a tab that says "wntdll.pdb not loaded" or something.
The question is: how do I not trigger the breakpoint and close the file properly? Or, if the problem isn't in the file, where is it?
Code (C):
#define _CRT_SECURE_NO_WARNINGS
#define cnCOUNTRY_LENGTH 3
#define cnOBJECT_NAME_LENGTH 30
#define cnOBJECT_MAX 1000
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//--Поле объекта objectType--
//Country (0) - строка названия страны
//ObjectName (1) - строка названия объекта
//Square (2) - площадь объекта
//Error (3) - ошибка в содержании строки
typedef enum IOOptions {Country, ObjectName, Square, Error} IOType;
//--Тип обрабатываемых объектов--
//char Country - строка названия страны
//char ObjectName - строка названия объекта
//int Square - площадь объекта
typedef struct object {
char Country[cnCOUNTRY_LENGTH];
char ObjectName[cnOBJECT_NAME_LENGTH];
int Square;
} objectType;
//--Копирование текущего элемента строки objects.txt--
//strMod - Строка, в которую идёт копирование
//strPos - Позиция в считываемой строке
//strBlueprint - Строка, из которой идёт копирование
//writeType - Поле объекта objectType. При "Country" - переводит вводимые символы в верхний регистр ('a' -> 'A' и т.д.)
void copyInputStr(char *strMod, int *strPos, char *strBlueprint, IOType writeType) {
for (*strPos; *strBlueprint != ' ' && *strBlueprint != '\n' && *strBlueprint != NULL; *strPos = *strPos + 1) {
*strMod = *strBlueprint;
if (writeType == Country) toupper(*strMod);
strBlueprint++; strMod++;
}
}
//--Запись текущего элемента строки objects.txt в текущий объект--
//strInput - Строка, из которой идёт запись
//objectOutput - Объект, в который идёт запись
//writeType - Поле объекта, в которое идёт запись
void writeObject(char *strInput, objectType *objectOutput, IOType writeType) {
if (writeType == Country)
strcpy(objectOutput->Country, strInput);
else if (writeType == ObjectName)
strcpy(objectOutput->ObjectName, strInput);
else if (writeType == Square)
objectOutput->Square = atoi(strInput);
else printf("Error 1. Invalid parameters");
}
//--Чтение objects.txt и запись в массив objectType--
//Возвращает указатель на первый элемент массива объектов
objectType *rwObjects() {
FILE *input = fopen("objects.txt", "r");
char objectQttStr[4], objectStr[38];
fgets(objectQttStr, 4, input);
objectType *objectList = (objectType *)malloc(atoi(objectQttStr)), *currentObject = objectList;
currentObject = (objectType *)malloc(atoi(objectQttStr));
for (int i = 0; i < atoi(objectQttStr); i++) {
fgets(objectStr, 38, input);
IOType inputType = Country;
for (int j = 0; objectStr[j] != NULL && objectStr[j] != '\n'; j++) {
char strBuf[cnOBJECT_NAME_LENGTH];
memset(&strBuf, 0, sizeof(strBuf));
copyInputStr(&strBuf, &j, &objectStr[j], inputType);
writeObject(&strBuf, currentObject, inputType);
inputType++;
}
currentObject++;
}
fclose(input); //this is where it happens
return objectList;
}
void main() {
objectType *objectList = rwObjects();
printf("");
}
This is one confusing program, but I've found no other way to conform the bloody rules, so let's put the coding style aside, shall we?
Also, I know that should it run successfully, nothing would happen - that is by design. It's not finished yet.
EDIT: Don't worry about validity of input data. All the input data formatting is explicitly stated in the task, ergo no checks are reqired. Still, for the curious, here it is:
objects.txt:
3
USA WelfareArrangement 120
Rus PoiskZemli 30
usa asdfEstate 1
EDIT 2: The moment I stopped using malloc, everything was fine. The question is - why exactly was it such a problem, and how would I create an array of the exact size I need, instead of creating max size evey time, if not with malloc?