Creating a global FILE* object? - c++

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);
}

Related

External Objects Across CPP files (Boost Filesystem/Variants, Libconfini)

I've got a deceptively complex one for y'all.
I am attempting to make a program which makes use of an INI config file (I am using the libconfini C library), which looks like this:
[General]
output_directory = /scratch/miles/trans_assembly_pipeline/
[SRA accessions]
SRR18328591
SRR28481881
It parses the information therein into a map, index-able by section, and then by key, which looks like this (the only important bit really is the char* option in the variant object):
map<string, map<string, boost::variants<int, bool, double, string, char*>>
Since keys in INI files can have various types, I am utilizing Boost's 'Variants' library to allow for multiple value types. Finally, for convenient file management, I am using Boost's 'Filesystem' library.
I have an INI parsing implementation file, which basically just stores the INI data into that map type, defined thus (the header for which, merely containing function declarations and definition directives, can be found at the bottom):
#include "ini_parse.h"
namespace fs = boost::filesystem;
// Dispatch INI data to a map, indexable by sections, then by keys
static int ini_callback(IniDispatch * const dispatch, void * map_pt) {
#define thismap (reinterpret_cast<INI_MAP*>(map_pt))
if (dispatch->type == INI_COMMENT) {
return 0;
}
if (dispatch->type == INI_SECTION) {
INI_MAP_ENTRY newSec;
thismap->insert(std::pair<std::string, INI_MAP_ENTRY>(dispatch->data, newSec));
return 0;
}
if (dispatch->type == INI_KEY) {
(*thismap)[dispatch->append_to].insert(std::pair<std::string, BOOST_VAR>(dispatch->data, dispatch->value));
}
return 0;
}
// Given a FILE object, return a buffer containing its contents
char * make_ini_buffer(FILE * iniFile) {
char * iniBuffer;
long sz;
fseek(iniFile, 0L, SEEK_END);
sz = ftell(iniFile);
rewind(iniFile);
iniBuffer = (char*)malloc(sz + 1);
fread(iniBuffer, 1, sz, iniFile);
return iniBuffer;
}
// Given the path/name of an INI config file, return a map of its data
// which can be indexed by sections, and then by keys
INI_MAP make_ini_map(const char * configPath) {
FILE * configIni = fopen(configPath, "r");
fs::path configPathObj(configPath);
try {
if (!configIni) {
std::string fileError = "ERROR: Cannot open config file: ";
throw std::runtime_error(fileError);
}
} catch (std::runtime_error& e){
std::cerr << e.what() << configPathObj.filename() << std::endl;
return {};
}
INI_MAP iniMap;
char * iniBuffer = make_ini_buffer(configIni);
strip_ini_cache(iniBuffer, strlen(iniBuffer), INI_DEFAULT_FORMAT,
NULL, ini_callback, &iniMap);
delete [] iniBuffer;
return iniMap;
}
INI_MAP cfgIni = make_ini_map("../config.ini");
Note the final line, outside of any other function, defining 'cfgIni'. The idea is to define a global INI data storage object that can be used externally by other files -- for example, like this:
#include "ini_parse.h"
int main() {
extern INI_MAP cfgIni;
extern int size_path;
std::cout << cfgIni["General"]["output_directory"] << std::endl;
return 0;
}
Now for my problem: When declaring 'cfgIni' externally in this separate file, it appears that bits of memory are getting lost from where it is defined in my implementation file to where it is declared externally and caught here. I have no issue accessing the keys in the parent/child map, but the values are more illusive.
When printing the contents of the section "General", "output_directory" is returned, no problem.
I would expect the final line in the above code snippet to print the filepath char* array, to which "output_directory" is set in the INI file.
However, I instead get some random characters, like "�U". What is even more confusing is when I print out the size of this return value in memory using sizeof(), it returns '40', the correct number of characters in that filepath.
I have linked the documentation for the libraries I used and their functions. Apologies for the length/complexity of this question.
strip_ini_cache(): https://madmurphy.github.io/libconfini/html/confini_8c.html#a25d648d387f6e8bc36e7965accfca63b
Boost.variant: https://www.boost.org/doc/libs/1_61_0/doc/html/variant.html
Boost.filesystem: https://www.boost.org/doc/libs/1_80_0/libs/filesystem/doc/reference.html
Below is my header file:
#include <iostream>
#include <string>
#include <map>
#include <cstdio>
#include <confini.h>
#include <boost/filesystem.hpp>
#include <boost/variant.hpp>
#define BOOST_VAR boost::variant<int, bool, double, std::string, char*>
#define INI_MAP_ENTRY std::map<std::string, BOOST_VAR>
#define INI_MAP std::map<std::string, INI_MAP_ENTRY>
static int ini_callback(IniDispatch * const dispatch, void * map_pt);
char * make_ini_buffer(FILE * iniFile);
INI_MAP make_ini_map(const char * configPath);
The answer to this is really quite trivial. When passed by value, as I had done in one of my files, a shallow copy of the object was created, wherein the pointers to the char arrays were overwritten with wild addresses.
The solution was to pass by const reference.

