I need simple program in C++ that will open text file and going line by line find second argument by knowing first in list.
Content of text file:
1, red
2, blue
3, green
4, orange
So I need a program that will go line by line and each line turn into array ( of two elements ) and then compare first element with user interactively inserted number.
So if user insert 2, it goes line by line, comparing first element of array-ed line and if it matches, it prints second element in array ( blue ), and if user type 3, it prints green...
I have always working in PHP, and it's much easier than this, so I am stuck a little bit with this now... :/
Here you go:
#include <iostream>
#include <fstream>
#include <map>
#include <sstream>
int main(int argc, char* argv[]) {
if (argc != 2) {
std::cerr << "Usage: test [inputfile]" << std::endl;
return 1;
}
std::fstream stream(argv[1]);
if (!stream.good()) {
std::cerr << "Error: could not open file: " << argv[1] << std::endl;
return 2;
}
std::string line;
std::map<int, std::string> map;
while (std::getline(stream, line)) {
std::string::size_type pos = line.find(',');
std::stringstream sstream(line.substr(0, pos));
int index;
sstream >> index;
map[index] = line.substr(pos+2);
}
int in;
while (std::cin >> in) {
std::map<int, std::string>::iterator i = map.find(in);
if (i == map.end())
std::cerr << "index not found" << std::endl;
else
std::cout << i->second << std::endl;
}
return 0;
}
Q1: How do you open text file in C++ ?
Q2: How do you read file line by line?
C++ Input/Output with files
Q3: How do you turn string with "," into array based on that delimiter?
How to split a string in C++?
This is probably not helpful, except for me; I get to practice using Spirit parsing (and karma output generation as a bonus):
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/std_pair.hpp>
#include <fstream>
#include <map>
namespace qi = ::boost::spirit::qi;
namespace karma = ::boost::spirit::karma;
typedef std::map<int, std::string> index_t;
index_t read_index(const char* filename)
{
using boost::spirit::istream_iterator;
using namespace qi;
index_t result;
std::ifstream ifs(filename);
ifs.unsetf(std::ios::skipws);
istream_iterator begin(ifs), end;
if (!parse(begin, end, (int_ >> omit[lit(',') >> *char_(" \t")] >> *(char_ - eol)) % eol, result))
{
throw std::runtime_error("Unable to read/parse index file ");
}
return result; // http://en.wikipedia.org/wiki/Return_value_optimization
}
int main()
{
index_t index = read_index("input.txt");
using namespace karma;
std::cout << format(('[' << int_ << ": " << *char_ << ']') % eol, index) << std::endl;
for (int i=0; i<10; i++)
{
int lookup=rand()%6;
std::cout << "Random lookup: " << lookup << ": " << index[lookup] << std::endl;
}
return 0;
}
Oh, sample output:
[1: red]
[2: blue]
[3: green]
[4: orange]
Random lookup: 1: red
Random lookup: 4: orange
Random lookup: 3: green
Random lookup: 1: red
Random lookup: 5:
Random lookup: 1: red
Random lookup: 4: orange
Random lookup: 0:
Random lookup: 3: green
Random lookup: 1: red
Related
I'm trying to read and parse my CSV files in C++ and ran into an error.
The CSV has 1-1000 rows and always 8 columns.
Generally what i would like to do is read the csv and output only lines that match a filter criteria. For example column 2 is timestamp and only in a specific time range.
My problem is that my program cuts off some lines.
At the point where the data is in the string record variable its not cutoff. As soon as I push it into the map of int/vector its cutoff. Am I doing something wrong here?
Could someone help me identify what the problem truly is or maybe even give me a better way to do this?
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <map>
#include "csv.h"
using std::cout; using std::cerr;
using std::endl; using std::string;
using std::ifstream; using std::ostringstream;
using std::istringstream;
string readFileIntoString(const string& path) {
auto ss = ostringstream{};
ifstream input_file(path);
if (!input_file.is_open()) {
cerr << "Could not open the file - '"
<< path << "'" << endl;
exit(EXIT_FAILURE);
}
ss << input_file.rdbuf();
return ss.str();
}
int main()
{
int filterID = 3;
int filterIDIndex = filterID;
string filter = "System";
/*Filter ID's:
0 Record ID
1 TimeStamp
2 UTC
3 UserID
4 ObjectID
5 Description
6 Comment
7 Checksum
*/
string filename("C:/Storage Card SD/Audit.csv");
string file_contents;
std::map<int, std::vector<string>> csv_contents;
char delimiter = ',';
file_contents = readFileIntoString(filename);
istringstream sstream(file_contents);
std::vector<string> items;
string record;
int counter = 0;
while (std::getline(sstream, record)) {
istringstream line(record);
while (std::getline(line, record, delimiter)) {
items.push_back(record);
cout << record << endl;
}
csv_contents[counter] = items;
//cout << csv_contents[counter][0] << endl;
items.clear();
counter += 1;
}
I can't see a reason why you data is being cropped, but I have refactored you code slightly and using this it might be easier for you to debug the problem, if it doesn't just disappear on its own.
int main()
{
string path("D:/Audit.csv");
ifstream input_file(path);
if (!input_file.is_open())
{
cerr << "Could not open the file - '" << path << "'" << endl;
exit(EXIT_FAILURE);
}
std::map<int, std::vector<string>> csv_contents;
std::vector<string> items;
string record;
char delimiter = ';';
int counter = 0;
while (std::getline(input_file, record))
{
istringstream line(record);
while (std::getline(line, record, delimiter))
{
items.push_back(record);
cout << record << endl;
}
csv_contents[counter] = items;
items.clear();
++counter;
}
return counter;
}
I have tried your code and (after fixing the delimiter) had no problems, but I only had three lines of data, so if it is a memory issue it would have been unlikely to show.
i have loaded both of my files into an array and im trying to compare both of the files to get the comparisons inside the file. However when I run my code I don't receive an output.
This is the contents of both files.
file1
tdogicatzhpigu
file2
dog
pig
cat
rat
fox
cow
So when it does a comparison between the words from search1.txt and the words from text1.txt. I want to find the occurence of each word from search1.txt in text1.txt
What I want to eventually output is whether it has been found the index of the location inside the array.
e.g
"dog". Found, location 1.
Here is my code
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
ifstream file1("text1.txt");
if (file1.is_open())
{
string myArray[1];
for (int i = 0; i < 1; i++)
{
file1 >> myArray[i];
any further help would be greatly appreciated. Thanks in advance.
I believe the goal is to search the text in file1 for each word in file2.
You can't use equality for the two strings, as they aren't equal. You'll need to use the std::string::find method:
std::string target_string;
std::getline(file1, target_string);
std::string keyword;
while (getline(file2, keyword))
{
const std::string::size_type position = target_string.find(keyword);
std::cout << "string " << keyword << " ";
if (position == std::string::npos)
{
std::cout << "not found.\n";
}
else
{
std::cout << "found at position " << position << "\n";
}
}
Edit 1:
An implemented example:
#include <iostream>
#include <string>
using std::cout;
using std::string;
using std::endl;
int main()
{
const std::string target_string = "tdogicatzhpigu";
const std::string key_list[] =
{
"dog",
"pig",
"cat",
"rat",
"fox",
"cow",
};
static const unsigned int key_quantity =
sizeof(key_list) / sizeof(key_list[0]);
for (unsigned int i = 0; i < key_quantity; ++i)
{
const std::string::size_type position = target_string.find(key_list[i]);
std::cout << "string " << key_list[i] << " ";
if (position == std::string::npos)
{
std::cout << "not found.\n";
}
else
{
std::cout << "found at position " << position << "\n";
}
}
return 0;
}
I want to read word by word from a text file. Here's my code in C++:
int main(int argc, const char * argv[]) {
// insert code here...
ifstream file("./wordCount.txt");
string word;
while(file >> word){
cout<<word<<endl;
}
return 0;
}
The text file contains the sentence:
I don't have power, but he has power.
Here's the result I get:
I
don\241\257t
have
power,
but
he
has
power.
Can you tell me how to get the result like the below format:
I
don't
have
power
but
he
has
power
Thanks.
I understand that you're looking for getting rid of the punctuation.
Unfortunately, extracting strings from a stream looks only for spaces as separator. So "don't" or "Hello,world" would be read as one word, and "don' t" or "Hello, world" as two words.
The alternative, is to read the text line by line, and use string::find_first_of() to jump from separator to separator:
string separator{" \t\r\n,.!?;:"};
string line;
string word;
while(getline (cin, line)){ // read line by line
size_t e,s=0; // s = offset of next word, e = end of next word
do {
s = line.find_first_not_of(separator,s); // skip leading separators
if (s==string::npos) // stop if no word left
break;
e=line.find_first_of(separator, s); // find next separator
string word(line.substr(s,e-s)); // construct the word
cout<<word<<endl;
s=e+1; // position after the separator
} while (e!=string::npos); // loop if end of line not reached
}
Online demo
The code below, gets rid of punctuation, except of the apostrophe:
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
using namespace std;
int main(int argc, const char * argv[]) {
ifstream file("wordCount.txt");
string word;
while(file >> word) {
for (auto c : word)
if (ispunct(c) && c != '`')
word.erase(word.find_first_of(c));
cout << word << endl;
}
return 0;
}
should produce the desired output:
Georgioss-MacBook-Pro:~ gsamaras$ g++ -Wall -std=c++0x main.cpp
Georgioss-MacBook-Pro:~ gsamaras$ ./a.out
I
don`t
have
power
but
he
has
power
For the problem with some characters, I encourage you to check the encoding of the file, so try doing (as explained here):
file -I wordCount.txt
wordCount.txt: text/plain; charset=us-ascii
which is what worked for me. Or simply open a text editor and make sure the characters are valid.
To ease debug, I replace the file with std::istringstream.
easy to add additional test input
input is thus documented, and repeatable.
I also added a bool (class data attribute) to simplify enable/disable of additional diagnostic information. (m_dbg)
#include <algorithm>
#include <chrono>
// 'compressed' chrono access --------------vvvvvvv
typedef std::chrono::high_resolution_clock HRClk_t; // std-chrono-hi-res-clk
typedef HRClk_t::time_point Time_t; // std-chrono-hi-res-clk-time-point
typedef std::chrono::microseconds MS_t; // std-chrono-milliseconds
typedef std::chrono::microseconds US_t; // std-chrono-microseconds
typedef std::chrono::nanoseconds NS_t; // std-chrono-nanoseconds
using namespace std::chrono_literals; // support suffixes like 100ms, 2s, 30us
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <vector>
class T496_t
{
std::array<char, 256> m_keep;
std::vector<std::string> m_wordVec;
bool m_dbg = false;
public:
T496_t()
{
for (uint i=0; i<256; ++i)
m_keep[i] = static_cast<char>(i);
m_keep[uint(',')] = 0;
m_keep[uint('.')] = 0;
}
~T496_t() = default;
int exec()
{
std::istringstream file(
"Hello\n"
"I don't have power, but he has power.\n"
"I don't have power , but he has power.\n"
); //ifstream file("./wordCount.txt");
uint lineCount = 1;
while(1)
{
std::string line;
(void)std::getline(file, line);
if(file.eof())
{
ltrim(line);
if(0 != line.size())
if(m_dbg) std::cout << __LINE__ << " tail: " << line << std::endl;
break;
}
if(m_dbg) std::cout << "\n line " << lineCount++ << " : '"
<< line << "'\n " << std::setfill('-')
<< std::setw(static_cast<int>(line.size())+12)
<< "-" << std::setfill(' ');
std::cout << '\n';
size_t sz = line.size();
if(0 == sz)
continue; // ignore empty lines
extractWordsFrom(line); // extract words
if(file.eof()) break;
}
return(0);
}
private: // methods
void extractWordsFrom(std::string& unfiltered)
{
std::string line; // filtered
filter(unfiltered, line);
if(0 == line.size()) {
if(m_dbg) std::cout << " empty line" << std::endl; return;
}
size_t indx1 = 0;
do {
while(isspace(line[indx1])) { indx1 += 1; } // skip leading spaces
size_t indx2 = line.find(" ", indx1);
if(std::string::npos == indx2)
{
m_wordVec.push_back(line.substr(indx1));
if(m_dbg) std::cout << " word(" << std::setw(3) << indx1 << ", eoln): ";
std::cout << " " << m_wordVec.back() << std::endl;
break;
}
m_wordVec.push_back(line.substr(indx1, indx2-indx1));
if(m_dbg) std::cout << " word(" << std::setw(3) << indx1 << ","
<< std::setw(3) << indx2 << "): ";
std::cout << " " << m_wordVec.back() << std::endl;
indx1 = indx2+1;
}while(1);
}
void filter(std::string& unfiltered, std::string& line)
{
ltrim(unfiltered); // remove leading blanks
for(uint i=0; i<unfiltered.size(); ++i) // transfer all chars
if(m_keep[unfiltered[i]]) // exception check
line.push_back(unfiltered[i]);
}
// trim from start
void ltrim(std::string &s) {
s.erase(s.begin(),
std::find_if(s.begin(), s.end(),
std::not1(std::ptr_fun<int, int>(std::isspace)) ));
}
// trim from end
void rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(),
std::not1(std::ptr_fun<int, int>(std::isspace))).base(),s.end());
}
// trim from both ends
void lrtrim(std::string &s) { rtrim(s); ltrim(s); }
}; // class T496_t
int main(int /*argc*/, char** /*argv[]*/)
{
setlocale(LC_ALL, "");
std::ios::sync_with_stdio(false);
Time_t start_us = HRClk_t::now();
int retVal = -1;
{
T496_t t496;
retVal = t496.exec();
}
auto duration_us = std::chrono::duration_cast<US_t>(HRClk_t::now() - start_us);
std::cout << "\n\n FINI " << duration_us.count() << " us" << std::endl;
return(retVal);
}
// desired output:
// I
// don't
// have
// power
// but
// he
// has
// power
Output from this code:
Hello
I
don't
have
power
but
he
has
power
I
don't
have
power
but
he
has
power
Output with m_dbg=true
line 1 : 'Hello'
-----------------
word( 0, eoln): Hello
line 2 : 'I don't have power, but he has power.'
-------------------------------------------------
word( 0, 1): I
word( 2, 7): don't
word( 8, 12): have
word( 13, 18): power
word( 19, 22): but
word( 23, 25): he
word( 26, 29): has
word( 30, eoln): power
line 3 : 'I don't have power , but he has power.'
---------------------------------------------------
word( 0, 1): I
word( 2, 7): don't
word( 9, 13): have
word( 14, 19): power
word( 21, 24): but
word( 25, 27): he
word( 28, 31): has
word( 32, eoln): power
FINI 215 us
A simple approach is first to filter the string. Remove any punctuation except apostrophe (i.e. ' ) and replace them with white-space for further manipulation (i.e. to take advantage of some built-in functions).
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <sstream>
#include <iterator>
using namespace std;
bool isOk(char c)
{
if ( ispunct(c) )
if ( c == '\'' )
return false;
return ispunct(c);
}
int main()
{
ifstream file("data.txt");
string word;
while(file >> word){
std::replace_if(word.begin(), word.end(), isOk, ' ');
istringstream ss(word);
copy(istream_iterator<string>(ss), istream_iterator<string>(), ostream_iterator<string>(cout, "\n"));
}
return 0;
}
The output is
I
don't
have
power
but
he
has
power
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.
I am trying to create a C++ code that using boost libraries reads an input file like the following,
1 12 13 0 0 1 0 INLE
.
.
.
In this case, I must do an action if the condition specified on the last column of the right is INLE.
I have the following code,
#include <iostream>
#include <fstream>
#include <string>
#include <boost/algorithm/string/predicate.hpp>
int main(int argc, const char * argv[])
{
std::string line;
const std::string B_condition = "INLE";
std::ifstream myfile ("ramp.bnd");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
if (boost::algorithm::ends_with(line,B_condition)==true)
{
std::cout << "Its True! \n"; // just for testing
//add complete code
}
}
myfile.close();
}
else std::cout << "Unable to open file";
return 0;
}
while compiling there are no issues, but when I run, it doesnt shows anything.
By the other side, if I modify my boolean condition to false, it will print "Its true!" the number of lines that my input file has.
What am I doing wrong?
Thanks!!
I can only assume that:
your file contains whitespace at the end (use trim)
your file has windows line ends (CRLF) but you're reading it as UNIX text files, meaning that the lines will include a trailing `\r' (CR) (often shown as ^M in various text editors/pagers).
So, either
fix the line endings
trim whitespace from the lines before comparing
or both
Best: use a 'proper' parser to do the work.
Update adding a quick & dirty approach using Boost Spirit: see it Live On Coliru
int main()
{
std::ifstream myfile("ramp.bnd");
myfile.unsetf(std::ios::skipws);
boost::spirit::istream_iterator f(myfile), l;
using namespace qi;
bool ok = phrase_parse(f, l,
(repeat(7) [ int_ ] >> as_string[lexeme[+(char_ - eol)]])
[ phx::bind(process_line, _1, _2) ]
% eol, // supports CRLF and LF
blank);
if (!ok)
std::cerr << "Parse errors\n";
if (f!=l)
std::cerr << "Remaing input: '" << std::string(f,l) << "'\n";
}
As you can see, it validates the whole line, assuming (for now) that the columns are 7 integer values and a string (e.g. "INLE"). Now, the actual work is much simpler and can be implemented in a separate function:
void process_line(std::vector<int> const& values, std::string const& kind)
{
if (kind == "INLE")
{
std::cout << "Column 1: " << values[0] << "\n";
}
}
The actual processing function doesn't have to meddle with trimming, line ends, even parsing the details columns :)
Full Code for reference
#include <iostream>
#include <fstream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;
static const std::string B_condition = "INLE";
void process_line(std::vector<int> const& values, std::string const& kind)
{
if (kind == "INLE")
{
std::cout << "Column 1: " << values[0] << "\n";
}
}
int main()
{
std::ifstream myfile("ramp.bnd");
myfile.unsetf(std::ios::skipws);
boost::spirit::istream_iterator f(myfile), l;
using namespace qi;
bool ok = phrase_parse(f, l,
(repeat(7) [ int_ ] >> as_string[lexeme[+(char_ - eol)]])
[ phx::bind(process_line, _1, _2) ]
% eol, // supports CRLF and LF
blank);
if (!ok)
std::cerr << "Parse errors\n";
if (f!=l)
std::cerr << "Remaing input: '" << std::string(f,l) << "'\n";
}
You don't need a library like boost at all. A solution with pur standard C++ is possible in some lines of code too:
const std::string B_condition = "INLE";
std::ifstream myfile ("ramp.bnd");
for( char c; myfile >> c; )
{
if( std::isdigit(c, myfile.getloc() ) ) // needs #include <locale>
{
int i;
if( myfile.putback(c) >> i )
std::cout << "read " << i << std::endl; // do something with 'i'
}
else
{
std::string token;
if( myfile.putback(c) >> token )
{
if( token == B_condition )
std::cout << B_condition << " found\n";
else
; // no number, no B_condition -> what ever You want to do
}
}
}