Существует ряд проблем с этим кодом. Но прежде всего проблема в том, что вы пишете какой-то злой гибрид C / C ++. Выберите один из двух языков и используйте его.
Вот пересмотренная версия вашего кода:
#include <iostream>
class fileReader
{
public:
FILE *fp;
char** lines;
fileReader() : fp(NULL) // initialization of members happens here
{
//fp = NULL; // anything here happens *after* initialization
lines = new char*[100]; // let's just assume max 100 lines. We have to allocate space for them
for (int i = 0; i < 100; ++i) {
lines[i] = new char[100]; // allocate space for the contents of each individual line
}
}
fileReader(const char* path)
{
lines = new char*[100]; // let's just assume max 100 lines. We have to allocate space for them
for (int i = 0; i < 100; ++i) {
lines[i] = new char[100]; // allocate space for the contents of each individual line
}
int i=0;
fp = fopen(path,"r");
while ( fgets(lines[i], 100, fp) )
i++;
}
~fileReader() {
// deallocate and close our members:
fclose(fp);
for (int i = 0; i < 100; ++i) {
delete[] lines[i]; // delete the contents of each line
}
delete[] lines; // delete the lines array
}
};
int main(int argv, char** argc)
{
const char* path = "D:\\PS4263-2.txt";
fileReader p(path); // don't use new unless you really really have to
for (int i=0; i<2; i++)
std::cout<<p.lines[i];
return 0;
}
Теперь, по крайней мере, это работает, , если каждая строка содержит менее 100 символов и , меньше 100 строк и файл существует и дюжина других условия, от которых мы действительно должны защищаться. В частности, мы тратим много усилий на управление памятью: выделение и освобождение места для всех данных строки.
Но мы можем сделать намного лучше с помощью нескольких изменений, если мы действительно начнем писать C ++.
#include <iostream> // we need this for the standard streams (cout)
#include <fstream> // we need proper C++ file streams too
#include <string> // C++ has strings. Don't waste your time on char pointers
#include <vector> // C++ has a dynamic array class. Don't use pointers as ad-hoc arrays
class fileReader
{
public:
// FILE* fp; // no point in making this a class member, when it's only used in one function
std::vector<std::string> lines; // use a vector of strings. Much easier to manage
fileReader() // vectors are automatically initialized, no need to do anything
{
}
fileReader(std::string path)
{
std::ifstream fp(path); // create an input file stream
std::string result; // store the contents of the current line here
while (std::getline(fp, result)) {
lines.push_back(result); // append the resulting line to the end of the vector
}
}
};
int main(int argv, char** argc)
{
std::string path = "blah.txt";
fileReader p(path); // don't use new unless you absolutely have to
for (int i=0; i<2; i++)
std::cout<<p.lines[i];
return 0;
}
Обратите внимание, что нам больше не нужно управлять памятью массива. Векторы и строки автоматически убираются за собой, когда выходят из области видимости. И поскольку мы больше не используем new
для выделения fileReader
, он автоматически удаляется, когда it выходит из области видимости. Это фактически запускает цепную реакцию, когда его члены начинают очищаться после себя: поток файлов закрывается, векторы освобождают его память после того, как просят свои сохраненные строки очистить и закрыть. И вся программа сворачивается и закрывается без необходимости написания единой строки кода для ее обработки.