FILE* initialisation in different function c++

I need to initialise FILE *fi in different function. This example code shows the problem.
#include<iostream>
using namespace std;
void init(FILE* fi)
{
fi=fopen("in.txt", "r");
if(fi==NULL)
{
cout<<"Got NULL\n";
}
}
int main()
{
FILE* fi;
init(fi);
if(fi==NULL)
{
cout<<"NULL\n";
return 0;
}
return 0;
}
The program outputs NULL (not "Got NULL"), and I don't have a clue how to make it work...
It is important that I have fi passed as a pointer, not getting it as a return value.
You shouldn't manipulate arguments unless that's the specific intent of the code. It's better to simply return things:
FILE* init()
{
return fopen("in.txt", "r");
}
Then you call it like this:
FILE* fi = init();
Note that since you're using C++ you should avoid using C anachronisms like FILE and instead use C++ file streams.
If you need to handle multiple return values:
std::tuple<FILE*, FILE*> init() {
return std::make_tuple(
fopen("in.txt", "r"),
fopen("out.txt", "w")
);
}
This is just a step towards making it proper C++ code by encapsulating all of this inside a proper class definition and then you can manipulate properties directly:
class FileWrapper {
public:
FileWrapper();
~FileWrapper();
void init();
protected:
FILE *fi;
FILE *fo;
}
void FileWrapper::init() {
fi = fopen("in.txt", "r");
fo = fopen("out.txt", "w");
}
In that case you don't even need return values. You'll also be able to automatically clean up those filehandles when that wrapper class gets deallocated if you write a proper destructor.
OK, got it.
Replase
void init(FILE* fi)
with
void init(FILE*&fi)

Simplest way to create a file for writing within a function?

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;
};

error: ‘length’ was not declared in this scope c++

I am beginner c++ programmer, It's my first program even (For those who are very keen to give negatives). I had written the same code in c but now trying to do in c++.
Where I get the following error.
error: ‘length’ was not declared in this scope
My code is as below.
#include <iostream>
#include <fstream>
#include <assert.h>
using namespace std;
class Huffman
{
public:
int data_size, length; //THis length variable is not accessible in main function below in main function.
Huffman(char *filename);
~Huffman();
struct Huffman1
{
int value;
unsigned char sym; /* symbol */
struct Huffman1 *left,*right; /* left and right subtrees */
}; typedef struct Huffman1 Node;
};
Huffman::Huffman(char * file_name)
{
//I will do something here soon
}
Huffman::~Huffman()
{
}
int main(int argc, char * * argv)
{
length=10; //Not accessible here.
if (argc < 2)
{
cout<<"Ohh.. Sorry , you forgot to provide the Input File please" <<endl;
return(0);
}
Huffman Object1(argv[1]);
return(0);
}
I am not sure that it's c++ programming error because it may be because i am compiling it g++ Filename.c -o filename. Could someone please correct if it's a programming error or it's due to the way i compile ?
thanks.
length is a member of the class, so it does not exist outside the class.
You can access lenth after creating an object of class Huffman as follows
Huffman Object(argv[1]);
Object.length = 10;
length belongs to Huffman class. So you should use it for Object1 after it's definition:
Huffman Object1(argv[1]);
Object1.length = 10;
You know, public: doesn't mean that anything put inside under that branch in the class tree, will be accessible everywhere it just means that you access the instance variables of the class through "dot notation" like so Object.length.
However if you truly wanted length to be accessible everywhere, you should declare it as a global variable:
short int length;
class Huffman{
...
};
...
It's a compile error and your code is responsible. You defined length inside your Huffman class. It's a member of that class, not a global variable.
Imagine your class as a C Struct. You'd need to create a struct first in order to access the variable. Same thing applies to C++ classes.
Try Object1.length = 10; after you create the instance of your class.
EDIT
For your purposes, use C++ classes as you would use C structs. That will do the trick.
I would actually put the Node struct declaration outside of the Huffman class. I think it's easier to understand. Also, using a typedef to a struct is not really that useful in C++ for these cases, the name of the struct is usable by just declaring the struct.
The pointers do not allocate memory for the struct themselves. Only after you allocate memory they will be usable, and even then they're members of Object1, so you need that too.
#include <iostream>
#include <fstream>
#include <assert.h>
using namespace std;
struct Node
{
int value;
unsigned char sym; /* symbol */
};
class Huffman
{
public:
int data_size, length; //THis length variable is not accessible in main function below in main function.
Huffman(char *filename);
~Huffman();
Node *left,*right; /* left and right subtrees */
};
Huffman::Huffman(char * file_name)
{
//I will do something here soon
}
Huffman::~Huffman()
{
}
int main(int argc, char * * argv)
{
length=10; //Not accessible here.
if (argc < 2)
{
cout<<"Ohh.. Sorry , you forgot to provide the Input File please" <<endl;
return(0);
}
Huffman Object1(argv[1]);
Object1.left = new Node;
Object1.right = new Node;
//Do your stuff here...
Object1.left->sym;
return(0);
}
This should get you started, it is by no means a perfect implementation. It's not even very C++ oriented, but I already went ahead of myself with the answer. This is a topic for a very different question, which you're welcome to ask in SO, but try not to make questions inside questions.
Good luck!
length is part of your class, not main, thus the compiler is right.
Members belong to an object and are accessed liek this:
Huffman huffmannObj(...);
std::cout << huffmannObj.length << std::endl;
length is a publicly accessible member of your class, but you'll need an instance of that class first before you can do anything with the member
Huffman h(whatever_constructor_params);
h.length = 10;
...is ok

