I save a boolean matrix(ROW*ROW) to .txt file (0,1 format).
How could I read the matrix from the file? I wrote code below, but I compare the read results with the file, and the array results don't match the file. Could anyone tell me where I wrote wrong? Or are there any easier ways to read a matrix file?
bool **results = new bool*[ROW];
for(int i=0;i<ROW;i++){
results[i] = new bool[ROW];
}
ifstream infile;
infile.open ("FRM.txt");
string line;
int row=0;
if (infile.is_open())
{
while ( infile.good() )
{
getline(infile,line);
istringstream iss(line);
int col=0;
while(iss)
{
string word;
iss >> word;
int number = atoi(word.c_str());
if(number==1){
results[row][col] = true;
}
else{
results[row][col] = false;
}
col++;
}
row++;
}
}
infile.close();
Representing a matrix as a nested array is usually a bad idea. Use a linear array instead and do the index-juggling through a macro or inline function.
I would go for something like this:
#include <algorithm>
#include <cmath>
#include <cstdint> // uint8_t requires C++11
#include <iterator>
#include <vector>
// don't use vector<bool>, it creates all sorts of problems
std::vector<uint8_t> results;
{
std::ifstream infile('FRM.txt', std::ifstream::in);
if(infile.is_open() && infile.good())
{
std::istream_iterator<uint8_t> first(infile), last;
copy(first, last, std::back_inserter(results));
}
}
// only if you know the matrix is square! error checking strongly advised!
size_t nrows = size_t(std::sqrt(results.size()));
// accessing element (i,j) is then as easy as
size_t i = 2, j = 3; // assuming nrows > i,j
bool a_ij = results[i*rows+j];
Related
I am working on a program to read floating point number from an txt file and store in array, and I need to check are there any invalid input like character.
My code is:
int main() {
string line;
ifstream myfile("data.txt");
int size;
float* result;
if (myfile.is_open()) {
getline(myfile, line);
size = stoi(line);
result = new float[size];
for (int i = 0; i < size; i++) {
myfile >> result[i];
/*if ( (isdigit(arr[i])==0) ){
cout << "Invaild input." << endl;
return 0;
}*/
}
myfile.close();
}
else {
return 0;
}
}
The first line of the txt file is the size of the array and the second line is the contents like
5 //size
1 -2 9.2 4.7 -5.2 //content
How can I check that is there any character exist in the array like 1 -2 B 4.7 -5.2 //Invalid input ?
I try the isdigit function but it fail.
If you get an invalid input, reading will fail, and you can check this in the usual manner.
if (myfile >> result[i])
{
// Handle success.
}
else
{
// Handle failure.
}
I have given 2 solutions. One uses built in arrays and other uses std::vector.
Solution 1: Using built in array
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
int main()
{
std::string line;
std::ifstream inFile("input.txt");
//in case of using array, size must be fixed and predetermined
double arr[120] = {0.0}; //you can choose size according to your needs
if(inFile)
{
double i = 0;//this variable will be used to add element into the array
int count = 0;
while(getline(inFile, line, '\n'))
{
std::istringstream s(line);
//take input(from s to i) and then checks stream's eof flag status
while(s >> i || !s.eof()) {
//check if either failbit or badbit is set
if(s.fail())
{
//clear the error state to allow further operations on s
s.clear();
std::string temp;
s >> temp;
continue;
}
else
{
arr[count] = i;
++count;
//break out of the loop so we do go out of bounds
if(count >=120)//note 120 is the size of the array and you can change it according to your needs
{
break;
}
}
}
}
}
else
{
std::cout<<"file could not be read"<<std::endl;
}
inFile.close();
for(double i: arr)
{
std::cout<<"elem: "<<i<<std::endl;
}
return 0;
}
The output of solution 1 can be seen here.
Solution 2: Using std::vector
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
int main()
{
std::string line;;
std::ifstream inFile("input.txt");
std::vector<double> vec;
if(inFile)
{
double i = 0;//this variable will be used to add element into the vector
while(getline(inFile, line, '\n'))
{
std::istringstream s(line);
//take input(from s to i) and then checks stream's eof flag status
while(s >> i || !s.eof()) {
if(s.fail())
{
//clear the error state to allow further operations on s
s.clear();
std::string temp;
s >> temp;
continue;
}
else
{
vec.push_back(i);
}
}
}
}
else
{
std::cout<<"file could not be read"<<std::endl;
}
inFile.close();
for(double i: vec)
{
std::cout<<"elem: "<<i<<std::endl;
}
return 0;
}
The ouput of solution 2 can be seen here.
Important Note
The advantage of using std::vector over built in array(in this case) is that you don't have know the size of the vector beforehand. So it is preferable because you don't know how many integers are there in the input.txt file. std::vector can handle this correctly(dynamically). But when using built in arrays you must know/specify the size of the array beforehand. This in turn means you must know beforehand how many integers are there in the input.txt, which is not practical.
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'm making a function importcsv() which takes in a filename and outputs a 2D array. For some reason, whenever I use the following version of importcsv(), the compiler runs smoothly, but the executable always returns a "segmentation fault: 11" error.
typedef vector<vector<double> > matrix;
matrix importcsv(string filename)
{
ifstream myfile (filename); //Constructs a stream, and then asssociates the stream with the file "filename"
matrix contents; // Vector which will store the contents of the stream.
int i, j;
while(!myfile.eof())
{
if(myfile.get()==','){++j;}
else if(myfile.get()=='\n'){++i; j=0;}
else{
contents[i][j]=2;}
}
return contents;
}
Can anyone find the source of the error? btw I have the following header:
#include <fstream>
#include <iostream>
#include <array>
#include <vector>
using namespace std;
You are getting "segmentation fault: 11" since you have not allocated memory for contents.
contents[i][j] will work only if contents has something in it.
You can divide reading of the file and constructing the matrix into various parts:
Reading all the numbers in a line and treating it as a row of contents.
Reading a number from the line and treating it as a column of a row.
This way, the program can be simplified. This also helps you easily isolate problems when there are any and fix them.
typedef vector<vector<double> > matrix;
double readNextNumber(std::istream& str)
{
double n = 0.0;
str >> n;
// Skip until we get ',' or '\n'
while (str)
{
int c = str.getc();
if ( c == ',' || c == '\n' || c == EOF )
break;
}
return n;
}
std::vector<double> importRow(std::ifstram& myfile)
{
std::string line;
std::vector<double> row;
// Read a line as a string.
// Then parse the string using std::istringstream.
// When you have finished parsing the line, you know
// you have finished constructing a row of the matrix.
std::getline(myfile, line);
if ( myfile )
{
std::istringstream str(line);
while (str)
{
double n = readNextNumber(str);
if (str)
{
row.push_back(n);
}
}
}
return row;
}
matrix importcsv(string filename)
{
ifstream myfile (filename); //Constructs a stream, and then asssociates the stream with the file "filename"
matrix contents; // Vector which will store the contents of the stream.
while(!myfile.eof())
{
std::vector<double> row = importRow(myfile);
if (myfile)
{
contents.push_back(row);
}
}
return contents;
}
You haven't defined the size of contents. So by default, it will be a vector of 0 element. Therefore the calls to the operator[] will lead to a segmentatin fault.
Implementing the advice of the others here, the quick fix is to use resize() before reading each value into the array:
//WARNING: THIS PROGRAM UTILIZES C++11
#include <fstream>
#include <iostream>
#include <array>
#include <vector>
#include <cctype>
#include <thread>
using namespace std;
typedef vector<vector<double> > matrix;
matrix importcsv(string filename)
{
ifstream myfile ("wavelengthtorgb.csv"); //Constructs a stream, and then asssociates the stream with the file "filename".
matrix contents {{0.0}};
char nextchar; double data; int i,j;
while(!myfile.eof())
{
myfile.get(nextchar);
if(nextchar==',')
{
++j;
contents[i].resize(j+1);
cout<<"encountered a comma."<<" contents is now " <<i+1<<" x "<<j+1<<'\n';
}
else if(isspace(nextchar))
{
myfile.get(); //You might not need this line - first run with this line, and if there is an error, delete it, and try again.
++i;
contents.resize(i+1);
j=0;
contents[i].resize(j+1);
cout<<"encountered a carriage return."<<" contents is now " <<i+1<<" x "<<j+1<<'\n';
}
else
{
myfile.unget();
myfile >> data;
contents[i][j]=data;
cout<< "encountered a double."<<" contents("<<i<<','<<j<<")="<<data<<'\n';
}
}
return contents;
}
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)