Simplest way to create a file for writing within a function? - c++

I have a function like so:
void my_func(unordered_map<std::string, std::string> arg){
//Create/open file object on first call and append to file on every call
//Stuff
}
and inside this function I wish to write to a file. How can I achieve this without having to create the file object in the caller and pass it in as a parameter? Each time the function is called I would like to append the latest write to the end of the file.

void my_func(unordered_map<std::string, std::string> arg){
static std::ofstream out("output.txt");
// out is opened for writing the first time.
// it is available for use the next time the function gets called.
// It gets closed when the program exits.
}

Pass two strings/char arrays. One is the file path, the other is the data to be written. Create the file using fstream myFile(fstream::out | fstream::app)
Need anymore explanation? I can write a full example if you would like.
Edit
Forgot to mention, this will do what you want, but you will be creating the file object everytime. You will not be creating a new file everytime though. That's what fstream::app is for. You open the file and start at the end.

Another alternative is to use a functor. This will give you the potential to control the lifetime of the file object and even pass around the function object
#include <string>
#include <fstream>
#include <unordered_map>
struct MyFunc {
MyFunc(std::string fname) {
m_fobj.open(fname);
};
~MyFunc() {
m_fobj.close();
};
void operator ()(std::unordered_map<std::string, std::string> arg) {
// Your function Code goes here
};
operator std::ofstream& () {
return m_fobj;
};
std::ofstream m_fobj;
};
int main() {
MyFunc my_func("HelloW.txt");
my_func(std::unordered_map<std::string, std::string>());
std::ofstream &fobj = my_func;
return 0;
};

Related

Creating a custom iterator struct to work with cstdio

I'm trying to create a iterator to go through my file. My file is binary and have int values inside, so in my point of view, it should work like that. But I'm getting errors says "invalid use of data-member 'IntFile::file' "So i marked in code where I'm getting errors. How can I manage it?
#include <iostream>
#include <cstdio>
using namespace std;
class IntFile
{
public:
int index;
FILE* file; // Error here
IntFile() {}
~IntFile() {}
int mnumbers[10];
int mnumbers2[10];
int value;
// And this whole class does not work
class iterator
{
bool operator ++ ()
{
file = fopen ("text.txt", "r+b");
fseek (file, 4*index, SEEK_CUR);
fclose(file);
}
bool operator -- ()
{
file = fopen ("text.txt", "r+b");
fseek (file, (-4)*index, SEEK_CUR);
fclose(file);
}
/*
iterator begin()
{
return ;
}
iterator end()
{
return ;
}
*/
};
};
I'm getting errors says "invalid use of data-member 'IntFile::file'"
IntFile::iterator doesn't have a data member file, nor does it implicitly have a reference to an instance of IntFile (as would be the case in, say, Java).
IntFile::iterator needs a reference to IntFile to be able to use that data member:
class iterator
{
explicit iterator(IntFile &file) : file(file) {}
// Your other code
private:
IntFile &file;
};
Then you will be able to access file.file, file.index, etc.
However, this will break down if you create multiple iterators and expect them to point to different places in the file because with this approach they all share a single file handle, and therefore a single position within that file. You can have each iterator keep track of its own position and seek there before each operation (not thread-safe) or you can duplicate the file handle for each iterator (consumes an additional file descriptor per iterator).
Or, it may be much easier to just memory-map the file and use a pointers into the mapped address space as your iterators.

Optional passing object to function by reference

