How to read a CSV file in C++ - c++

Here is my code that I have written to read an excel file in csv format in C++. I want to read the file line by line. When I run the code it gives me an error saying
argument list for class template 'array' is missing
Thanks.
#include <string>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <array>
using namespace std;
int main() {
array<string , 29>arr;
string line;
int location;
int start = 0;
//int arrayFile[51][28] = { { 0 } };
string fileName;
ifstream infile(fileName);
infile >> line;
//error check
if (infile.fail()) {
cout << "File not Found !" << endl;
exit(1);
}
//reading the file
for (int i = 0; i < 29; i++) {
location = line.find(","); //find the first comma in line
array[i] = line.substr(start, location - start); // separate the information from line up to the comma
line = line.substr(location + 1); //change line to the rest after removing the the abouve piece of the information
}
array[i] = line;

Since you declared using namespace std and included <array>, array is not a variable, but a template class (C++11 STL). You must define an actual array with it like
array<string, 29> arr;
// std::array<std::string, 29> arr;
Then you'll be able to use arr afterwards

Related

Why is my string empty when taking input from file?

I have a huge file full of numbers (2 billion). So this is a file splitter that splits my file in groups of 100000 numbers. but this is returning empty files full of spaces and enters. I even tried to change the data type of the variable. I am struck. please suggest.
#include <iostream>
#include <vector>
#include <string>
#include <iterator>
#include <fstream>
#include <algorithm>
using namespace std;
int main()
{
std::ifstream ifs("prime.txt");
unsigned long long int curr;
unsigned long long int x = 0;
string li;
int count;
while (getline(ifs, li))
{
count ++;
}
ifs.seekg(ios::beg);
string v;
while (curr < count)
{
x++;
std::string file = to_string(x) ;
std::string filename = "splitted\\"+file+ ".txt";
std::ofstream ofile (filename.c_str());
while (curr < 100000*x )
{
ifs >> v ;
ofile << v << "\n";
curr++;
}
ofile.close();
}
}
You have 2 uninitialised variables, count and curr, your compiler should have warned you about these. If it didn't make sure you have enabled compiler warnings.
After the last getline in your initial while loop fails the stream will have the fail and eof flags set. Due to the stream not being in the good state all further operations on it will fail so your seekg will be ignored as will all your reads. To fix this call ifs.clear(); before your seekg.
As you don't seem to need the line count anywhere pre-calculating it is unnecessary and as you are then not reading the file in lines it will lead to incorrect behaviour if your file has more than one value on a line. Your code can be simplified to:
#include <iostream>
#include <vector>
#include <string>
#include <iterator>
#include <fstream>
#include <algorithm>
using namespace std;
int main()
{
std::ifstream ifs("prime.txt");
if (!ifs)
{
std::cout << "error opening input file\n";
return 1;
}
int64_t fileNumber = 0;
int64_t fileCount = 0;
std::ofstream ofile;
while (ifs)
{
if (!ofile.is_open() || (fileCount >= 100000))
{
ofile.close();
fileCount = 0;
fileNumber++;
std::string file = to_string(fileNumber);
std::string filename = "splitted\\" + file + ".txt";
ofile.open(filename.c_str());
if (!ofile)
{
std::cout << "error opening output file\n";
return 1;
}
}
std::string value;
if (ifs >> value) {
ofile << value << "\n";
fileCount++;
}
}
}

I'm stuck on how to read from a text file

/* In the text file I have a char followed by a blankspace then a string. I'm trying to read the char and string into seperated arrays. Any help is appreciated */
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;
int main()
{
char arrivOrDepart;
string licensePlt;
ifstream inFile;
inFile.open("Text.txt");
if (!inFile)
{
cout << "Can't open file" << endl;
return 1;
}
for (int i = 0; i < 4; i++)
{
getline(cin, arrivOrDepart[i]);
getline(cin, licensePlt[i]);
}
inFile.close();
cin.get();
return 0;
}
//text file
A QWE123
A ASD123
A ZXC123
A WER123
A SDF123
#include <fstream>
#include <iterator>
#include <vector>
this reads from file into vector
std::ifstream input("d:\\testinput.txt");
std::vector<std::string> bytes(
(std::istreambuf_iterator<std::string>(input)),
(std::istreambuf_iterator<std::string>()));
input.close();
then, just put the data into whatever container you want. you should almost always prefer vector over array btw
There are a few problems with the code:
getline is the wrong tool of choice for this. if you want to split a stream based on spaces, use >>.
arrivOrDepart and licensePlt are not defined as arrays but are used as arrays.
reading from cin, not from file.
My suggested fixes (excluding using vectors instead of arrays):
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std; // avoid using this
int main()
{
const int MAXARRAY = 4; // avoid using magic numbers
char arrivOrDepart[MAXARRAY]; // made an array, but prefer std::vector
string licensePlt[MAXARRAY]; //made an array
ifstream inFile;
inFile.open("Text.txt");
if (!inFile)
{
cout << "Can't open file" << endl;
return 1;
}
string temp;
int i = 0;
while (i < MAXARRAY && // not overrunning the arrays
inFile >> temp >> licensePlt[i] && // read data from file stream
temp.length() == 1) // read only one character for arrivOrDepart
{
arrivOrDepart = temp[0];
i++;
}
inFile.close();
cin.get();
return 0;
}
Recommended reading:
Why is "using namespace std" considered bad practice?
What is a magic number, and why is it bad?
std::vector documentation (Alternate easier to read but often less accurate documentation)
std::getline documentation. Note the third parameter used to set the parsing delimiter.

Displaying contents of vector

I am having trouble displaying the contents of a vector. I am unsure whether it is the way I read in the values from the text file, or whether my display function is just not working.
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
using namespace std;
int main()
{
string line;
int n,length;
std::vector<int>arr1;
fstream file("t1.txt");
if(file.is_open())
{
while (getline(file,line))
{
cout << line << endl;
}
file << line;
length = line.length();
while(file >> n)
arr1.push_back(n);
for(int i =0; i < (int)arr1.size(); i++)
cout << arr1.at(i) << endl;
}
return 0;
}
Any help would be greatly appreciated.
the text file contains "5 2 5 5 -1 7 2 5 3 5 2 -2"
I suppose you have a problem with vector building (reading values from file to vector). You should delete (or comment) expression with getline, as well as writing line back to file (file << line), and use only file >> n.
Try the following shortened version of your program
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
using namespace std;
int main()
{
string line;
int n;
std::vector<int> arr1;
fstream file("t1.txt");
if(file.is_open())
{
while(file >> n)
arr1.push_back(n);
for(int i =0; i < (int)arr1.size(); i++)
cout << arr1.at(i) << endl;
file.close();
}
return 0;
}
Problem of your initial code is that after you read line from your file (that comprises only one line) next reading (whether it is file >> ... or getline(...)) will provide no data because END OF FILE. To read data from file again you should re-open it
...
length = line.length();
file.close();
file.open("t1.txt");
while(file >> n)
arr1.push_back(n);
...
or rewind to the beginning
...
length = line.length();
file.clear();
file.seekg(0, ios_base::beg);
while(file >> n)
arr1.push_back(n);
...
But you should understand, that writing to file stream does not provide desired effect - the recorded data will be available only after transfer written data from the buffer to the file (in the general case, after the file closing).
EDIT:
Also I want to add, that C++ allows input to and output from vector without additional loops, just consider the following example
if(file.is_open())
{
// filling vector from the stream
istream_iterator<int> it(file); // iterator for int values in file
istream_iterator<int> eos; // end of straem
arr1.insert(arr1.begin(), it, eos);
// output vector to the stream (cout = standard output stream)
ostream_iterator<int> oit (cout,"\n"); // "\n" = new line is a separator for output
// also " " or any other separator can be used
copy(arr1.begin(), arr1.end(), oit);
}

Reading multiple lines of strings from a file and storing it in string array in C++

I have a class called StringList consisting of a constructor and a de-structor. What I am shooting for is for the ability of my program to retain its strings in the array even after it is not running. The way i want to do this is to have my constructor function read strings from a file and store them into my string array (str[]). My de-structor will save my current strings into my file. I am having trouble reading and storing from the file when memory is created. I want each word to be one element in the array.
For example, in the file that is being read from, the strings are stored as such:
HELLO
MOM
DAD
FOUR
YELLOW
I want each word to be a slot. In other words. str[0] = HELLO, str[1]= MOM, str[2]=DAD and such.
Here is my constructor function:
StringList::StringList()
{
numberOfStrings=0;
str = new string[1000000];
ifstream myfile ("Read.txt");
if (myfile.is_open())
{
for (int i = 0; i < 1000000; i++)
{
getline(myfile,str[i]);
numberOfString++;
}
myfile.close();
}
}
Problem here is the for (int i=0; i<100000;i++) line
What this did is continue to fill each blank space into the element until it reached 100000.
Same if i put i<20, it would read all the contents and add blanks to fill to 20. Is there anyway to fill up to the amount of actual strings in the txt. file?
NumberOfStrings++ is outside of your for loop when you read (i.e. it only gets incremented once). Also please consider using std::vector<std::string> instead of a dynamic array.
Here's a version of your code using std::vector instead of an array:
#include <vector>
#include <fstream>
#include <iostream>
#include <string>
class StringList
{
public:
StringList(): str(1000000), numberOfStrings(0)
{
std::ifstream myfile ("Read.txt");
if (myfile.is_open())
{
for (int i = 0; i < str.size(); i++)
{
getline(myfile, str[i]);
numberOfStrings++;
}
myfile.close();
}
}
StringList::~StringList()
{
std::ofstream os("Read.txt");
for (int i = 0; i <numberOfStrings; i++)
{
os << str[i] << std::endl;
}
}
private:
std::vector<std::string> str;
int numberOfStrings;
};
As you can see the changes are rather minimal.
The numberOfStrings variable is only updated once after the for loop has finished. You can also simplify this without the need to specify a large number of lines to read by checking the return value of getline for failure. If you try to read past the end of file is getline will return false.
numberOfStrings = 0;
str = new std::string[1000000];
std::ifstream myfile("Read.txt");
if (myfile.is_open())
{
std::string line;
while(getline(myfile, str[numberOfStrings]))
numberOfStrings++;
myfile.close();
}
You can simplify this even further by using std::vector. To expand on the example provided in your answer StringList might look something like below.
StringList.h
#include <vector>
#include <string>
class StringList
{
public:
StringList();
void PrintWords();
private:
size_t numberOfLines;
std::vector<std::string> str;
};
StringList.cpp to read in single line into each string
#include "StringList.h"
#include <fstream>
StringList::StringList()
{
std::ifstream myfile("Read.txt");
if (myfile.is_open())
{
std::string line;
while(getline(myfile, line))
{
lines_.push_back(line);
}
myfile.close();
}
numberOfLines = str.size();
}
StringList.cpp to read in single word into each string using std::istream_itertor and std::copy
#include "StringList.h"
#include <fstream>
#include <istream>
#include <algorithm> // std::copy
#include <iterator> // istream_iterator
StringList::StringList()
{
std::ifstream myfile("Read.txt");
if (myfile.is_open())
{
std::copy(
istream_iterator<string>(myfile),
istream_iterator<string>(),
back_inserter(str));
}
numberOfLines = str.size();
}
Some other function to print the words
StringList::PrintWords()
{
for(size_t i = 0; i < numberOfLines; ++i)
{
std::cout << str[i] << std::endl;
}
}
I also recommend avoiding using using namespace std in your code. It pulls everything from std into the current scope (typically the global namespace) and can cause conflicts with identifiers.
This would be my approach to reading the data (this doesn't quite work the same as the other answers, but as long as your wordlist doesn't contain words with whitespace, it should work fine).
#include <iostream>
#include <fstream>
#include <iterator>
#include <vector>
int main()
{
std::fstream myFile("read.txt");
if (myFile.is_open())
{
std::istream_iterator<std::string> iter(myFile), end;
std::vector<std::string> str(iter, end);
// print contents
for (int i = 0; i < str.size(); i++)
std::cout << i << ": " << str[i] << std::endl;
}
}
References:
istream_iterator
vector
You can continue to averse std::vector all you want, but for a scenario like this, it is the best tool for the job.

code to read-in floating variables from a textfile containing more than one line

In c++ how would I read a text file containing 3 float variables not as string types, but as float variable types for re-use by a program.
I was trying to use fscanf function and having results of it only reading in the first line of the file. How do I tell it to use delimiters such as \n end of line and have it continue to process the rest of the file?
Thanks.
#include <cstdlib>
#include <math.h> //Include math functions
#include <iostream> //Stream to allow input/output
#include <fstream> //Stream class to read/write files
using namespace std;
string line = "0.0";
char str [80];
float f;
FILE * pFile;
int main () {
pFile = fopen ("C:\\Users\\Brian\\Documents\\NetBeansProjects\\CppApplication_2\\init_temps.txt","r"‌​);
fscanf (pFile, "%f", &f);
cout << f;
return 0;
}
Based on your code, it seems you are only reading the first number. You should iterate 3 times:
int i;
for(i = 0; i < 3; i++)
{
fscanf(pFile, "%f", &f);
cout << f << endl;
}
or better yet check for fscanf()'s return value to better decide if you've read it all.
On another note, you should learn to use local variables instead of global variables, unless there's really a need to.
Hope this helped.
floats.text
5.5
2.2
1.1
read.cpp
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main () {
string line;
float sum = 0;
ifstream myfile ("floats.text");
if (myfile.is_open())
{
while ( myfile.good() )
{
getline (myfile,line);
sum += ::atof(line.c_str());
}
myfile.close();
}
cout << sum << endl;
return 0;
}
result
./a.out
>> 8.8