I am wondering how to make a lambda in C++ for this function and the type has to be void
void setIO(string s){
freopen((s+".in").c_str(),"r",stdin);
freopen((s+".out").c_str(),"w",stdout);
}
You can specify the type like so:
#include <iostream>
#include <fstream>
using namespace std;
int main() {
const string FILE_NAME = "test.txt";
auto f = [](string const &name) -> void {
ofstream file;
file.open(name);
file << "junk\n" << "junk2" << endl;;
file.close();
};
f(FILE_NAME);
ifstream inputFile(FILE_NAME);
if (inputFile.is_open()) {
cout << "File is open." << endl;
string line;
while (getline(inputFile, line))
cout << line << '\n';
cout << flush;
inputFile.close();
} else
cerr << "Error opening file." << endl;
return EXIT_SUCCESS;
}
However, lambda functions can deduce the return type, so you can leave out -> void.
auto f = [](string const &name) {
ofstream file;
file.open(name);
file << "junk\n" << "junk2" << endl;;
file.close();
};
The equivalent way to create a lambda would be:
auto f = [](string s) -> void {
//freopen((s+".in").c_str(),"r",stdin);
//freopen((s+".out").c_str(),"w",stdout);
std::cout<<"inside lambda"<<std::endl;
//some other code here
};
Now you can use/call this as:
f("passing some string");
Related
I am struggling with a programming assignment in my C++ class. The assignment involves creating a random access file to store inventory for a hardware store. I can create, read and write to the file just fine. I have a function which opens the file or creates a new one if it does not exist. This function then returns the open file as std::fstream. I am trying to pass that open file to another function which prints out the contents of the file to the console. When I call the print function the first time it works just fine. However, when I return to the main menu and try and call the print function again, it prints out nothing from the file.
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdlib>
#include "HardwareData.h"
void printMenu();
unsigned short int getMenuChoice();
std::string getFileName();
std::fstream openFile(const std::string& fileName);
std::fstream newFile(const std::string& filename);
void printHeader();
void printAllRecords(std::fstream& file);
void newRecord(std::fstream& file);
unsigned int getRecordNum(const std::string& prompt);
bool recordIsBlank(std::fstream& file, unsigned int recordNum);
int main() {
unsigned short int menuChoice{0};
std::string filename;
std::fstream file;
while(menuChoice != 6){
printMenu();
menuChoice = getMenuChoice();
switch(menuChoice){
case 1:
filename = getFileName();
file = openFile(filename);
break;
case 2:
printAllRecords(file);
break;
case 3:
newRecord(file);
break;
case 4:
break;
case 5:
break;
default:
break;
}
}
return(0);
}
std::string getFileName(){
std::string filename;
std::cout << "Enter a filename:";
std::cin >> filename;
return filename;
}
std::fstream openFile(const std::string& filename){
std::fstream file{filename, std::ios::in | std::ios::out | std::ios::binary};
if(!file){
std::cout << "File could not be opened." << std::endl;
std::cout << "Creating new file." << std::endl;
file = newFile(filename);
std::cout << "Successfully created " << filename << std::endl;
}
else{
std::cout << filename << " opened successfully" << std::endl;
}
return file;
}
std::fstream newFile(const std::string& filename){
std::ofstream file{filename, std::ios::out | std::ios::binary};
if(!file){
std::cerr << "File could not be created." << std::endl;
exit(EXIT_FAILURE);
}
HardwareData emptyRecord;
for(int i=0; i<100; i++){
file.write(reinterpret_cast<const char*>(&emptyRecord), sizeof(HardwareData));
}
file.close();
return openFile(filename);
}
void printHeader(){
std::cout << "Record# Tool Name Quantity Cost \n";
std::cout << "==================================================\n";
}
void printAllRecords(std::fstream& file){
file.seekg(0);
HardwareData record;
file.read(reinterpret_cast<char*>(&record), sizeof(HardwareData));
printHeader();
while(!file.eof()){
if(record.getRecordNum() != 0){
record.printRecord();
}
file.read(reinterpret_cast<char*>(&record), sizeof(HardwareData));
}
}
I was expecting to pass the file by reference and still be able to use that reference again on another function call. I am not getting any errors
The code is supposed to be able to count the characters in total then count each time they appear within a text file. I tried building a struct that makes an array which is an integer and char array at the same time so that I can have the counting in the same place as my array. But now I am stuck. I've looked online a lot but cannot find what I need to help me. Anyone got some advice? Also in the code if you see anything that should be changed I appreciate the tips! I am newer at c++ so go easy on me please.
Structs, multiple arrays, searching internet for answers
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
struct letters {
int count;
char letter;
};
constexpr int SIZE = 10000;
std::string fileName, word;
int count = 0, charCount = 0;
int Alphabet[26];
letters chars[];
void getFileName(std::string& fileName);
int countWords(int& count, std::string& fileName, std::string word);
int countChar(int& charCount, std::string& fileName, letters chars[]);
void sortChars(letters chars[SIZE], int SIZE);
int main()
{
getFileName(fileName);
countWords(count, fileName, word);
countChar(charCount, fileName, chars);
sortChars(chars, SIZE);
return 0;
}
void getFileName(std::string& fileName)
{
std::cout << "Please enter the name of the file followed by the type (ex: text.txt) : " << std::endl;
std::getline(std::cin, fileName);
}
int countWords(int& count, std::string& fileName, std::string word)
{
count = 0;
std::ifstream infile(fileName);
while (infile >> word) {
count++;
}
std::cout << count << std::endl;
return count;
}
int countChar(int& charCount, std::string& fileName, letters chars[])
{
std::ifstream infile(fileName);
while (infile >> chars->letter) {
count++;
}
std::cout << charCount;
return charCount;
}
void sortChars(letters chars[SIZE], int SIZE)
{
int i = 0;
std::ifstream infile(fileName);
while (infile >> chars[i].letter) {
for (int i = 0; i <= chars->count; i++) {
if (infile == chars[i].letter) {
chars[i].count++;
}
}
}
}
void printCount()
{
std::cout << count << std::endl;
std::cout << charCount << std::endl;
std::ifstream infile(fileName);
}
The struct should count the number of times 'A' or 'a', should be able to convert to one case, but I can do this after it counts one or the other. My tester file is in all lowercase so that would be a good place to start.
Even bigger hint, use a std::unordered_map to count the characters:
#include <cstdlib> // EXIT_FAILURE
#include <cctype> // std::isupper(), std::tolower()
#include <string> // std::string<>, std::getline()
#include <unordered_map> // std::unordered_map<>
#include <iostream> // std::ifstream
#include <fstream> // std::cout, std::cerr
int main()
{
std::string file_name;
if (!std::getline(std::cin, file_name)) {
std::cerr << "Input error. :(\n\n";
return EXIT_FAILURE;
}
std::ifstream is{ file_name };
if (!is.is_open()) {
std::cerr << "Couldn't open \"" << file_name << "\" for reading. :(\n\n";
return EXIT_FAILURE;
}
std::size_t num_words = 0;
std::unordered_map<char, std::size_t> char_counts;
for (std::string word; is >> word; ++num_words) {
for (auto ch : word) {
if (std::isupper(ch))
ch = std::tolower(ch);
++char_counts[ch];
}
}
for (auto const &count : char_counts)
std::cout << "'" << count.first << "': " << count.second << '\n';
std::cout << "Number of words: " << num_words << "\n\n";
} // when control reaches the end of main() without encountering a return-statement
// it has the same effect as return 0;
If you insist on splitting that few lines of code up into functions:
#include <cstdlib> // EXIT_FAILURE
#include <cctype> // std::isupper(), std::tolower()
#include <string> // std::string<>, std::getline()
#include <unordered_map> // std::unordered_map<>
#include <iostream> // std::ifstream
#include <fstream> // std::cout, std::cerr
std::string get_file_name()
{
std::cout << "Filename: ";
std::string file_name;
if (!std::getline(std::cin, file_name))
std::cerr << "Input error. :(\n\n";
return file_name;
}
std::ifstream open_file(std::string file_name)
{
std::ifstream file{ file_name };
if (!file.is_open())
std::cerr << "Couldn't open \"" << file_name << "\" for reading. :(\n\n";
return file;
}
std::size_t get_file_stats(std::istream &is, std::unordered_map<char, std::size_t> &char_counts)
{
std::size_t num_words = 0;
for (std::string word; is >> word; ++num_words) {
for (auto ch : word) {
if (std::isupper(ch))
ch = std::tolower(ch);
++char_counts[ch];
}
}
return num_words;
}
int main()
{
std::string file_name{ get_file_name() };
if (!file_name.length())
return EXIT_FAILURE;
std::ifstream is{ open_file(file_name) };
if (!is.is_open())
return EXIT_FAILURE;
std::unordered_map<char, std::size_t> counts;
std::cout << "Number of words: " << get_file_stats(is, counts) << "\n\n";
for (auto const &count : counts)
std::cout << "'" << count.first << "': " << count.second << '\n';
}
I am trying to read from a .csv file. There are two functions below, one for writing and one for reading.
The file contains a simple table:
date,first,second
1 a one
2 b two
3 c three
4 c four
For some reason, the statement while(file_stream.read(&c,1)); does not read anything. It stops at the first character and I'm dumbfounded as to why. Any clues?
#include <iostream>
#include <sstream>
#include <fstream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <string>
#include <cstdlib>
using namespace std;
std::string filename;
std::string line_string;
ifstream file_stream;
stringstream ss;
vector< vector<string> > vec;
char c;
void read_file()
{
filename = "test.csv";
cout << filename << endl;
file_stream.open(filename.c_str(),ios::out|ios::binary);
if(file_stream.fail())
{
cout << "File didn't open" << endl;
return;
}
if(file_stream.is_open())
cout << "file opened" << endl;
while(file_stream.read(&c,1)); // this isn't working
{
cout <<"char c is: " << c;
ss << noskipws << c;
}
file_stream.close();
cout << "string is: " << ss.str() << endl;
//get each line
int counter = 0;
vector<string> invec;
while(getline(ss,line_string,'\n'))
{
string header_string;
stringstream header_stream;
header_stream << line_string;
while(getline(header_stream, header_string,','))
{
invec.push_back(header_string);
}
invec.push_back(header_string);
vec.push_back(invec);
invec.clear();
counter++;
}
}
void test_output()
{
for(int i = 0; i < vec.size();i++)
{
for(int in = 0; in < vec[0].size(); in++)
cout << vec[i][in] << " ";
cout << endl;
}
}
int main()
{
read_file();
test_output();
}
Look very very carefully at the line that is not working:
while(file_stream.read(&c,1)); // this isn't working
{
cout <<"char c is: " << c;
ss << noskipws << c;
}
The ; character at the end of the while statement does NOT belong! You are running a no-body loop that does not terminate until read() fails, and THEN your code enters the bracketed block to output the last character that was successfully read (if any).
You need to remove that erroneous ; character:
while(file_stream.read(&c,1)) // this works
{
cout <<"char c is: " << c;
ss << noskipws << c;
}
Now, the real question is - why are you reading the input file character-by-character into a std::stringstream in the first place? You can use std::getline() with the input std::ifstream directly:
#include <iostream>
#include <sstream>
#include <fstream>
#include <vector>
#include <string>
std::vector< std::vector<std::string> > vec;
void read_file()
{
std::string filename = "test.csv";
std::cout << filename << std::endl;
std::ifstream file_stream;
file_stream.open(filename.c_str(), ios::binary);
if (!file_stream)
{
std::cout << "File didn't open" << std::endl;
return;
}
std::cout << "file opened" << std::endl;
//get each line
std::vector<std::string> invec;
std::string line;
int counter = 0;
if (std::getline(file_stream, line))
{
std::istringstream iss(line);
while (std::getline(iss, line, ','))
invec.push_back(line);
vec.push_back(invec);
invec.clear();
++counter;
while (std::getline(file_stream, line))
{
iss.str(line);
while (iss >> line)
invec.push_back(line);
vec.push_back(invec);
invec.clear();
++counter;
}
}
}
void test_output()
{
if (!vec.empty())
{
for(int in = 0; in < vec[0].size(); ++in)
std::cout << vec[0][in] << ",";
std::cout << std::endl;
for(int i = 1; i < vec.size(); ++i)
{
for(int in = 0; in < vec[i].size(); ++in)
std::cout << vec[i][in] << " ";
std::cout << std::endl;
}
}
}
int main()
{
read_file();
test_output();
}
I'm having trouble loading from a text file to a value. I want it to load from the text file, but the number remains unchanged.
Data.txt
7
7
Line 1 of the file is Health, what I'm trying to load.
Player.h
#ifndef PLAYER_H
#define PLAYER_H
class Player
{
public:
int Health;
int MaxHealth;
Player() { this->Health = 9; this->MaxHealth = 9; }
};
#endif // PLAYER_H
and main.cpp
#include <iostream>
#include "Player.h"
#include <fstream>
using namespace std;
void save_to_file(string filename, Player P)
{
ofstream f( filename.c_str() );
f << P.Health << endl;
f << P.MaxHealth << endl;
}
bool load_from_file(string filename, Player P)
{
ifstream f( filename.c_str() );
f >> P.Health;
f >> P.MaxHealth;
return f.good();
}
int main()
{
Player P;
load_from_file("Data.txt", P);
cout << P.Health << endl;
return 0;
}
Thanks! I just learned C++ so I'm a little confused. I'm running Codeblocks and 'Data.txt' is in the 'bin' folder.
EDIT :
Changed main.
bool load_from_file(string filename, Player& P)
{
ifstream f( filename.c_str() );
f >> P.Health;
f >> P.MaxHealth;
if(f.good()){
cout << "Sucess!" << endl;
} else {
cout << "Failure" << endl;
}
return f.good();
}
Not sure what you're doing wrong if you followed πάντα ῥεῖ's advice, but this works:
#include <iostream>
#include <fstream>
using namespace std;
class Player {
public:
int Health, MaxHealth;
};
void save_to_file(string filename, const Player& P)
{
ofstream f( filename.c_str() );
f << P.Health << endl;
f << P.MaxHealth << endl;
}
bool load_from_file(string filename, Player& P) {
ifstream f( filename.c_str() );
f >> P.Health;
f >> P.MaxHealth;
if(f.good()){
cout << "Success!" << endl;
}
else {
cout << "Failure" << endl;
}
return f.good();
}
int main() {
Player P;
load_from_file("Data.txt", P);
cout << P.Health << endl;
return 0;
}
Change your function signature to take the parameter by reference:
bool load_from_file(string filename, Player& P) {
// ^
As is, your function only modifies a copy of the Player parameter, and the result isn't seen in main().
I've been looking at this for hours and I just know the answer is simple. It seems no matter what I do I cannot open a file. It's a multi-class program so in the header I have
#include <iostream>
#include < fstream>
class A{
string path;
A(string p): path(p){}
...
...
void PrintToFile();
void PrintBase();
void PrintNext();
...
...
};
and in the cpp file I have
#include "A.h"
void A::PrintToFile(){
ofstream f(path.c_str(), ios::out);
assert(f.is_open);
f << "markuptext" << endl;
PrintBase();
f << "endtag" << endl;
f.close();
}
void A::PrintBase(){
ofstream f(path.c_str(), ios::app);
assert(f.is_open);
f << "markuptext" << endl;
f << somevale << endl;
PrintNext();
f << "endtag" << endl;
f.close()
}
void A::PrintNext(){
ofstream f (path.c_str(), ios::app);
assert(f.is_open);
f << "markuptext" << endl;
f << somevalue << endl;
f << "endtag" << endl;
f.close()
}
I've played around with the flags on the constructors and with the open commands as well. And once it managed to open a file, but it never wrote anything to the file. If you have any insights I'd much appreciate it.
edit
Thanks for all the help guys, looks like I was trying to open a file with "". But even now after I've got that straightened out, my code is not writing to that open file. I checked my permissions and I'm doing chmod a+rwx... well here's the code in more detail.
#ifndef XML_WRITER_H
#define XML_WRITER_H
#include "WordIndex.h"
#include "PageIndex.h"
#include "StringUtil.h"
#include "CS240Exception.h"
#include <iostream>
#include <fstream>
/* prints out the wordIndex to an xml file
*/
class XMLWriter{
private:
WordIndex * wIndex;
PageIndex * pIndex;
URL baseurl;
//const char * file;
ofstream f;
public:
XMLWriter();
XMLWriter(string base);
XMLWriter(XMLWriter & other){
assert(&other != NULL);
Init(other);
}
XMLWriter & operator =(XMLWriter & other){
Free();
Init(other);
}
~XMLWriter(){
Free();
}
void Load(WordIndex & wi, PageIndex & pi);
//prints to the file
void Print(char * ofile);
private:
void Init(XMLWriter & other){
baseurl = other.baseurl;
wIndex = other.wIndex;
pIndex = other.pIndex;
}
void Free(){
}
void PrintWebsite();
void PrintStartURL();
void PrintPages();
void PrintIndex();
void PrintWord(OccurenceSet ocs);
void PrintValue(string s);
void PrintOccurence(Occurence o);
void PrintPage(Page & page );
void PrintDescription(string dscrptn );
void PrintValue(int n );
void PrintURL(URL url );
};
#endif
.cpp file
#include "XMLWriter.h"
XMLWriter::XMLWriter(){
}
XMLWriter::XMLWriter( string base): baseurl(base){
//cout << "filename : " << filename << endl;
//file = filename.c_str();
//cout << "file : " << *file << endl;
}
void XMLWriter::Load(WordIndex & wi, PageIndex & pi){
wIndex = &wi;
pIndex = π
wIndex->ResetIterator();
pIndex->ResetIterator();
}
void XMLWriter::Print(char * filename){
cout << filename << endl;
ofstream f(filename);
if(!f){
cout << "file : " << filename;
throw CS240Exception("could not open the file for writing");
}
PrintWebsite();
f.close();
}
//private methods
//
void XMLWriter::PrintWebsite(){
f <<"<website>\n";
PrintStartURL();
PrintPages();
PrintIndex();
f << "</website>" << endl;
}
// startURL
//
void XMLWriter::PrintStartURL( ){
f << "\t" << "<start-url>"<< endl;
string val = baseurl.Value();
StringUtil::EncodeToXml(val);
f << "\t\t" << val << endl;
f << "\t" << "</start-url>"<< endl;
}
//pages
//
void XMLWriter::PrintPages(){
f << "\t" << "<pages>"<< "\n";
while(pIndex->HasNext())
PrintPage(*(pIndex->Next()));
f << "\t" <<"</pages>"<< '\n';
}
void XMLWriter::PrintPage(Page & page ){
f << "\t\t" <<"<page>"<< endl;
PrintURL(page.Value());
PrintDescription(page.Description() );
f << "\t\t" <<"</page>"<< endl;
}
void XMLWriter::PrintURL(URL url){
f << "\t\t\t<url>"<< endl;
f << "\t\t\t\t" << StringUtil::EncodeToXmlCopy(url.Value()) << endl;
f << "\t\t\t</url>"<< endl;
}
void XMLWriter::PrintDescription(string dscrptn){
f << "\t\t\t<description>";
f << StringUtil::EncodeToXmlCopy(dscrptn);
f << "</description>"<< endl;
}
//index
//
void XMLWriter::PrintIndex(){
f << "\t<index>"<< endl;
while(wIndex->HasNext())
PrintWord(*(wIndex->Next()) );
f << "\t</index>"<< endl;
}
void XMLWriter::PrintWord(OccurenceSet ocs ){
f << "\t\t<word>" << endl;
PrintValue(ocs.Value());
ocs.ResetIterator();
while(ocs.HasNext())
PrintOccurence(*(ocs.Next()) );
f << "\t\t</word>"<< endl;
}
void XMLWriter::PrintValue(string s ){
f << "\t\t\t<value>";
f << StringUtil::EncodeToXmlCopy(s);
f << "</value>"<< endl;
}
void XMLWriter::PrintOccurence(Occurence o ){
f << "\t\t\t<occurence>" << endl;
PrintURL(o.Value()->Value());
PrintValue(o.NumOfOccur());
f << "<\t\t\t/occurence>"<< endl;
}
void XMLWriter::PrintValue(int n ){
f << "\t\t\t\t<count>";
f << n;
f << "</count>"<< endl;
}
it won't write anything to the file :( but now it is creating a file so thats a step :-D.
obviously I have a data structures and other things backing this up, but I just need to get it writing. Thanks in advance
The most obvious problem is that you are opening the file several times.
Each instance of the open file will have its own file position and its
own buffer. In addition, depending on the system, either all open's but
the first will fail (Windows, I think), or the open will truncate the
file, effectively erasing any information that might have been written
to it. What you should do is have PrintToFile pass the open stream to
the functions it calls (recursively); each of these functions should
take a std::ostream& (not std::ofstream&) to receive it.
One thing I see is that you are opening the file several times. Maybe that would cause trouble. You open it first in PrintToFile then while it is still open there you open it for append in PrintBase. Then while in PrintBase you open it yet again in the call to PrintNext.
Put the ofstream as a member of the class, open it once and refer to it from all three functions.
I would use a simple if :
ofstream f (path.c_str(), ios::app);
if(!f)
{
throw std::exception(std::string("Could not open file : " + path + "for writing"));
}
//write to file here
f.close();
This way you can be sure if the file was opened succesfully or not.