I have 2 files: main.cpp and parser.hpp
I am returning vector<vector> from a member function in class in parser.hpp. However it seems I am not getting anything in my main.cpp from the return value because when I print its size I get 0.
This is my main.cpp:
#include <vector>
#include <cstring>
#include <fstream>
#include <iostream>
#include "parser.hpp"
using namespace std;
int main()
{
ifstream file;
file.open("test.csv");
csv obj;
obj.parse(file);
obj.print_parsed_csv(file);
vector<vector<string>> parsed_csv_data = obj.parse(file);
cout << parsed_csv_data.();
cout << parsed_csv_data.size();
for (int i = 0; i < parsed_csv_data.size(); i++)
{
for (int j = 0; j < parsed_csv_data[i].size(); j++)
cout << parsed_csv_data[i][j] << '\t';
cout << endl;
}
}
This is my parser.hpp
using namespace std;
class csv
{
public:
vector<vector<string>> parse(ifstream &file)
{
string str;
vector<vector<string>> parsed_data;
while (getline(file, str))
{
vector<string> parsed_line;
while (!str.empty())
{
int delimiter_pos = str.find(',');
string word = str.substr(0, delimiter_pos);
// cout << word << " ";
if (delimiter_pos == -1)
{
parsed_line.push_back(word);
break;
}
else
{
str = str.substr(delimiter_pos + 1);
// cout << str << endl;
parsed_line.push_back(word);
}
}
parsed_data.push_back(parsed_line);
}
return parsed_data;
}
void print_parsed_csv(ifstream &file)
{
vector<vector<string>> parsed_csv_data = parse(file);
cout << parsed_csv_data.size();
for (int i = 0; i < parsed_csv_data.size(); i++)
{
for (int j = 0; j < parsed_csv_data[i].size(); j++)
cout << parsed_csv_data[i][j] << '\t';
cout << endl;
}
}
};
I am getting correct cout output in parse() only. print_parsed_csv() in parser.hpp and the cout in main.cpp both are giving 0 as the variable's size.
How do I resolve this?
The first time you call obj.parse the stream object is read from until you get to the end of the file. You need to either reopen the file or reset file to point back to the beginning of the file after reading from it.
You pass the same file variable to each of the three functions below but only the first one works. The first call to obj.parse moves where file is pointing in the input file. When obj.parse exits the first time, file is pointing to the end of the file so when it's used in the subsequent 2 calls, there's nothing to read.
obj.parse(file); // <-- this works fine
obj.print_parsed_csv(file); // <-- this fails
vector<vector<string>> parsed_csv_data = obj.parse(file);fails
// ^^^^^^^^^- this fails
See this question for answers on how to reset the ifstream to the beginning of the file.
Goal: Android/iOS app that displays tricky-to-spell words when user puts in a letter.
The code runs correctly, except for non-English characters. The program allows some non-English curse words through when the user puts in their first name.
Expected result: Program will reject all curse words (within
nameCurseWordsList.txt)
Actual result: Some non-English curse words are let through.
Error messages: None
Tried:
Changing vector input and the related variable, userFirstName, to wstring.
Checked to see if VS2019 settings were set to "Autodetect UTF-8 encoding without signature" - Already enabled.
Changed encoding of nameCurseWordsList.txt from "UTF-8 with BOM" to "UTF-8".
Set VS2019's cmd output window to use the font Lucida Console.
How to handle unicode character sequences in C/C++?
How can my program switch from ASCII to Unicode?
How to show Unicode characters in Visual Studio?
Code:
// Description: Android/iOS application that takes in a letter and displays tricky-to-spell words.
#include <iostream>
#include <fstream>
#include <locale>
#include <string>
#include <vector>
#include <limits>
#include <sstream>
#include "usingDeclarations.hpp"
vector <string> trickyWordsVector;
vector <wstring> nameCurseWordsVector;
void printWords(char userLetterInput);
void getTrickyWords();
void getNameCurseWords();
int main() {
cout << "----------------<>-----------\n";
cout << "Welcome to Your TRICKY WORDS Helper!\n";
cout << "----------------<>-----------\n";
wstring userFirstName;
size_t firstNameOnlyAlpha{};
bool isNameCurseWord = false;
do {
cout << "\nEnter your first name: ";
getline(wcin, userFirstName);
for (unsigned __int8 i = 1; i < userFirstName.length(); i++) {
if (userFirstName[i - 1] == ' ') {
userFirstName[i] = toupper(userFirstName[i]);
} else {
userFirstName[i] = tolower(userFirstName[i]);
}
}
userFirstName[0] = toupper(userFirstName[0]);
firstNameOnlyAlpha = userFirstName.find_first_of(L"0123456789`~!##$%^&*()':'';''/'-_=+{}[]|:<>,.' '?'\t\"");
getNameCurseWords();
if (find(nameCurseWordsVector.begin(), nameCurseWordsVector.end(), userFirstName) != nameCurseWordsVector.end()) {
cout << "Curse word entered. Please freakin' try again.\n";
isNameCurseWord = true;
} else {
isNameCurseWord = false;
}
} while (isNameCurseWord || firstNameOnlyAlpha != string::npos || userFirstName.empty());
char userLetterInput;
char userChoiceContinue;
do {
do {
cout << "\nEnter a letter [a-z]: ";
cin >> userLetterInput;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
userLetterInput = toupper(userLetterInput);
if (isalpha(userLetterInput)) {
wcout << "\nHey " << userFirstName << ",\n\nHere's your list of tricky words for the letter (" << char(toupper(userLetterInput)) << "):\n" << endl;
}
} while (!isalpha(userLetterInput));
getTrickyWords();
printWords(userLetterInput);
do {
cout << "\nWould you like to enter another letter [y,n]?: ";
cin >> userChoiceContinue;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
} while (char(tolower(userChoiceContinue)) != 'y' && char(tolower(userChoiceContinue)) != 'n');
} while (char(tolower(userChoiceContinue)) == 'y');
cout << "\n----------------<>-----------\n";
cout << "Thank you for using Your TRICKY WORDS Helper!\n";
cout << "\n----------------<>-----------\n";
return 0;
} // end main()
void printWords(char userLetterInput) {
for (int i = 0; i < trickyWordsVector.size(); i++) {
if (trickyWordsVector[i][0] == userLetterInput) {
cout << trickyWordsVector[i];
cout << "\n";
}
}
} // end printWords()
void getTrickyWords() {
ifstream trickyWordsFile("trickyWordsList.txt");
if (trickyWordsFile.is_open()) {
if (trickyWordsVector.empty()) {
string line;
while (getline(trickyWordsFile, line)) {
if (line.size() > 0) {
trickyWordsVector.push_back(line);
}
}
}
}
else {
cerr << "Cannot open the file.";
}
trickyWordsFile.close();
} // end getTrickyWords()
void getNameCurseWords() {
wifstream nameCurseWordsFile("nameCurseWordsList.txt");
if (nameCurseWordsFile.is_open()) {
if (nameCurseWordsVector.empty()) {
wstring line;
while (getline(nameCurseWordsFile, line)) {
if (line.size() > 0) {
nameCurseWordsVector.push_back(line);
}
}
}
}
else {
cerr << "Cannot open the file, you sailor mouth. ;)";
}
nameCurseWordsFile.close();
} // end getNameCurseWords()
usingDeclarations.hpp
#pragma once
using std::cout;
using std::wcout;
using std::cin;
using std::wcin;
using std::cerr;
using std::getline;
using std::endl;
using std::use_facet;
using std::numeric_limits;
using std::streamsize;
using std::string;
using std::wstring;
using std::ifstream;
using std::wifstream;
using std::vector;
using std::locale;
using std::ctype;
trickyWordsList.txt or trickyWordsFile
Argument
Atheist
Axle
Bellwether
Broccoli
Bureau
Caribbean
Calendar
Camaraderie
Desiccate
Desperate
Deterrence
nameCurseWordsList.txt or nameCurseWordsFile (partial list)
// Irish
RáIcleach
// German
ScheißKopf
// Russian
Oбосра́ться
Obosrat'sya
// Chinese
王八蛋
Hùn Zhàng
// Japanese
くそ
// Korean
아, 씨발
Thanks for any advice.
Run code using https://repl.it/~
I am trying to write some string data to a .txt file that i read from the user but after doing so, the program shuts down instead of continuing and when i check the results inside the .txt file i see some part of the data and then some gibberish, followed by an assertion failure error! Here's the code:
#include "std_lib_facilities.h"
#include <fstream>
using namespace std;
using std::ofstream;
void beginProcess();
string promptForInput();
void writeDataToFile(vector<string>);
string fileName = "links.txt";
ofstream ofs(fileName.c_str(),std::ofstream::out);
int main() {
// ofs.open(fileName.c_str(),std::ofstream::out | std::ofstream::app);
beginProcess();
return 0;
}
void beginProcess() {
vector<string> links;
string result = promptForInput();
while(result == "Y") {
for(int i=0;i <= 5;i++) {
string link = "";
cout << "Paste the link skill #" << i+1 << " below: " << '\n';
cin >> link;
links.push_back(link);
}
writeDataToFile(links);
links.clear(); // erases all of the vector's elements, leaving it with a size of 0
result = promptForInput();
}
std::cout << "Thanks for using the program!" << '\n';
}
string promptForInput() {
string input = "";
std::cout << "Would you like to start/continue the process(Y/N)?" << '\n';
std::cin >> input;
return input;
}
void writeDataToFile(vector<string> links) {
if(!ofs) {
error("Error writing to file!");
} else {
ofs << "new ArrayList<>(Arrays.AsList(" << links[0] << ',' << links[1] << ',' << links[2] << ',' << links[3] << ',' << links[4] << ',' << links[5] << ',' << links[6] << ',' << "));\n";
}
}
The problem lies probably somewhere in the ofstream writing procedure but i can't figure it out. Any ideas?
You seem to be filling a vector of 6 elemenents, with indices 0-5, however in your writeDataToFile function are dereferencing links[6] which is out of bounds of your original vector.
Another thing which is unrelated to your problem, but is good practice:
void writeDataToFile(vector<string> links)
is declaring a function which performs a copy of your vector. Unless you want to specifically copy your input vector, you most probably want to pass a const reference, like tso:
void writeDataToFile(const vector<string>& links)
Hello I'm having problem with dividing two doubles on C++, on a basic C++ it's working fine, for example
double DfirstNumber = 4.3;
double DsecondNumber = 2.0;
double DthirdNumber = DfirstNumber/DsecondNumber;
std::cout << DthirdNumber;
but not on the code below:
#include <iostream>
#include <fstream>
#include <string>
#include <Windows.h>
#include <regex>
std::string getLastLine(std::ifstream& in)
{
std::string line;
while (in >> std::ws && std::getline(in, line)) // skip empty lines
;
return line;
}
int main()
{
double DfirstNumber;
double DsecondNumber;
while(true){
std::ifstream file("C:\\Users\\Admin\\Documents\\myfile.txt");
if (file)
{
std::string line = getLastLine(file);
Sleep(1000);
try {
std::regex re("\\d*\\.\\d*");
std::sregex_iterator next(line.begin(), line.end(), re);
int i = 0;
std::string firstNumber;
std::string secondNumber;
while (i < 3) {
std::smatch match = *next;
if (i == 1) {
firstNumber = match.str();
DfirstNumber = std::stof(firstNumber);
}
if (i == 2) {
secondNumber = match.str();
DsecondNumber = std::stof(secondNumber);
}
next++;
i++;
}
}
catch (std::regex_error&) {
std::cout << "regex error";
}
double DthirdNumber = DsecondNumber) / DfirstNumber;
std::cout << DthirdNumber << std::endl;
}
else{
std::cout << "Can't Open the file.\n";
}
}
}
I'm getting every second a new line on myfile.txt so I had to check the last line of file, then using regular expression to get the desired datas and store them to C++ variables.
This is how myfile.txt looks
Hello Name Name0.00042Surname NameSurname Name0.00042$100.03
Hello Name Name0.00143Surname NameSurname Name0.00143$100.53
Hello Name Name0.00342Surname NameSurname Name0.00342$100.32
..............................................^1stNr^.^2ndNr^
... and another program just continues to extract lines like these every second!
Could anyone explain to me why is this happening, because if I'm trying to divide for example
DfirstNumber = 407.33
DsecondNumber = 0.015982
I'm not getting 25486.79764735327 but I'm getting 25489.8
I've been looking at this for a while in the debugger while Googling around, but I think I've stumbled upon some C++ behavior that I'm not familiar with. I'm going to give a quick outline on what I'm doing and what/where the problem is. I'll put code block below.
The rough outline of what's happening is:
Created a custom class (LogReader) to handle a single log file.
LogReader contains a pointer to an ifstream (ifstream *log_file)
The ifstream is used with getline() in the constructor, this works fine.
The LogReader is placed in a vector.
The code below for main.cpp is using the LogReader directly (without the vector). The segfault occurs in both cases.
LogReader.advance() is called. getline() is used in this function. The segfault occurs here (commented in LogReader.cpp).
Thanks for any help on what C++ behaviors I'm missing that might be causing this!
EDIT: Not placing the LogReader into a vector removes the segfault (failing elsewhere now, but not a problem). The change is commenting the following line out in main.cpp
readers.push_back(&label_reader);
I guess now the question is why using std::vector is causing this problem.
LogReader.h
#ifndef LOGREADER
#define LOGREADER
using namespace std;
class LogReader {
private:
LogReader(){} // private default constructor
public:
ifstream *log_file; // file the log is read from
vector<int> val_locations; // offsets in line for values
string next_line; // next line from the file
int current_time; // time for most recent reading
string current_line;
int next_time; // what is the next time in the file
vector<string> current_vals; // what the current vals are
LogReader(string log_loc, vector<int> offsets); // given a file to start on
bool advance(int new_time); // advance the log reader, return true if advanced
bool has_more(); // is there more in the log
};
#endif
LogReader.cpp
// c++ imports
#include <boost/algorithm/string.hpp>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
// my imports
#include "LogReader.h"
#include "functions.h"
using namespace std;
LogReader::LogReader(string log_loc, vector<int> offsets){
// make the file reader
ifstream lf(log_loc);
log_file = &lf;
// pull out the first line
getline(*log_file, current_line);
cout << current_line << endl;
// get the set of current values
val_locations = offsets;
for(int i = 0; i < val_locations.size(); i++) {
current_vals.push_back(get_line_part(current_line,
val_locations.at(i)));
}
// get the current time
current_time = stoi(get_line_part(current_line, 0));
// pull down the next line
getline(*log_file, next_line);
cout << next_line << endl;
// get the next time
next_time = stoi(get_line_part(next_line, 0));
}
bool LogReader::advance(int new_time){
if(new_time < next_time)
return false; // nothing to do, current still good
cout << "can check time" << endl;
// update the time and values
current_time = next_time;
current_line = next_line;
current_vals.clear();
cout << "can do housekeeping" << endl;
for(int i = 0; i < val_locations.size(); i++) {
current_vals.push_back(get_line_part(next_line,
val_locations.at(i)));
}
cout << "can push in new values" << endl;
// move the line
next_line.clear();
if(!getline(*log_file, next_line)) { // **SEGFAULT**
// no more lines
cout << "no more lines" << endl;
next_line.clear();
next_time = -1;
return true;
}
cout << "got the line" << endl;
// update the time as well
next_time = stoi(get_line_part(next_line, 0));
return true;
}
bool LogReader::has_more(){
return next_time != -1;
}
main.cpp
// c imports
#include <time.h>
// c++ imports
#include <algorithm>
#include <boost/algorithm/string.hpp>
#include <boost/date_time.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/filesystem.hpp>
#include <fstream>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
// my imports
#include "LogReader.h"
#include "functions.h"
// custom shorter namespaces
namespace bfs = boost::filesystem;
// used namespaces
using namespace std;
void update_line(int *current_time, string *current_line,
ifstream *current_file){
if(!getline(*current_file, *current_line)){
*current_time = -1;
current_line->clear();
return;
}
try {
*current_time = stoi(get_line_part(*current_line, 0));
} catch (int e) {
cout << "update line, bad stoi on time" << endl;
cout << *current_line << endl;
throw e;
}
}
void update_vals(vector<float*> vals, string line) {
for(int i = 0; i < vals.size(); i++) {
// offset for fact that first two are time and sensor
try {
*(vals.at(i)) = stof(get_line_part(line, 2 + i));
} catch (int e) {
cout << "update_vals, bad stof for " << i << endl;
cout << line << endl;
throw e;
}
}
}
string get_correct_file(string name, vector<string> options) {
for(int i =0; i < options.size(); i++) {
string option = options.at(i);
if(boost::algorithm::contains(option, name)){
return option;
}
}
return string("");
}
int main(int argc, char* argv[]) {
// open the base dir
bfs::path base_dir("log/");
if(!bfs::exists(base_dir) && !bfs::is_directory(base_dir)){
cout << "Bad base directory" << endl;
return 1;
}
// create a vector of the possible traces
vector<string> traces;
for(bfs::directory_iterator iter(base_dir);
iter != bfs::directory_iterator(); iter++) {
stringstream trace_path;
trace_path << iter->path().string();
traces.push_back(trace_path.str());
}
int trace_index = user_choose_option(traces);
// load that directory
bfs::path trace_dir(traces.at(trace_index));
if(!bfs::exists(base_dir) && !bfs::is_directory(base_dir)){
cout << "Selected a bad trace directory" << endl;
return 1;
}
// get the image directory
cout << "loading image directory" << endl;
string img_path_string = trace_dir.string();
stringstream img_path_stream;
img_path_stream << img_path_string << "/img/";
bfs::path img_dir(img_path_stream.str());
if(!bfs::exists(img_dir) && !bfs::is_directory(img_dir)){
cout << "no image directory" << endl;
return 1;
}
// get image list, ends up in sorted order from naming conventions
cout << "getting image paths" << endl;
vector<string> image_paths;
for(bfs::directory_iterator iter(img_dir);
iter != bfs::directory_iterator(); iter++) {
stringstream image_path;
image_path << iter->path().string();
image_paths.push_back(image_path.str());
}
// get the data traces
cout << "loading data traces" << endl;
vector<string> log_paths;
vector<string> label_paths;
string trace_path_string = trace_dir.string();
for(bfs::directory_iterator iter(trace_path_string);
iter != bfs::directory_iterator(); iter++) {
string cur_file = iter->path().string();
cout << cur_file << endl;
if(boost::algorithm::contains(cur_file, "label-")) {
label_paths.push_back(cur_file);
} else if(boost::algorithm::contains(cur_file, "log-")) {
log_paths.push_back(cur_file);
}
}
cout << endl;
// temp for reading in line parts
// istringstream temp;
cout << "getting log readers" << endl;
// choose the label file to use, get first line
int label_index = user_choose_option(label_paths);
vector<int> label_offsets;
label_offsets.push_back(1);
LogReader label_reader(label_paths.at(label_index), label_offsets);
/*
ifstream label_file(label_paths.at(label_index));
string label_line;
getline(label_file, label_line);
int label_time;
temp.clear();
temp.str(get_line_part(label_line, 0));
temp >> label_time;
string label_current = get_line_part(label_line, 1);
*/
/*
// get the accel
string accel_path = get_correct_file("accel", log_paths);
vector<int> accel_offsets;
accel_offsets.push_back(2);
accel_offsets.push_back(3);
accel_offsets.push_back(4);
LogReader accel_reader(accel_path, accel_offsets);
*/
vector<LogReader*> readers;
vector<bool> updated;
readers.push_back(&label_reader);
updated.push_back(true);
// readers.push_back(&accel_reader);
// updated.push_back(true);
int l_time = current_time_min(readers);
while(label_reader.has_more() ){ // || accel_reader.has_more()) {
// figure out what time to advance to
int n_time;
cout << label_reader.has_more() << endl;
if(same_current_time(readers)) {
n_time = next_time_min(readers);
} else {
n_time = current_time_nextmin(readers);
}
cout << n_time << endl;
label_reader.advance(n_time);
cout << label_reader.current_line << endl;
/*
// advance all the readers
for(int i = 0; i < readers.size(); i++) {
cout << "loop " << i << endl;
// keep track of which values updated
readers.at(i);
cout << "can get from vector" << endl;
bool advanced = readers.at(i)->advance(n_time);
cout << advanced << endl;
if(advanced) {
updated.at(i) = true;
} else {
updated.at(i) = false;
}
}
// sanity check printing
for(int i = 0; i < readers.size(); i++) {
cout << readers.at(i)->current_line << endl;
}
*/
// deal with statistics here
}
/*
ifstream accel_file(accel_path);
string accel_line;
getline(accel_file, accel_line);
int accel_time;
temp.clear();
temp.str(get_line_part(accel_line, 0));
temp >> accel_time;
float accel_current_x = stof(get_line_part(accel_line, 2));
float accel_current_y = stof(get_line_part(accel_line, 3));
float accel_current_z = stof(get_line_part(accel_line, 4));
vector<float*> accel_vals;
accel_vals.push_back(&accel_current_x);
accel_vals.push_back(&accel_current_y);
accel_vals.push_back(&accel_current_z);
// get the sprox
string sprox_path = get_correct_file("sprox", log_paths);
ifstream sprox_file(sprox_path);
string sprox_line;
getline(sprox_file, sprox_line);
int sprox_time;
temp.clear();
temp.str(get_line_part(sprox_line, 0));
temp >> sprox_time;
float sprox_current = stof(get_line_part(sprox_line, 2));
vector<float*> sprox_vals;
sprox_vals.push_back(&sprox_current);
// get the lprox
string lprox_path = get_correct_file("lprox", log_paths);
ifstream lprox_file(lprox_path);
string lprox_line;
getline(lprox_file, lprox_line);
int lprox_time;
temp.clear();
temp.str(get_line_part(lprox_line, 0));
temp >> lprox_time;
float lprox_current = stof(get_line_part(lprox_line, 2));
vector<float*> lprox_vals;
lprox_vals.push_back(&lprox_current);
// get the light
string light_path = get_correct_file("light", log_paths);
ifstream light_file(light_path);
string light_line;
getline(light_file, light_line);
int light_time;
temp.clear();
temp.str(get_line_part(light_line, 0));
temp >> light_time;
float light_current = stof(get_line_part(light_line, 2));
vector<float*> light_vals;
light_vals.push_back(&light_current);
*/
// int time_current = min(label_time, min(sprox_time,
// min(lprox_time, min(accel_time,
// light_time))));
/*
// variables for processing here
int total_time = 0;
map<string, int> label_counts;
while(label_time != -1 || accel_time != -1 || sprox_time != -1
|| lprox_time != -1 || light_time != -1) {
time_current++;
if(label_time != -1 && time_current > label_time) {
update_line(&label_time, &label_line, &label_file);
if(label_line.size() > 0) // if last label, don't overwrite
label_current = get_line_part(label_line, 1);
}
if(accel_time != -1 && time_current > accel_time) {
update_line(&accel_time, &accel_line, &accel_file);
if(accel_line.size() > 0) // if last line, don't overwrite
update_vals(accel_vals, accel_line);
}
if(sprox_time != -1 && time_current > sprox_time) {
update_line(&sprox_time, &sprox_line, &sprox_file);
if(sprox_line.size() > 0) // if last line, don't overwrite
update_vals(sprox_vals, sprox_line);
}
if(lprox_time != -1 && time_current > lprox_time) {
update_line(&lprox_time, &lprox_line, &lprox_file);
if(lprox_line.size() > 0) // if last line, don't overwrite
update_vals(lprox_vals, lprox_line);
}
if(light_time != -1 && time_current > light_time) {
update_line(&light_time, &light_line, &light_file);
if(light_line.size() > 0) // if last line, don't overwrite
update_vals(light_vals, light_line);
}
// Processing happens here
total_time++;
if(label_counts.count(label_current) == 0)
// not in map
label_counts[label_current] = 0;
label_counts[label_current]++;
}
// post processing happens here
cout << "Labels Counts:" << endl;
for(map<string, int>::iterator it = label_counts.begin();
it != label_counts.end(); it++) {
cout << it->first << " -> " << it->second << " -> ";
cout << 1.0 * it->second / total_time << endl;
}
*/
}
Your program exhibits undefined behavior since you are using a pointer to an object that has been deleted.
ifstream lf(log_loc);
log_file = &lf;
if gets deleted when the constructor returns and you are still holding on to a pointer to the object.
Change log_file to an object instead of a pointer.