I do not fully understand what you want to do. There is missing information. Anyway. I will try to help.
I guess that you are new to C++. You are using a lot of C functions. And your program looks completely like C, with some additional C++ features. That you should not do. You are especially using malloc and raw pointers. This you must not do at all.
Try to learn C++ step by step.
Let me first show you what I mean with C-Style programming. I took your program and added comments with hints.
// Do not pass arguments by pointer, pass by reference
// For invariants, pass as const T&
// Do not use "char *". Should be at least const. But do not use at all
// Use std::string (so pass "const std::string& dbname") as argument
void Table::LoadTableRows(Table::TableStruct *table,char *dbname) {
// Always initialize varibles. Use universal initialization, with {}
ifstream fp;
// Never use malloc. Use new.
// Do not use raw ptr. use std::unique_ptr. Initialize with std::make_unique
// Do not use C-Style cast. Use static_cast
Table::RowStruct *p = (Table::RowStruct*) malloc(sizeof(Table::RowStruct));
// Use std::string
char *filename;
int x;
// Again. No malloc, no C-Style cast
// Do not use C-Sytle string functions
filename = (char*) malloc((strlen(table->tablename)+strlen(dbname)+strlen("Data"))*sizeof(char));
// Do not use C-Sytle string functions
strcpy(filename,dbname);
// Do not use C-Sytle string functions
strcat(filename,table->tablename);
// Do not use C-Sytle string functions
strcat(filename,"Data");
// Check, if open works, Open file through constructor, then it will be closed by destructor
fp.open(filename);
while(!fp.eof()) { //goes through all file lines
// Do not use malloc and C-Style cast
Table::RowStruct *newrow = (Table::RowStruct*) malloc(sizeof(Table::RowStruct)); //allocates space for a new row
//initializes element
// Do not use NULL, but nullptr
newrow->prev = NULL;
newrow->next = NULL;
// Do not use malloc and C-Style cast
newrow->data = (char**) malloc(table->ncols*30*sizeof(char)); //allocates space to store the row data
// Do not use x++ but ++x
for(x=0;x<table->ncols;x++) {
// Do not use malloc and C-Style cast
newrow->data[x] = (char*) malloc(30*sizeof(char)); //allocates space for individual data element
// Check for out of bounds
fp >> newrow->data[x];
}
// Do not use selfmade linked list. Use STL container
for(p=table->rows;p->next!=NULL;p=p->next) {}
newrow->prev = p;
p->next = newrow;
}
fp.close();
}
You see, there is a lot of C in it and not so much C++.
The modern C++ makes much use of containers and algorithms.
A full fledged example for C++ is below. It is hard to understand for beginners. But try to analyze and you will get a hang of it.
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include <iterator>
#include <algorithm>
#include <sstream>
using AllWordsInOneLine = std::vector<std::string>;
using AllLines =std::vector<AllWordsInOneLine>;
struct Line // ! This is a proxy for the input_iterator !
{ // Input function. Read on line of text file and split it in words
friend std::istream& operator>>(std::istream& is, Line& line) {
std::string wholeLine; std::getline(is, wholeLine); std::istringstream iss{ wholeLine }; line.allWordsInOneLine.clear();
std::copy(std::istream_iterator<std::string>(iss), std::istream_iterator<std::string>(), std::back_inserter(line.allWordsInOneLine));
return is;
}
operator AllWordsInOneLine() const { return allWordsInOneLine; } // cast to needed result
AllWordsInOneLine allWordsInOneLine{}; // Local storage for all words in line
};
int main()
{
std::ifstream inFileStream{ "r:\\input.txt" }; // Open input file. Will be closed by destructor
if (!inFileStream) { // ! operator is overloaded
std::cerr << "Could not open input file\n";
}
else {
// Read complete input file into memory and organize it in words by lines
AllLines allLines{ std::istream_iterator<Line>(inFileStream), std::istream_iterator<Line>() };
// Make exact ncols entries.
const size_t ncols = 6; // whatever ncols may be. Empty cols will be filled with ___ (or whatever you like)
std::for_each(allLines.begin(), allLines.end(), [ncols](AllWordsInOneLine& awil) {awil.resize(ncols, "___"); });
// copy result to std::cout
std::for_each(allLines.begin(), allLines.end(), [](AllWordsInOneLine & awil) {std::copy(awil.begin(), awil.end(), std::ostream_iterator<std::string>(std::cout, " ")); std::cout << '\n'; });
}
return 0;
}
Please see especially that the whole file, with all lines split into words, will be read in one line of code in function main.
An additional one-liner converts this into a vector with exactly ncols elements (words). This regardless if there were more or less than ncols words per line in the source file.
Hope I could help at least a little bit.