I was using the following code to read information from a file (b.txt) into a vector. every time I execute, the program starts reading from the second line. So vector_b[0] = the second line instead of the first line.
I'm still not used to c++ hope you can help
string line_b;
int idx = -1;
float *vector_b = new float[1];
float element_b;
if (file_b.is_open() && file_b.good()) {
cout << "File is open. \n";
while (getline(file_b, line_b)) {
stringstream stream_b(line_b);
while(1) {
stream_b >> element_b;
if(!stream_b) {
break; }
idx = idx+1;
float *tempArr = new float [idx];
copy(vector_b, vector_b + idx, tempArr);
tempArr[idx] = element_b;
delete [] vector_b;
vector_b = tempArr;
}
}
}
else {
cout << "Failed to open file.";
}
You might try something like the following. You might try a vector
as opposed to a dynamic array. they're more flexible and in most cases faster. You don't have to worry about use after frees, double frees, or memory leaks... so Yeah... vectors rule...
int main() {
std::ifstream file_b;
file_b.open("Some-file.cpp");
std::string line_b;
// vector_b is a vector of doubles
std::vector<double> vector_b();
double element_b;
if (file_b.is_open() && file_b.good()) {
std::cout << "File is open. \n" << std::endl;
while(getline(file_b, line_b)) {
std::stringstream stream_b(line_b);
// You don't need a second if.
while(stream_b) {
stream_b >> element_b;
// append element_b to your vector
vector_b.push_back(element_b);
}
}
} else {
std::cout << "Failed to open file." << std::endl;
}
}
However, if you can't use vectors, I'd suggest you look into creating a container class like the class and usage listed below. I don't trust myself to remember to free memory, so sometimes its just best to build a class. I tested the class below under valgrind a few times, so there shouldn't be any leaks, but no promises. I made it very hurried.
#include <cassert>
// use a templated class so we can use it with different types
template<typename T>
class Container {
private:
unsigned int m_size;
unsigned int m_capacity;
T* m_array;
public:
// Any time you make a container class make sure you follow the
// rule of 5 with C++11 or the rule of 3 for prior compilers
// 1) Copy Constructor
// 2) Move Constructor (C++11)
// 3) Copy Assignment Operator
// 4) Move Assignment Operator (C++11)
// 5) Destructor
// Default constructor
Container() { }
// Constructor we'll use
Container(unsigned sz) :
m_size(0),
m_capacity(sz),
m_array(new T[sz]) { }
// Copy constructor
Container(const Container& src) :
m_size(src.m_size),
m_capacity(src.m_size),
m_array(new T[src.m_size]) {
for(unsigned i = 0; i < m_size; ++i) {
// copy values
m_array[i] = src.m_array[i];
}
}
// Move constructor
Container(Container&& src) {
// "steal" the sources members
m_capacity = src.m_capacity;
m_size = src.m_size;
m_array = src.m_array;
// "destroy" the sources members
src.m_size = 0;
src.m_capacity = 0;
src.m_array = nullptr;
}
// Destructor
~Container() {
delete[] m_array;
}
// Copy assignment operator
Container& operator=(const Container& src) {
// check to make sure you're copying a different source
if(this == &src) {
return *this;
}
// free your current memory
delete[] m_array;
// make a new array and copy the sources values
m_array = new T[src.m_size];
for(unsigned i = 0; i < src.m_size; ++i) {
m_array[i] = src.m_array[i];
}
// copy the size parameters
m_size = src.m_size;
m_capacity = src.m_capacity;
return(*this);
}
// Move assignment operator
Container& operator=(Container&& src) {
// check to make sure you're copying a different source
if(this == &src) {
return *this;
}
// free your current memory
delete[] m_array;
// "steal" the sources members
m_array = src.m_array;
m_size = src.m_size;
m_capacity = src.m_capacity;
// "destroy" the sources members
src.m_array = nullptr;
src.m_size = 0;
src.m_capacity = 0;
return(*this);
}
void resize(unsigned int sz) {
// make sure you're not shrinking the container
if(sz > m_capacity) {
// make a temporary array
T* tmp = new T[sz];
for(unsigned i = 0; i < m_size; ++i) {
// copy the values to the temporary array
tmp[i] = m_array[i];
}
// free your current memory
delete[] m_array;
// "steal" the temporary array
m_array = tmp;
// release tmp's handle on the memory
tmp = nullptr;
// inform your object that it has more memory now
m_capacity = sz;
}
}
void push_back(const T& src) {
// check if you have enough space to append a value
if(m_size + 1 > m_capacity) {
// if not, double your current size, so you don't have
// to do it every time
resize((m_capacity + 1) * 2);
}
// increment the size member and append the value to your array
m_array[m_size++] = src;
}
T& operator[](unsigned index) {
// make sure the index value is in-bounds
assert(index < m_size);
return(m_array[index]);
}
size_t size() { return(m_size); }
};
Usage:
int main(int argc, char *argv[]) {
Container<std::string> vector_b(1);
std::ifstream file_b;
file_b.open("Sleep.cpp");
std::string line_b;
std::string element_b;
if (file_b.is_open() && file_b.good()) {
std::cout << "File is open. \n" << std::endl;
while(getline(file_b, line_b)) {
std::stringstream stream_b(line_b);
while(stream_b) {
stream_b >> element_b;
vector_b.push_back(element_b);
}
}
} else {
std::cout << "Failed to open file." << std::endl;;
}
for(unsigned i = 0; i < vector_b.size(); ++i) {
std::cout << vector_b[i] << std::endl;
}
}
As you can see, working with dynamic memory allocations is a pain, and generally should be avoided, or at least handled with extreme care and lots of valgrind.