I have many calls to a function that takes just one argument and I don't want update those calls. But I want to call that function from some other special place but in that case it should additionally fill a vector that I will pass with some data.
I know I can create a default argument with NULL pointer to a std::vector container and then, if it is null, skip doing any extra actions and if it is a valid pointer - gather data to vector. However I wanted to try using boost::optional.
Please see the code below. It compiles and works, but Is this approach fine or I shouldn't do that and better use raw pointer?
#include <boost/optional.hpp>
#include <boost/none_t.hpp>
#include <vector>
//header file declaration
int doAction(
int value,
char *msg = NULL,
boost::optional<std::vector<int>&> optionalNumberVec = boost::none);
//main.cpp
int doAction(int value, char* msg, boost::optional<std::vector<int>&> optionalNumberVec)
{
//do main actions here
//...
//...
//end of main action
//get additional information to table
if (optionalNumberVec)
{
optionalNumberVec.get().push_back(5);
optionalNumberVec.get().push_back(3);
}
return 1;
}
int main()
{
std::vector<int> numVec;
boost::optional<std::vector<int>&> optionalNumberVec(numVec);
doAction(2);
doAction(2, NULL, optionalNumberVec);
return 0;
}
Using boost or not is a simple decision based on your preferences (or your boss's preferences).
Once you get used to C++ you will notice that it doesn't really matter which one you use, as long you know how to use them.

Why only last thread executing?

I need to create console application that counts files in folders. Each folder executes parallel. I get directories paths from .txt file and put them to threads.
I'm using std::thread and boost::filesystem.
It works fine with one directory, but crashes or returns wrong results with many.
What is interesting that last thread always gets correct result, but those before it are wrong.
Here is my code:
DirHandler.h
#include <iostream>
#include <fstream>
#include <string>
#include <thread>
#include <windows.h>
#include <boost/filesystem.hpp>
using namespace std;
using namespace boost::filesystem;
class DirHandler{
public:
DirHandler();
void getPaths(ifstream file);
void output();
static void run_thread(pair<string, int> * dir, string cur_path, void *args)
{
DirHandler *prunnable = static_cast<DirHandler*>(args);
prunnable->some_counting(dir, cur_path);
}
private:
vector<thread> threads;
vector<pair<string, int>> paths; // current directory name and files amount
void some_counting(pair<string, int> * dir, string cur_path);
void escape();
};
DirHandler.cpp
void DirHandler::getPaths(ifstream file)
{
// parse pathes and create separate thread for each
string line;
if (file.is_open())
{
while (getline(file, line))
{
cout << line << endl;
// add thread for path
pair<string, int> dir = make_pair(line, 0);
paths.push_back(dir);
threads.push_back(thread(&DirHandler::run_thread, &paths.back(), line, this));
}
for (auto& thr : threads){
thr.join();
}
file.close();
}
}
void DirHandler::some_counting(pair<string, int> * dir, string cur_path){...}
main.cpp
#include <iostream>
#include <windows.h>
#include "DirHandler.h"
int main(int argc, char* argv[])
{
DirHandler dirHandler = DirHandler();
dirHandler.getPaths(ifstream("strings.txt")); //ifstream(argv[1])
dirHandler.output();
return 0;
}
Note : While debugging I've found that all streams before last have id=0 in the end
Also I've read that the problem can be caused by a reference to single object. (In my case it's vector<pair<string, int>> paths)
So my question is how to get few threads work correctly ?
The problem is that you get pointers from the paths vector, and if the vector is resized all previous pointers (and iterators) to elements in the vector will become invalid. Using an invalid pointer leads to undefined behavior which often leads to crashes.
And one common way of causing a vector is to adding new elements to it, exactly what you do in your loop.
One solution is to either pass a reference to the vector and an index of the element to the thread (the index will not change on reallocation). Another solution is to have two loops, one to add all elements to the vector and the second to create the threads.
There are other solutions too, like not passing a pointer to the thread, but instead pass the pair by value. This is actually the solution I recommend.
After checking your code a little, I also see that since you use std::thread you don't need the static member function wrapper at all. Instead you can call the non-static actual thread function directly:
threads.emplace_back(&DirHandler::some_counting, this, paths.back(), line);
[Note the use of this as the second argument, as well as the change to emplace_back for the threads vector]
Well, the most obvious problem is here: threads.push_back(thread(&DirHandler::run_thread, &paths.back(), line, this)); you are using pointer to the object(&paths.back()) which might not be there anymore after any push_back. So this error should be fixed, you can't pass pointer to the vector item unless you can guarantee that it will not reallocate its internal structure.
Besides that and ugly code I don't see anything. But more problems might be lurking in the some_counting method.

