I'm having slight trouble creating a 2D Vector of String that's created by reading values from a text file. I initially thought I needed to use an array. however I've come to realise that a vector would be much more suited to what I'm trying to achieve.
Here's my code so far:
I've initialised the vector globally, but haven't given it the number of rows or columns because I want that to be determined when we read the file:
vector<vector<string>> data;
Test data in the file called "test" currently looks like this:
test1 test2 test3
blue1 blue2 blue3
frog1 frog2 frog3
I then have a function that opens the file and attempts to copy over the strings from text.txt to the vector.
void createVector()
{
ifstream myReadFile;
myReadFile.open("text.txt");
while (!myReadFile.eof()) {
for (int i = 0; i < 5; i++){
vector<string> tmpVec;
string tmpString;
for (int j = 0; j < 3; j++){
myReadFile >> tmpString;
tmpVec.push_back(tmpString);
}
data.push_back(tmpVec);
}
}
}
However, when I attempt to check the size of my vector in my main function, it returns the value '0'.
int main()
{
cout << data.size();
}
I think I just need a pair of fresh eyes to tell me where I'm going wrong. I feel like the issues lies within the createVector function, although I'm not 100% sure.
Thank you!
You should use std::getline to get the line of data first, then extract each string from the line and add to your vector. This avoids the while -- eof() issue that was pointed out in the comments.
Here is an example:
#include <string>
#include <iostream>
#include <vector>
#include <sstream>
typedef std::vector<std::string> StringArray;
std::vector<StringArray> data;
void createVector()
{
//...
std::string line, tempStr;
while (std::getline(myReadFile, line))
{
// add empty vector
data.push_back(StringArray());
// now parse the line
std::istringstream strm(line);
while (strm >> tempStr)
// add string to the last added vector
data.back().push_back(tempStr);
}
}
int main()
{
createVector();
std::cout << data.size();
}
Live Example
Related
I am struggling to write parameters for a function 'readFile' which parameters are - a file name and a 2D vector to which information is copied from the file. The program doesn't throw ANY errors, but it does return just an empty vector. If i copy the code from 'readFile' function to main() function, it does work, but I want to make a seperate function so I can fill vectors with information from different files. Also I will need to pass these arguments for different type of functions with similar structure where I read from a file and copy to a 2D vector, so I really have to figure this out.
'PrintVector' function works fine. Could someone help me?
#include <string>
#include <sstream>
#include <iostream>
#include <vector>
#include <fstream>
using namespace std;
void printVector(vector< vector <float> > v)
{
for (size_t i=0; i<v.size(); ++i)
{
for (size_t j=0; j<v[i].size(); ++j)
{
cout << v[i][j] << "\t";
}
cout << "\n";
}
}
void readFile(char* filename, vector< vector<float> > &rowvector)
{
ifstream myfile(filename, ios::in);
string line;
string field;
vector<float> v; // 1 row
float result; // converted string value is saved in 'result' as a float type
if(myfile.is_open()){
while ( getline(myfile,line) ) // get next line in file
{
v.clear();
stringstream ss(line);
while (getline(ss,field,',')) // comma seperates elements
{
istringstream convert(field);
if ( !(convert >> result) )
result = 0;
v.push_back(result); // add each field to the 1D array
}
rowvector.push_back(v); // add the 1D array to the 2D array
}
}
myfile.close();
}
int main()
{
vector< vector<float> > myvector; // new 2D vector
readFile("test.txt", myvector);
printVector(myvector);
return 0;
}
Any help is much appreciated!
I know this is a dumb question!
But I just CAN NOT get my head around how to read my file into an array one word at a time using c++
Here is the code for what I was trying to do - with some attempted output.
void readFile()
{
int const maxNumWords = 256;
int const maxNumLetters = 32 + 1;
int countWords = 0;
ifstream fin;
fin.open ("madLib.txt");
if (!fin.is_open()) return;
string word;
while (fin >> word)
{
countWords++;
assert (countWords <= maxNumWords);
}
char listOfWords[countWords][maxNumLetters];
for (int i = 0; i <= countWords; i++)
{
while (fin >> listOfWords[i]) //<<< THIS is what I think I need to change
//buggered If I can figure out from the book what to
{
// THIS is where I want to perform some manipulations -
// BUT running the code never enters here (and I thought it would)
cout << listOfWords[i];
}
}
}
I am trying to get each word (defined by a space between words) from the madLib.txt file into the listOfWords array so that I can then perform some character by character string manipulation.
Clearly I can read from a file and get that into a string variable - BUT that's not the assignment (Yes this is for a coding class at college)
I have read from a file to get integers into an array - but I can't quite see how to apply that here...
The simplest solution I can imagine to do this is:
void readFile()
{
ifstream fin;
fin.open ("madLib.txt");
if (!fin.is_open()) return;
vector<string> listOfWords;
std::copy(std::istream_iterator<string>(fin), std::istream_iterator<string>()
, std::back_inserter(listOfWords));
}
Anyways, you stated in your question you want to read one word at a time and apply manipulations. Thus you can do the following:
void readFile()
{
ifstream fin;
fin.open ("madLib.txt");
if (!fin.is_open()) return;
vector<string> listOfWords;
string word;
while(fin >> word) {
// THIS is where I want to perform some manipulations
// ...
listOfWords.push_back(word);
}
}
On the suggestion of πάντα ῥεῖ
I've tried this:
void readFile()
{
int const maxNumWords = 256;
int const maxNumLetters = 32 + 1;
int countWords = 0;
ifstream fin;
fin.open ("madLib.txt");
if (!fin.is_open()) return;
string word;
while (fin >> word)
{
countWords++;
assert (countWords <= maxNumWords);
}
fin.clear();
fin.seekg(0);
char listOfWords[countWords][maxNumLetters];
for (int i = 0; i <= countWords; i++)
{
while (fin >> listOfWords[i]) //<<< THIS did NOT need changing
{
// THIS is where I want to perform some manipulations -
cout << listOfWords[i];
}
}
and it has worked for me. I do think using vectors is more elegant, and so have accepted that answer.
The suggestion was also made to post this as a self answer rather than as an edit - which I kind of agree is sensible so I've gone ahead and done so.
The most simple way to do that is using the STL algorithm... Here is an example:
#include <iostream>
#include <iomanip>
#include <iterator>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<string> words;
auto beginStream = istream_iterator<string>{cin};
auto eos = istream_iterator<string>{};
copy(beginStream, eos, back_inserter(words));
// print the content of words to standard output
copy(begin(words), end(words), ostream_iterator<string>{cout, "\n"});
}
Instead of cin of course, you can use any istream object (like file)
I am reading numbers from a file, say:
1 2 3 4 5
I want to read this data from a file into a string into an array for further processing. Here's what I've done:
float *ar = nullptr;
while (getline(inFile, line))
{
ar = new float[line.length()];
for (unsigned int i = 0; i < line.length(); i++)
{
stringstream ss(line);
ss >> ar[i];
}
}
unsigned int arsize = sizeof(ar) / sizeof(ar[0]);
delete ar;
Suffice it to say that it works insofar it only gets the first value from the file. How do I get the array to be input ALL the values? I debugged the program and I can confirm that line has all the necessary values; but the float array doesn't. Please help, thanks!
line.length() is the number of characters in the line, not the number of words/numbers/whatevers.
Use a vector, which can be easily resized, rather than trying to juggle pointers.
std::vector<float> ar;
std::stringstream ss(line);
float value;
while (ss >> value) { // or (inFile >> value) if you don't care about lines
ar.push_back(value);
}
The size is now available as ar.size(); your use of sizeof wouldn't work since ar is a pointer, not an array.
The easiest option is to use the standard library and its streams.
$ cat test.data
1.2 2.4 3 4 5
Given the file you can use the stream library like this:
#include <fstream>
#include <vector>
#include <iostream>
int main(int argc, char *argv[]) {
std::ifstream file("./test.data", std::ios::in);
std::vector<float> res(std::istream_iterator<float>(file),
(std::istream_iterator<float>()));
// and print it to the standard out
std::copy(std::begin(res), std::end(res),
std::ostream_iterator<float>(std::cout, "\n"));
return 0;
}
I ran into this problem earlier when I wanted to extract data line by line from a file to fill my sql database that I wanted to use.
There are many solutions to this specific problem such as:
The solution is using stringstream with a while statement to put data from file into the array with a while statement
//EDIT
While statement with getline
//This solution isn't very complex and is pretty easy to use.
New Improved simple solution:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
int main()
{
ifstream line;
line.open("__FILENAME__");
string s;
vector<string> lines;
while(getline(line, s))
{
lines.push_back(s);
}
for(int i = 0;i < lines.size();i++)
{
cout << lines[i] << " ";
}
return 0;
}
compiled code to check - http://ideone.com/kBX45a
What about atof?
std::string value = "1.5";
auto converted = atof ( value.c_str() );
Rather complete:
while ( std::getline ( string ) )
{
std::vector < std::string > splitted;
boost::split ( splitted, line, boost::is_any_of ( " " ) );
std::vector < double > values;
for ( auto const& str: splitted ) {
auto value = atof ( str.c_str() );
values.push_back ( value );
}
}
I am attempting read in a file and create a 2D vector to store the game board for a word search game but I can't seem to get it to read more than the first line. I'm sure it is something small but I put in a test display for the 'board' vector and all that shows up is the first line of the text file.
Here is some of my code:
'Board.cpp'
#include "stdafx.h"
#include "Board.h"
#include <fstream>
#include <iostream>
using namespace std;
Board::Board(void)
: rows(0)
{
}
Board::~Board(void)
{
}
void Board::readInFile(void)
{
ifstream indata;
indata.open("Puzzle.txt");
indata >> rows;
for(int i = 0; i < rows; i++){
char tmpChar;
for(int j = 0; j < rows; j++){
indata >> tmpChar;
row.push_back(tmpChar);
}
board.push_back(row);
}
indata.close();
}
'Board.h'
#pragma once
#include <vector>
using namespace std;
class Board
{
public:
Board(void);
~Board(void);
void readInFile(void);
protected:
vector<vector<char>> board;
vector<char>row;
protected:
int rows;
};
Here is how the text file is set up:
16
BDXWASEESPHWEBGB
SIGJVAWDFLCTZIAM
ENKVESMARNAEBRRI
IKOEOPZLUKMVJDDL
KLIRELOBSNPOFWEC
SBOHKLLRHSIFPANA
RSKWMEEEPEITPTPE
EZPIELLLYMOOQCDH
TAWDLGGLZBUNDHOJ
ASIOJNFOPKAJAPBP
WLRCIILROZXLSCID
SKATEBOARDGCLCIA
LLABESABIVOTNVVE
VOFRISBEETMIEVZG
BWADEVAUCYCSWING
XNJFJPZHBTBFTSAW
There are much better ways to handle input files. Firstly, rather than using a vector<char>, just use a std::string, and rather than using a vector<vector<char> >, just use a vector<string>. I'm not sure I understand why row is a member of the class if it is only being used to fill the board. Anytime you need the last item in board you can just do board.back() or *board.rbegin().
void Board::readInFile(void)
{
ifstream indata("Puzzle.txt", ios::in);
if(!ifstream.is_open())
return;
indata >> rows; //you don't really need to do this if you take
//the row count out of the file, but if you can't
//change the file, leave it in so as not to corrupt
//the loop that follows
string line;
while(getline(indata, line)){
board.push_back(line);
}
indata.close();
}
Really, you don't need to have the file store the rows variable.
Your function would also be more reusable if readInFile took the filename as a parameter so it could open anything instead of only one specific filename.
I am new to c++. I am learning fast, but i dont know much yet.
I cannot see the problem with index in this function:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
void get_rows(string filepath, vector<string> &rows);
int main() {
vector<string> rows;
get_rows("ninja.txt", rows);
for (int i = 0; i < rows.size(); i++) {
cout << rows[i] << endl;
}
}
void get_rows(string filepath, vector<string> &rows) {
ifstream file;
file.open(filepath);
string str;
int index = 0;
while (!file.eof()) {
getline(file, str);
rows[index] = str;
index++;
}
}
Any help will be appreciated.
You have constructed an std::vector<string> object:
vector<string> rows;
and then later you are trying to access its elements although there are no elements in this vector yet:
rows[index] = str;
You should push new elements into the vector using push_back method:
rows.push_back(str);
Also note that using while (!file.eof()) is wrong becuase getline might fail inside the loop:
while (!file.eof()) {
getline(file, str);
...
}
Your loop should look the following way:
while (std::getline(file, str)) {
if (str.empty()) continue; // we skip empty lines
rows.push_back(str); // and push non-empty lines at the end
}
vector<string> rows;
^
size() is 0
get_rows("ninja.txt", rows);
void get_rows(string filepath, vector<string> &rows) {
//...
int index = 0;
rows[index] = str; // but there is no rows[0] yet
//...
}
you should either use push_back to add new elements into vector or create a vector with specified size at the beginning (if it is known)
vector<string> rows(160);
which has advantage over the former as you can avoid potential reallocation (which may invalidate pointers to vector elements i.e)