Initializing a large global constant object

How do you use a file to initialize a global const object that is too large to be created in the stack? This is my attempt so far:
// test.h
#pragma once
#include <boost/array.hpp>
typedef boost::array<int,100000> bigLut_t;
extern const bigLut_t constLut;
// test.cpp
#include <fstream>
#include <boost/filesystem.hpp>
#include "test.h"
bigLut_t& initializeConstLut()
{
if( boost::filesystem::exists("my_binary_file") == false ) {
std::ofstream outStream( "my_binary_file", ios::out | ios::binary );
bigLut_t* tempLut = new bigLut_t;
for(int i = 0; i < 100000; ++i) {
// Imagine this taking a long time,
// which is why we're using a file in the first place
tempLut->at(i) = i;
}
outStream.write( reinterpret_cast<char*>(tempLut), sizeof(bigLut_t) );
outStream.close();
delete tempLut;
}
// We can't write "bigLut_t lut;" because that would cause a stack overflow
bigLut_t* lut = new bigLut_t; // lut gets never deallocated
std::ifstream inStream( "my_binary_file", ios::in | ios::binary );
inStream.read( reinterpret_cast<char*>(lut), sizeof(bigLut_t) );
inStream.close();
return *lut;
}
const bigLut_t constLut = initializeConstLut();
AFAIK this works in a sense that constLut gets corretly initialized, but there's a memory leak since bigLut_t* lut gets never deallocated. I tried using a smart pointer for it, but that resulted in the values in constLut being quite random. I'm baffled by the lack of information I found by trying to google the solution.
How did you use shared_ptr ? Try the following :
// test.h
#pragma once
#include <boost/array.hpp>
typedef boost::array<int,100000> bigLut_t;
extern const bigLut_t constLut;
// test.cpp
#include <fstream>
#include <boost/filesystem.hpp>
#include "test.h"
boost::shared_ptr<bigLut_t> initializeConstLut()
{
if( boost::filesystem::exists("my_binary_file") == false ) {
std::ofstream outStream( "my_binary_file", ios::out | ios::binary );
bigLut_t* tempLut = new bigLut_t;
for(int i = 0; i < 100000; ++i) {
// Imagine this taking a long time,
// which is why we're using a file in the first place
tempLut->at(i) = i;
}
outStream.write( reinterpret_cast<char*>(tempLut), sizeof(bigLut_t) );
outStream.close();
delete tempLut;
}
// We can't write "bigLut_t lut;" because that would cause a stack overflow
boost::shared_ptr<bigLut_t> lut(new bigLut_t); // lut gets never deallocated
std::ifstream inStream( "my_binary_file", ios::in | ios::binary );
inStream.read( reinterpret_cast<char*>(lut), sizeof(bigLut_t) );
inStream.close();
return lut;
}
const bigLut_t constLut = *(initializeConstLut().get());
There are several good solutions to your problem. The solutions offered as answers so far are not among the good solutions (in particular, dynamic allocation and copying and relying on lifetime of temporary objects is just Very Bad™). I'll just give you one common solution.
A simple way to provide a huge constant is to use a Meyers' singleton, which means defining the constant as a static local variable in a function that returns a reference to it:
inline BigThing const& theBigThing()
{
static BigThing const theInstance; // Default constructor does the init job.
return theInstance;
}
This is not yet a complete solution, but let's first see how you can get rid of having to invoke a function, and instead dealing directly with what-looks-like-a-constant:
namespace detail {
inline BigThing const& theBigThing()
{
static BigThing const theInstance; // Default constructor does the init job.
return theInstance;
}
}
BigThing const& theBigThing = detail::theBigThing(); // No copying, just ref.
In your case where BigThing is an array that should be initialized from data in a file, you can't directly rely on the default constructor. You could if you defined a wrapper class, and that's one way. OK, let's do that (it's what I'd choose, I think):
namespace detail {
struct BigThingWrapper
{
BigThing thingy_;
BigThingWrapper()
{
// Initialize the thingy_ member here.
}
};
inline BigThing const& theBigThing()
{
static BigThingWrapper const theInstance;
return theInstance.thingy_;
}
}
BigThing const& theBigThing = detail::theBigThing(); // No copying, just ref.
Note 1: I've used inline so that the code conceivably could be placed in a header file. Just remove for implementation placed in an implementation file.
Note 2: This code is untouched by compiler's hands and so may contain ERORS, TYPPOS and whatnot. :-) But it's the idea that is your answer.
Note 3: There are, as mentioned, also other good ways to do this, so this is not "the" answer, and there is no "the" answer, but it's "an" answer.
Cheers & hth.,
Just doing it the old fashioned way is fine - create an auto pointer whose lifecycle is the whole application life-cycle, and an extern reference to the pointer:
// test.h
#pragma once
#include <boost/array.hpp>
typedef boost::array<int,100000> bigLut_t;
extern const bigLut_t& constLut; // make it a reference
// test.cpp
#include <fstream>
#include <boost/filesystem.hpp>
#include "test.h"
namespace {
std::auto_ptr<bigLut_t> initializeConstLut()
{
std::auto_ptr<bigLut_t> lut(new bigLut_t);
if( boost::filesystem::exists("my_binary_file") == false ) {
std::ofstream outStream( "my_binary_file", ios::out | ios::binary );
for(int i = 0; i < 100000; ++i) {
// Imagine this taking a long time,
// which is why we're using a file in the first place
lut->at(i) = i;
}
outStream.write( reinterpret_cast<char*>(lut), sizeof(bigLut_t) );
outStream.close();
// no point writing then reading the same data
} else {
std::ifstream inStream( "my_binary_file", ios::in | ios::binary );
inStream.read( reinterpret_cast<char*>(lut.get()), sizeof(bigLut_t) );
inStream.close();
}
return lut;
}
// local to this compilation unit, deletes object on exit
std::auto_ptr<bigLut_t> constLutPtr ( initializeConstLut() );
}
// the extern reference refers to the object held by the auto_ptr
const bigLut_t& constLut ( *constLutPtr.get() );
No extra copying, client code sees the extern variable as before, though the linker may have to have an extra indirection rather than the extern varibale being in a fixed address (&constLutPtr is on the heap rather than in static data area).
If having a fixed address for constLut is important, go back to having an extern value rather than an extern reference, read the data in using a reinterpret cast and a const_cast of &constLutPtr. pass reinterpret_cast<char*>(const_cast<bigLut_t*>(&constLut)) to the stream read.
Wouldn't it be easier to just make your global object a pointer, new a temporary object from initializeConstLut and set the global pointer to that object before exiting the function ?
If the object is so big, you should avoid any solution which involves copying and/or assignment. So you're left with several choices :
Make the global object a pointer (free copy)
Make the global object non-const and read directly in it
I can't believe I'm saying this, but use a Singleton like pattern and wrap the object. This will allow you to isolate initialization and provide a public method for access which will return a const reference to the array.
I'm not adding much details here because it really depends on your requirements (I'm thinking thread-safety for instance).
There is a line of thought that says known objects do not leak, if the only leak is at the end of application life. If all you do with the object is remove it from memory (and do not release other resources, nor update some external stuff like DB's and files) then you can just leave it there. After all, by explicitly deleting them from memory you are just blocking the application from finishing for no real benefit: memory will be released one way or the other.
Add an explicit destruction of the lut. You are responsible for destroying anything you create. Best is to do it explicitly:
void destroyLut(bigLut_t& lut)
{
delete &lut;
}
Then simply call this function before exiting main. You should never rely on static initialization and destruction in C++. Better is to always do explicit initialization and destruction.