The file does open and I get the message "File opened successfully". However I can't input data from the array in file "random.csv" into my inputFile object.
The data in random.csv is:
Boston,94,-15,65
Chicago,92,-21,72
Atlanta,101,10,80
Austin,107,19,81
Phoenix,112,23,88
Washington,88,-10,68
Here is my code:
#include "main.h"
int main() {
string item; //To hold file input
int i = 0;
char array[6];
ifstream inputFile;
inputFile.open ("random.csv",ios::in);
//Check for error
if (inputFile.fail()) {
cout << "There was an error opening your file" << endl;
exit(1);
} else {
cout << "File opened successfully!" << endl;
}
while (i < 6) {
inputFile >> array[i];
i++;
}
for (int y = 0; y < 6; y++) {
cout << array[y] << endl;
}
inputFile.close();
return 0;
}
Hello and welcome to Stack Overflow (SO). You can use std::getline() to read each line from the file, and then use boost::split() to split each line into words. Once you have an array of strings for each line, you can use a container of your liking to store the data.
In the example below I've used an std::map that stores strings and a vector of ints. Using a map will also sort the entrances using the key values, which means that the final container would be in alphabetical order. The implementation is very basic.
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <fstream>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/split.hpp>
#include <ctype.h>
typedef std::map<std::string,std::vector<int>> ContainerType;
void extract(ContainerType &map_, const std::string &line_)
{
std::vector<std::string> data;
boost::split(data, line_, boost::is_any_of(","));
// This is not the best way - but it works for this demo.
map_[data[0]] = {std::stoi(data[1]),std::stoi(data[2]),std::stoi(data[3])};
}
int main()
{
ContainerType map;
std::ifstream inputFile;
inputFile.open("random.csv");
if(inputFile.is_open())
{
std::string line;
while( std::getline(inputFile,line))
{
if (line.empty())
continue;
else
extract(map,line);
}
inputFile.close();
}
for (auto &&i : map)
{
std::cout<< i.first << " : ";
for (auto &&j : i.second)
std::cout<< j << " ";
std::cout<<std::endl;
}
}
Hope this helps.
Related
Hi I have got an text file and inside writing:
15 7 152 3078
178 352 1 57
What I want to do is get the int's from first line, sum up the numbers and make it an integer. And than do it for the second line with another int. How can I do that with c++? Thanks for your help.
You can use stringstream to convert a string into integer. And to sum a vector of integer, use accumulate algorithm. You can pass a filename as first argument to the program, by default the program assume the filename as input.txt.
Here is a complete program to demonstrate this.
#include <iostream>
#include <fstream>
#include <sstream>
#include <numeric> // for accumulate
#include <vector>
int main(int argc, char *argv[]) {
std::string filename{"input.txt"};
if(argc > 1) {
filename = argv[1];
}
// open the input file
std::ifstream inputFile(filename);
if(!inputFile.is_open()) {
std::cerr << "Unable to open " << filename << std::endl;
return 1;
}
std::string line;
// read the file line by line
while(getline(inputFile, line)) {
if(line.empty()) continue;
std::stringstream ss(line);
std::vector<int> v;
int x;
// extract the content as integer from line
while(ss >> x) {
v.push_back(x);
}
// add them all
auto total = std::accumulate(v.begin(), v.end(), 0);
std::cout << total << std::endl;
}
}
As in Aamir's answer, but with separate listing of sums and numbers per line. Maybe that helps too.
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
int main(int argc, char *argv[]) {
std::string filename{"input.txt"};
if(argc > 1) {
filename = argv[1];
}
// open the input file
std::ifstream inputFile(filename);
if(!inputFile.is_open()) {
std::cerr << "Unable to open " << filename << std::endl;
return 1;
}
std::vector<int> v_numberSum;
std::vector<int> v_numbersPerLine;
std::string line;
// read the file line by line
int i = 0;
while(getline(inputFile, line)) {
if(line.empty()) continue;
v_numberSum.push_back(0);
v_numbersPerLine.push_back(0);
std::stringstream f(line);
std::string s;
int cnt = 0;
while (getline(f, s, ' ')) {
v_numberSum[i] += std::stoi(s);
cnt++;
}
v_numbersPerLine[i] = cnt;
i++;
}
int j = 0;
for (auto intItem: v_numberSum){
std::cout << "sum"<<j<<": " << intItem << " numbers per line: " << v_numbersPerLine[j] << std::endl;
j++;
}
}
I am trying to write a code which lists all words used in a text file without repeating. I succeeded to list all the words but I always get repeating ,the if statement line 17 always gives the value of 0.I have no idea why , the words are listed properly in the vector. Any suggestion ?
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
class reading {
public:
string word;
vector<string> words;
};
int checkifexist(string word) {
reading readingobject;
bool exist = false;
for (int i = 0; i < readingobject.words.size(); i++) {
if (word == readingobject.words[i]) {
exist = true;
break;
}
}
return exist;
}
int main() {
reading readingobject;
ifstream inFile;
inFile.open("Book.txt");
if (inFile.fail()) {
cout << "file didn't open" << endl;
exit(1);
}
readingobject.word.resize(1);
while (!inFile.eof()) {
inFile >> readingobject.word;
if (checkifexist(readingobject.word) == 1)
continue;
cout << readingobject.word << endl;
readingobject.words.push_back(readingobject.word);
}
return 0;
}
Inside of checkifexist(), you are creating a new reading object, whose words vector is empty, so there is nothing for the loop to do, and the function returns 0.
You need to instead pass in the reading object from main() as an input parameter, eg:
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
class reading {
public:
vector<string> words;
};
bool checkifexist(const reading &readingobject, const string &word)
{
for (size_t i = 0; i < readingobject.words.size(); ++i) {
if (word == readingobject.words[i]) {
return true;
}
}
return false;
/* alternatively:
return (std::find(readingobject.words.begin(), readingobject.words.end(), word) != readingobject.words.end());
*/
}
int main()
{
reading readingobject;
string word;
ifstream inFile;
inFile.open("Book.txt");
if (!inFile) {
cout << "file didn't open" << endl;
return 1;
}
while (inFile >> word) {
if (checkifexist(readingobject, word))
continue;
cout << word << endl;
readingobject.words.push_back(word);
}
return 0;
}
Alternatively, when it comes to tracking unique elements, you can use a std::set instead of a std::vector, eg:
#include <iostream>
#include <fstream>
#include <set>
using namespace std;
class reading {
public:
set<string> words;
};
int main()
{
reading readingobject;
string word;
ifstream inFile;
inFile.open("Book.txt");
if (!inFile) {
cout << "file didn't open" << endl;
return 1;
}
while (inFile >> word) {
if (readingobject.words.insert(word).second)
cout << word << endl;
}
return 0;
}
trying to add words from this text file but keep getting thrown an out of range error. I think the error lies somehwere in the loops but havent been able to figure out why it isnt working. Help would be greatly appreciated
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
struct WordCount{
string word;
int count;
};
int main () {
vector<WordCount> eggsHam;
ifstream readFile ("NewTextDocument.txt");
int counter = 0;
int holder;
string lineRead;
WordCount word;
if(readFile.is_open()){
//add all the words into a vector
while (getline(readFile, lineRead)){
holder = counter;
for(int i = 0; i < lineRead.length(); ++i) {
if (lineRead.at(i) != ' ') {
++counter;
}
if (lineRead.at(i) != ' ') {
for (int k = 0; k < (counter - holder); ++k) {
word.word.at(k) = lineRead.at(holder + k);
}
eggsHam.push_back(word);
++counter;
}
}
}
readFile.close();
}
else cout << "Unable to open file";
return 0;
}
Your code is way to complicated. To read all words (=space-seperated thingies) into a std::vector<std::string> simply do:
#include <cstdlib>
#include <vector>
#include <string>
#include <iterator>
#include <fstream>
#include <iostream>
int main()
{
char const *filename = "test.txt";
std::ifstream is{ filename };
if (!is.is_open()) {
std::cerr << "Couldn't open \"" << filename << "\" for reading :(\n\n";
return EXIT_FAILURE;
}
std::vector<std::string> words{ std::istream_iterator<std::string>{ is },
std::istream_iterator<std::string>{} };
for (auto const &w : words)
std::cout << w << '\n';
}
I am pretty new to c++. I am trying to read a file in line by line and store the input into several arrays.
Because I don't know the size of input file, I have this to get the number of lines in the file
while (std::getline(inputFile, line)){
++numOfLines;
std::cout << line << std::endl;
}
Now I want to use the numOfLines as the size of arrays, but i cannot get it run by having this
std::string *firstName= new std::string[numOfLines];
std::string *lastName= new std::string[numOfLines];
for (int i = 0; i < numOfLines; ++i)
{
line >> firstName[i];
}
I guess it is because it has reached the end of the file after the while loop. But I do not know how to solve this problem. Is there a way to scan the input file in and store the value into array at the same time?
If you use std::vector you don't need to know ahead the lines count. You can use vector method push_back to insert new elements into it. Try use something like this:
#include <fstream>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
std::vector<std::string> first_names;
std::string line;
ifstream input_file;
while (std::getline(input_file, line)){
first_names.push_back(line);
}
for (size_t i = 0; i < first_names.size(); i++) {
std::cout << first_names[i] << std::endl;
}
return 0;
}
I don't know if you have ever taken a course related to Data Structures & Algorithms,
in which you will learn to use Containers (such as:
vector,
deque,
list, etc.) instead of Primitive Data Structures.
Please notice that although the follow example chooses vector as its container, it could vary according to different contexts. Say you are handling gigantic mount of data, you might want to use list instead`1,2,3.
#include <fstream>
#include <iostream>
#include <vector>
#include <string>
// alias long type
// #see: https://en.cppreference.com/w/cpp/language/type_alias
using NameVector = std::vector<std::string>;
int handleLine(std::string line, NameVector &firstNames)
{
// TODO implement your line handler here
firstNames.push_back(line);
return 0;
}
int handleFile(std::ifstream inputFile, NameVector &firstNames)
{
std::string line;
for (int lineNum = 1;
// invoke `good` to check if there is any error
inputFile.good()
&&
std::getline(inputFile, line);
lineNum++)
{
std::cout << "Current line number : (" << lineNum << ")" << std::endl;
std::cout << "Current line content: (" << line << ")" << std::endl;
handleLine(line, &firstNames);
}
return 0;
}
int main()
{
std::string path; // = R"(HERE GOES YOUR FILE PATH)";
// Using **Raw string**
std::ifstream inputFile { path }; // Initialize `inputFile`
NameVector firstNames;
handleFile(inputFile, firstNames);
for (auto firstName : firstNames)
{
std::cout << firstName << std::endl;
}
return 0;
}
I'm a beginner in c++ and required to write a c++ program to read and print a csv file like this.
DateTime,value1,value2
12/07/16 13:00,3.60,50000
14/07/16 20:00,4.55,3000
May I know how can I proceed with the programming?
I manage to get the date only via a simple multimap code.
I spent some time to make almost (read notice at the end) exact solution for you.
I assume that your program is a console application that receives the original csv-file name as a command line argument.
So see the following code and make required changes if you like:
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <map>
#include <string>
std::vector<std::string> getLineFromCSV(std::istream& str, std::map<int, int>& widthMap)
{
std::vector<std::string> result;
std::string line;
std::getline(str, line);
std::stringstream lineStream(line);
std::string cell;
int cellCnt = 0;
while (std::getline(lineStream, cell, ','))
{
result.push_back(cell);
int width = cell.length();
if (width > widthMap[cellCnt])
widthMap[cellCnt] = width;
cellCnt++;
}
return result;
}
int main(int argc, char * argv[])
{
std::vector<std::vector<std::string>> result; // table with data
std::map<int, int> columnWidths; // map to store maximum length (value) of a string in the column (key)
std::ifstream inpfile;
// check file name in the argv[1]
if (argc > 1)
{
inpfile.open(argv[1]);
if (!inpfile.is_open())
{
std::cout << "File " << argv[1] << " cannot be read!" << std::endl;
return 1;
}
}
else
{
std::cout << "Run progran as: " << argv[0] << " input_file.csv" << std::endl;
return 2;
}
// read from file stream line by line
while (inpfile.good())
{
result.push_back(getLineFromCSV(inpfile, columnWidths));
}
// close the file
inpfile.close();
// output the results
std::cout << "Content of the file:" << std::endl;
for (std::vector<std::vector<std::string>>::iterator i = result.begin(); i != result.end(); i++)
{
int rawLen = i->size();
for (int j = 0; j < rawLen; j++)
{
std::cout.width(columnWidths[j]);
std::cout << (*i)[j] << " | ";
}
std::cout << std::endl;
}
return 0;
}
NOTE: Your task is just to replace a vector of vectors (type std::vector<std::vector<std::string>> that are used for result) to a multimap (I hope you understand what should be a key in your solution)
Of course, there are lots of possible solutions for that task (if you open this question and look through the answers you will understand this).
First of all, I propose to consider the following example and to try make your task in the simplest way:
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
using namespace std;
int main()
{
string str = "12/07/16 13:00,3.60,50000";
stringstream ss(str);
vector<string> singleRow;
char ch;
string s = "";
while (ss >> ch)
{
s += ch;
if (ss.peek() == ',' || ss.peek() == EOF )
{
ss.ignore();
singleRow.push_back(s);
s.clear();
}
}
for (vector<string>::iterator i = singleRow.begin(); i != singleRow.end(); i++)
cout << *i << endl;
return 0;
}
I think it can be useful for you.