**the first constructor is supposed to take words from a txt file and the second one takes words from the string and add it to fileVec vector.
i'm trying to call a parameterized constructor but it doesn't work, instead it calls the default constructor
**
#include <iostream>
#include <vector>
#include <fstream>
#include <sstream>
using namespace std;
class stringSet
{
private:
int i = 0;
string fileName, line, word, word2;
istringstream iss;
fstream file;
vector<string> fileVec;
public:
string str = "that's a string for parameterized constructor";
stringSet()
{
cout << "Please enter filename: ";
getline(std::cin, fileName);
fileName += ".txt";
file.open(fileName, ios::in);
if (file.is_open())
{
while (getline(file, line))
{
iss.clear();
iss.str(line);
while (iss.good())
{
iss >> word;
fileVec.push_back(word);
cout << fileVec[i] << endl;
i++;
}
}
}
}
stringSet(string str)
{
istringstream iss2(str);
while (iss2 >> word2)
fileVec.push_back(word2);
cout << fileVec[i] << endl;
i++;
}
};
int main()
{
// stringSet();
stringSet(str);
return 0;
}
that code calls stringSet() instead of stringSet(str)
Issue similar to most vexing parse.
stringSet(str); // Variable declaration!
declares a variable str.
It is similar to
stringSet str;
You might use {..} syntax:
stringSet{str}; // Temporary created (assuming some std::string str available).
Related
Can someone tell me what is wrong in this code? Particularly the function longestLine.
When I run the code without that funcion (only using the inside of it) the program runs with no problems, but when I do it with the function it does not compile.
I dont understand the error the compiler gives but I think it has something to do with the argument of the funcion.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
string longestLine(ifstream infile);
string promptUserForFile(ifstream & infile, string prompt="");
int main() {
ifstream infile;
promptUserForFile(infile);
cout << "The longest line of the file is: " << endl;
cout << longestLine(infile);
return 0;
}
string promptUserForFile(ifstream & infile, string prompt) {
while (true) {
cout << prompt;
string filename;
getline(cin, filename);
infile.open(filename.c_str());
if (!infile.fail())
return filename;
infile.clear();
cout << "Unable to open that file. Try again." << endl;
if (prompt == "")
prompt = "Input file: ";
}
}
string longestLine(ifstream infile) {
int length = 0;
string longest_line;
string line;
while (getline(infile, line)) {
if (line.length() > length) {
length = line.length();
longest_line=line;
}
}
return longest_line;
}
I think you should pass ifstream by reference
string longestLine(ifstream& infile);
ifstream derive from ios_base, the copy constructor of stream is deleted: because streams are not copyable.
If you pass ifstream by value, the compiler will try to call the copy constructor of ifstream when you call longestLine, the compiler will definitely complain this error.
cppreference: basic_ifstream
Just quick one, how should I go about printing a value from a struct? the 'winningnums' contains a string from another function (edited down for minimal example)
I've tried the below but the program doesnt output anything at all, is my syntax incorrect?
struct past_results {
std::string date;
std::string winningnums;
};
int main(){
past_results results;
std::cout << results.winningnums;
return 0;
}
EDIT:
just to give some more insight, here's the function that populates my struct members. Is it something here im doing wrong?
//function to read csv
void csv_reader(){
std::string line;
past_results results;
past_results res[104];
int linenum = 0;
//open csv file for reading
std::ifstream file("Hi S.O!/path/to/csv", std::ios::in);
if(file.is_open())
{
while (getline(file, line))
{
std::istringstream linestream(line);
std::string item, item1;
//gets up to first comma
getline(linestream, item, ',');
results.date = item;
//convert to a string stream and put into winningnums
getline(linestream, item1);
results.winningnums = item1;
//add data to struct
res[linenum] = results;
linenum++;
}
}
//display data from struct
for(int i = 0; i < linenum; i++) {
std::cout << "Date: " << res[i].date << " \\\\ Winning numbers: " << res[i].winningnums << std::endl;
}
}
is my syntax incorrect?
No, it's just fine and if you add the inclusion of the necessary header files
#include <iostream>
#include <string>
then your whole program is ok and will print the value of the default constructed std::string winningnums in the results instance of past_results. A default constructed std::string is empty, so your program will not produce any output.
Your edited question shows another problem. You never call csv_reader() and even if you did, the result would not be visible in main() since all the variables in csv_reader() are local. Given a file with the content:
today,123
tomorrow,456
and if you call csv_reader() from main(), it would produce the output:
Date: today \\ Winning numbers: 123
Date: tomorrow \\ Winning numbers: 456
but as I mentioned, this would not be available in main().
Here's an example of how you could read from the file and make the result available in main(). I've used a std::vector to store all the past_results in. It's very practical since it grows dynamically, so you don't have to declare a fixed size array.
#include <fstream>
#include <iostream>
#include <sstream> // istringstream
#include <string> // string
#include <utility> // move
#include <vector> // vector
struct past_results {
std::string date;
std::string winningnums;
};
// added operator to read one `past_results` from any istream
std::istream& operator>>(std::istream& is, past_results& pr) {
std::string line;
if(std::getline(is, line)) {
std::istringstream linestream(line);
if(!(std::getline(linestream, pr.date, ',') &&
std::getline(linestream, pr.winningnums)))
{ // if reading both fields failed, set the failbit on the stream
is.setstate(std::ios::failbit);
}
}
return is;
}
std::vector<past_results> csv_reader() { // not `void` but returns the result
std::vector<past_results> result; // to store all past_results read in
// open csv file for reading
std::ifstream file("csv"); // std::ios::in is default for an ifstream
if(file) {
// loop and read records from the file until that fails:
past_results tmp;
while(file >> tmp) { // this uses the `operator>>` we added above
// and save them in the `result` vector:
result.push_back(std::move(tmp));
}
}
return result; // return the vector with all the records in
}
int main() {
// get the result from the function:
std::vector<past_results> results = csv_reader();
// display data from all the structs
for(past_results& pr : results) {
std::cout << "Date: " << pr.date
<< " \\\\ Winning numbers: " << pr.winningnums << '\n';
}
}
Your example doesn't initialize the struct members. There is no data to print, so why would you expect it to output anything?
I would like to get some advice on an issue I've encountered once working on small adjustments to an existing program.
The program itself has to:
Open a file and read it line-by-line preferably
Pack the lines into istringstream and then split to 2 strings on a ':' separator
Insert those 2 strings line1 and line2 into an existing std::map container
Than I can do more stuff with the map and the data from it.
My code looks like that:
int main()
{
FILE *fpFile;
map<string, string>mapOfPci;
std::string tempBuff="";
std::string line1="", line2="";
fpFile = fopen(PCI_MAPPING_PATH, "r");
if(!fpFile)
return false;
while(getline(fpFile, tempBuff)){
istringstream iSs(tempBuff);
iSs >> line1;
iSs.ignore(numeric_limits<std::streamsize>::max(), ':');
iSs >> line2;
mapOfPci.insert(make_pair(line1, line2));
}
for(const auto &m : mapOfPci){
cout << m.first << " : " << m.second << "\n";
}
fclose(fpFile);
return (0);
}
Now what I'm getting in my compiler feedback is:
mismatched types 'std::basic_istream<_CharT, _Traits>' and 'FILE* {aka _iobuf*}'
while(getline(fpFile, tempBuff))
At this point I presume that this is due to the usage of FILE* file handling method.
I might not be able to use the C++ std::ifstream, std::fstream, so is there any method to move this further with the current FILE* usage?
std::getline() expects an std::istream-derived class, like std::ifstream, so you simply can't pass your own FILE* to it (unless you wrap it inside of a custom std::streambuf-derived object assigned to a standard std::istream object. std::ifstream uses std::filebuf, which uses FILE* internally, but you can't supply it with your own FILE*).
Otherwise, you can use C's getline() function instead, but it doesn't work with std::string, as it allocates its own output char[] buffer which you will then have to free afterwards (you can assign the contents of that buffer to a std::string, though), eg:
#include <iostream>
#include <sstream>
#include <string>
#include <utility>
#include <limits>
#include <cstdio>
using namespace std;
int main()
{
FILE *fpFile = fopen(PCI_MAPPING_PATH, "r");
if (!fpFile)
return false;
map<string, string> mapOfPci;
char *tempBuff = nullptr;
size_t size = 0;
int nRead;
while ((nRead = getline(&tempBuff, &size, fpFile)) != -1){
istringstream iSs(string(tempBuff, nRead));
string line1, line2;
iSs >> line1;
iSs.ignore(numeric_limits<streamsize>::max(), ':');
iSs >> line2;
mapOfPci.insert(make_pair(line1, line2));
free(tempBuff); tempBuff = nullptr;
size = 0;
}
free(tempBuff);
for(const auto &m : mapOfPci){
cout << m.first << " : " << m.second << "\n";
}
fclose(fpFile);
return 0;
}
But, since you are using other C++ standard classes, there really is no good reason not to use std::ifstream instead, eg:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <utility>
#include <limits>
using namespace std;
int main()
{
ifstream fpFile(PCI_MAPPING_PATH);
if (!fpFile.is_open())
return false;
map<string, string> mapOfPci;
string tempBuff;
while (getline(fpFile, tempBuff)){
istringstream iSs(tempBuff);
string line1, line2;
iSs >> line1;
iSs.ignore(numeric_limits<streamsize>::max(), ':');
iSs >> line2;
mapOfPci.insert(make_pair(line1, line2));
}
for(const auto &m : mapOfPci){
cout << m.first << " : " << m.second << "\n";
}
return 0;
}
I have made a Quizlet code to save a word with its translation(in Russian) in csv file.
So, the 'add' and 'read' functions work perfectly but I have been trying to make the 'delete' function remove a line when I give a substring of that line.
update: I am trying to copy all the lines except the one that i wanna delete to a new file and then rename it.
but when the new file is created, it is empty!
ex: in the file, line 1: apple яблоко.
input: apple, and then the entire is being deleted.
here is my code: I just have a problem in void quizlet::DeleteWord()
#include <string>
#include <iostream>
#include <vector>
#include<fstream>
#include <sstream>
#include<cstdlib>
using namespace std;
class quizlet {
private:
std::string filename;
std::vector<std::string> lines;
public:
quizlet(std::string filename) : filename(filename) {}
void AddWord(std::string, std::string);
vector<string> ReadAllWords();
void DeleteWord();
};
void quizlet::AddWord(std::string word, std::string translation) {
cout << "Write a word and its translation separated by a space:" << std::endl;
cin >> word >> translation;
// file pointer
fstream fout;
// opens an existing csv file or creates a new file.
fout.open("words.txt",ios::out | ios::app);
// Insert the data to file
fout <<word<<" "<<translation<<endl;
std::cout << "Saved new card: " << word << "/" << translation << std::endl;
}
vector<string> quizlet::ReadAllWords() {
// File pointer
fstream fin;
// Open an existing file
fin.open("words.txt", ios::in);
// Read the Data from the file
// as String Vector
vector <string> rows;
string line, word, temp;
while (getline(fin, line)) {
cout << line << std::endl;
rows.push_back(line);
stringstream s(line);
}
return rows;
}
void quizlet::DeleteWord() {
string line;
fstream fin;
fstream fout;
fin.open("words.txt", ios::in);
fout.open("new.txt",ios::out | ios::app);
string token;
cin>>token;
vector <string> lines;
while (getline(fin, line)) {
if (line.find(token) != string::npos) {
cout << line << endl;
fin << line << endl;
cout<<"the line has been deleted!";
//remove (line);
}
}
fin.close();
fout.close();
remove("words.txt");
rename("new.txt", "words.txt");
cout << "\nChanges has Successfully been made...... Data Saved\n" << endl;
}
int main() {
auto Quizlet = quizlet("words.txt");
string word, translation;
while (true) {
std::string command;
std::cin >> command;
if (command == "add") {
Quizlet.AddWord(word, translation);
} else if (command == "read") {
Quizlet.ReadAllWords();
}
else if (command == "delete") {
Quizlet.DeleteWord();
}
else {
return 0;
}
}
}
Post-update edit:
My original answer now makes much more sense given what you are trying to do. You should read the whole file in at once, make any additions and deletions in-memory you want, then overwrite the original file with the whole, new, list.
Original answer:
Consider reading the file into memory via a std::map<std::string,std::wstring> instead of a std::vector<std::string> of lines in the file.
Using this approach, adding and deleting a word and its translation is simple.
Adding:
//if-guard only needed if you want to protect against overwriting already-existing words.
auto found_iter = cards.find(word);
if(found_iter == cards.end()) {
cards.insert_or_assign(word, translation);
}
Deleting:
auto found_iter = cards.find(word);
if(found_iter != cards.end()) {
cards.erase(found_iter);
}
Writing it back to the file is as simple as looping over the collection:
for(const auto& [word,translation] : cards) {
fout << word << ' ' << translation << '\n';
}
fout.close();
well, after trying for a long time.
I got this code and it works perfectly with no errors.
thank you all!
#include <string>
#include <iostream>
#include <vector>
#include <fstream>
#include <sstream>
#include <cstdlib>
using namespace std;
class quizlet {
private:
std::string filename;
std::vector<std::string> lines;
public:
quizlet(std::string filename) : filename(filename) {}
void AddWord(std::string, std::string);
vector<string> ReadAllWords();
void DeleteWord(std::string);
};
void quizlet::AddWord(std::string word, std::string translation) {
cout << "Write a word and its translation separated by a space:" << std::endl;
cin >> word >> translation;
// file pointer
fstream fout;
// opens an existing csv file or creates a new file.
fout.open("words.txt",ios::out | ios::app);
// Insert the data to file
fout << word << " " << translation << endl;
std::cout << "Saved new card: " << word << "/" << translation << std::endl;
}
vector<string> quizlet::ReadAllWords() {
// File pointer
fstream fin;
// Open an existing file
fin.open("words.txt", ios::in);
// Read the Data from the file
// as String Vector
vector <string> rows;
string line, word, temp;
while (getline(fin, line)) {
cout << line << std::endl;
rows.push_back(line);
stringstream s(line);
}
return rows;
}
void quizlet::DeleteWord(string token) {
string line;
fstream fin;
fstream fout;
fin.open("words.txt", ios::in);
fout.open("new.txt",ios::out | ios::app);
cin >> token;
vector<string> lines;
while(getline(fin, line)) {
if(line.find(token) == string::npos) {
fout << line << endl;
}
}
fout.close();
fin.close();
remove("words.txt");
rename("new.txt", "words.txt");
cout << "\nChanges has Successfully been made...... Data Saved\n" << endl;
}
int main() {
auto Quizlet = quizlet("words.txt");
string word, translation, token;
while(true) {
std::string command;
std::cin >> command;
if(command == "add") {
Quizlet.AddWord(word, translation);
} else if(command == "read") {
Quizlet.ReadAllWords();
} else if(command == "delete") {
Quizlet.DeleteWord(token);
} else {
return 0;
}
}
}
I am new to c++ and while i was working with streams i saw the following code:
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
using namespace std;
class Results
{
public:
string const& operator[](int index) const
{
return m_data[index];
}
int size() const
{
return m_data.size();
}
void readnext(istream& str)
{
string line;
getline(str, line);
cout << "line :" << line <<endl;
stringstream lineStream(line);
string cell;
m_data.clear();
while(getline(lineStream, cell, ','))
{
m_data.push_back(cell);
cout << cell<<endl;
}
}
private:
vector<string> m_data;
};
istream& operator>>(istream& str, Results & data)
{
data.readnext(str);
return str;
}
int main()
{
ifstream file("filename.txt");
Results r1;
while(file >> r1)
{
cout << "1st element: " << r1[3] << "\n";
}
}
When the call data.readnext(str) is made:
1)what is the value of str which is passed as an argument? When I print it out and i get 0x7ffd30f01b10 which is an address.
2)in the function getline(str, line); gives line the value of the first row of the file. I don't get why. Shouldn't that be getline(file, line);
I generally don't understand how this works so any help would be highly appreciated
The value is a reference to the std::istream superclass of the instantiated std::ifstream file object.
No. There is no file object visible in the scope of the readnext() function. The code is correct. str is the std::istream & parameter to readnext(), and matches the type of the first parameter to std::getline().