Calling the function pointed by a Pointer-to-Member-Function from within a struct

I have a class Test with a peculiar data structure.
A member of class Test is a std::map where the key is a std::string and the mapped value is a struct defined as follows:
typedef struct {
void (Test::*f) (void) const;
} pmf_t;
Initialization of the map is OK. The problem is when I am trying to call the function pointed. I made up a toy example reproducing the problem. Here it is:
#include <iostream>
#include <map>
using namespace std;
class Test;
typedef void (Test::*F) (void) const;
typedef struct {
F f;
} pmf_t;
class Test
{
public:
Test () {
pmf_t pmf = {
&Test::Func
};
m["key"] = pmf;
}
void Func (void) const {
cout << "test" << endl;
}
void CallFunc (void) {
std::map<std::string, pmf_t>::iterator it = m.begin ();
((*it).second.*f) (); // offending line
}
std::map<std::string, pmf_t> m;
};
int main ()
{
Test t;
t.CallFunc ();
return 0;
}
Thanks in advance,
Jir
The name of the pmf_t type is f, so the first change is to remove the * to get second.f. That gives you a pointer-to-member value. To use a pointer-to-member, you need an instance. The only one you have available of the correct type is this, so use it with the ->* operator:
(this->*it->second.f)();
You need parentheses around the whole thing, or else the compiler thinks you're trying to call it->second.f() (which isn't allowed) and then applying the result to ->*.
The offending line is trying to call a member function without any object to call it on. If the intention is to call it for the this object, I believe the call should look like
( this->* ((*it).second.f) )();
Where this->* is the syntax for dereferencing a pointer-to-member for the current object. ((*it).second.f) is the pointer retrieved from the map, and () is the call operator for actually calling the function.
This is perhaps good as an exercise, but otherwise of limited use.
I think you might want to check out the C++ FAQ on this one. The syntax is apparently pretty tricky to get right (they actually recommend using a macro).
It might be too late for this question but, the seemingly complex synatax can be break down to two simple lines so it looks pretty clear:
void CallFunc (void)
{
pmf_t t = m["key"]; //1>get the data from key
(this->*t.f)(); //2>standard procedure to call pointer to member function
}
try this:
(this->*((*it).second.f)) ();

Creating a global FILE* object?

I'm building a program that has several functions that need to read data from a file. Since the functions are used fairly frequently, opening and closing the file for each call would be too time consuming, so my plan was to make the FILE* object global, and have the file open the whole duration of the program. Apparently, though, it's not possible, since this:
#include <fstream>
FILE * yhtit;
yhtit = fopen("thefile.txt","r");
int main() {
return 0; }
gives error: main.cpp|54|error: expected constructor, destructor, or type conversion before ‘=’ token|
What's the best way to keep a file open the whole duration of the program, without having to separately pass the FILE* object to every function that needs it?
You almost got it right. Try this:
#include <fstream>
FILE * yhtit;
int main() {
yhtit = fopen("thefile.txt","r");
//Do your thing here.
fclose(yhtit);
return 0;
}
It'd be better to pass the FILE pointer to your functions than to create a global variable. Global variables are often code smells—signs of questionable coding. You can pass the file to your functions without having to open and close the file multiple times. For example:
#include <stdio.h>
void readData(FILE *);
void readMoreData(FILE *);
int main() {
FILE *fp = fopen("...", "r");
readData(fp);
readMoreData(fp);
fclose(fp);
return 0;
}
#include <fstream>
FILE * yhtit = fopen("thefile.txt","r");
int main() {
return 0; }
You can maintain the File * variable in a structure and make that structure accessible from any function.
typedef struct
{
FILE *fp;
//other members can also be part of this structure.
}myData;
appInit(myData *ptr)
{
ptr->fp = fopen(<>,<>);
//Initialise other variables also
return;
}
appDeInit(myData *ptr)
{
fclose(ptr->fp);
}
main()
{
myData *ptr= malloc(sizeof(myData));
appInit(ptr);
//Play with ptr in all your function calls
foo(ptr);
appDeInit(myData);
}