I have a class sample as:
class sample{
public:
sample(){
sample_name=new char[10];
}
int sample_num;
float sample_wt;
char *sample_name;
};
Its object is created and values are accesed as folllows:
sample *object= new sample();
object->sample_num=10;
object->sample_wt=20.02;
object->sample_name="test";
My question is as follows:
How will i create a buffer which contains all the information stored inside object?
I tried doing this as follows:
char * buffer = new char[256];
buffer = reinterpret_cast <char *> ( object );
Now,what i see is the object do consists of all the three values of sample_num, sample_wt and sample_name but these values are not passed to buffer,buffer shows garbage values.
So, how will i get these values inside the buffer?
Instead of using <char *> use <void *> if you are using buffers or you can use stl::vector to buffer some object and put these objects to the vector as shown in below code.
'int main()
{
int x;
int size;
vector<BoxOfProduce>box;
cout<<"How many boxes you want";
cin>>size;
for ( x = 0; x < size; x++)
{
BoxOfProduce obj; //create an object
box.push_back(obj); //insert it into the vector
}
for ( x = 0; x < size; x++)
{
box[x].setItemAry();
box[x].randomPick();
box[x].display();
box[x].change();
box[x].display2();
}
getchar();getchar();
return 0;
}'
and you can use Ques, Ques are the best options for buffering.
First Create a structure and store all the values in the structure and put that structure in to the queue.
This code is wrong on so many levels.
Your constructor isn't initializing your variables, but creates an array on the free store, and never deletes it. For default constructor just initialize your members to a default value (likely 0 here and nullptr for sample_name).
Replace
sample *object= new sample();
object->sample_num=10;
object->sample_wt=20.02;
object->sample_name="test";
With a proper constructor, that creates an object with the values given as parameters. Also, to create an object, you don't have to use new by default, you can just write
sample object
To get to your question. If you are using reinterpret_cast to see your object as a char[] you are relying on the fact that the layout of your object may or may not be as you see it in it's definition. This may even work, but you need to make sure that your class fulfills the requirements. Here are some further reading on the topic:
What are POD types in C++?
What are Aggregates and PODs and how/why are they special?
Until that, if you want to serialize your object i.e. read and write it to a stream/buffer, you should write serialize/deserialize functions, reading and writing each member to the stream.
Having in mind #Kerrek SB memory leaks and using standard strings and input/output operators:
#include <ostream>
#include <iostream>
#include <sstream>
class sample
{
public:
sample() {}
int sample_num;
float sample_wt;
std::string sample_name;
friend std::ostream & operator<<(std::ostream &, const sample&);
};
std::ostream & operator<<(std::ostream & os, const sample & sam)
{
os << sam.sample_num << " " << sam.sample_wt << " " << sam.sample_name.c_str();
return os;
}
int main(int argc, const char * argv[])
{
sample *object= new sample;
object->sample_num=10;
object->sample_wt=20.02f;
object->sample_name="test";
std::stringstream buffer;
buffer << *object;
std::cout << buffer.str();
delete object;
return 0;
}
Related
EDIT: Pasting portion of code that is giving me this issue. Although in my effort to cleanup some of the comments before pasting it here I ended up with a different error. Still happens in the same place though: "munmap_chunk(): invalid pointer
Aborted (core dumped)".
Learning C++; working on polymorphism.
I created a virtual base class and the idea is to have multiple child classes, although I'm currently just stuck on one. My program cannot use vectors, and must include a lambda, so I thought one way to incorporate it would be to just have a function that loops through all my objects and sends the object to the lambda which simply displays the name.
My issue is that I'm trying to figure out how to write the function and lambda parameters/arguments so that it accepts and can work with all my objects. I thought using the base class to create an array of pointers would e the answer but it's resulting in a segmentation fault.
Perhaps I'm misunderstanding inheritance, or perhaps unclear about the way I should be using the pointers and looping through the arrays?
#include <iostream>
#include <string>
#include <cstdlib>
#include <iomanip>
using namespace std;
//Hokeemon Class parent to Child class(es)
class Hokeemon {
friend ostream &operator<< (ostream &stream, Hokeemon &critter);
public:
// int hat, eyes, mouth, health = 0, boredom = 0; string name;//bool alive;
string name;
// virtual string changeName(string); // offers user to change critter name
// virtual void passTime(){health--; boredom++;};
// virtual void description(){};
virtual string getName(){return name;};
};
class Playful : public Hokeemon{ //inherits from parent Hokeemon
public:
Playful() {
cout << "Hokeemon's being hatched.\n";
name = "Test";
}
~Playful(){cout << "Hookemon deleted" << endl;};
};
void forEach(int objects, Hokeemon** ptr, int**, void(*func)(Hokeemon &critter));
int main() {
int obj = 1, aliveSize = 3; int playSize;
srand((time(NULL)));// seed for random numbers
playSize = aliveSize;
int* arraySizes[obj]{}; //to hold sizes of child class arrays
Hokeemon* hPtr[obj];
hPtr[0] = new Playful[playSize]; arraySizes[0] = &playSize; //creates pointer to array of pointers for objects of class Playful
forEach(obj, hPtr, arraySizes, [](Hokeemon &critter){ cout << critter.getName();}); //<< endl; critter.description();});
delete hPtr[0];
return 0;
}
void forEach(int obj, Hokeemon **hArray, int** array, void(*func)(Hokeemon &critter)){
Hokeemon* temp = NULL; //create pointer to hold pointers in array
for( int i = 0; i < obj; i++){ //this level loops through objects in array
temp = hArray[i]; //assigns temp pointer to applicable class pointer
for (int j = 0; j < *array[i]; j++){// loops through objects in class
func(temp[j]);
}
}
}
I can't get it to print past the first object (ptr[0][0] if I'm understanding correctly). I've tried manually printing ptr[0][1] and I get a segmentation fault. How should I be doing it so that I can access the second object of the Child class? Again, I'd like to keep it general so that I can easily add in another Child class and just change the array slightly.
I'm working on c++ and I need to save this struct into a file:
struct myStruct{
int value;
int value2;
MyClass * myClass[10];
};
The way that I'm saving this struct is the following:
myStruct my_struct;
my_struct.value = 1;
my_struct.value2 = 2;
for ( int i = 0; i < 10; i++){
my_struct.myClass[i] = new MyClass();
}
FILE* f = fopen(path.c_str(), "wb");
if ( f != NULL){
fwrite(&my_struct, sizeof(myStruct), 1, f);
fclose(f);
}
But, when I want to read this file, my program crashes when try to access to the array of "MyClass":
FILE* f = fopen(path.c_str(), "rb");
if ( f != NULL){
fread(&my_struct2, sizeof(struct myStruct), 1, f);
fclose(f);
}
for ( int i = 0; i < 10; i ++ ){
if ( my_struct2.myClass[i] != NULL ){
//Here is the crash
}
}
I've been searching but I can't find a solution. I only find topics about arrays of structs. I know that maybe I'm not searching very well.
Thanks.
Your MyStruct contains twenty pointers to other structures.
By fwrite()ing the contents of your MyStruct to a file, you have successfully written twenty raw memory addresses of your other structures into the file, together with the other members of the MyStruct class.
Which, of course, is utterly meaningless when you try to read them back in another process. You've read back twenty raw memory addresses. Which mean nothing to a completely unrelated process. And, accessing those memory addresses, unsurprisingly, leads to a crash since those memory addresses, for all intents and purposes, are completely random values.
What your code needs to do is not write twenty raw pointer addresses to the file, but the contents of those pointers, and what they point to.
I want to add some things to Sam's answer, even if I know this is not code review, you are writing C in C++.
C++ is not meant to be coded in C, it doesn't want to... It fought its entire life to break its bound with its deprecated father, to surpass him, to explore new meanings and way to solve problems and build efficient code. Don't do this to him... (I love C by the way, deprecated was a joke obviously ;) )
Here's how I'd do it:
#include <fstream>
#include <iostream>
class MyClass
{
public:
MyClass() : _type(-1) {}
MyClass(int type) : _type(type) {}
inline const int &type() const
{ return _type; }
private:
int _type;
};
// -- overload of operator<< that permits me to write a MyClass* to a stream
std::ostream &operator<<(std::ostream &stream, MyClass *myClass)
{
stream << "myClass::type: " << myClass->type();
return stream;
}
struct MyStruct
{
int value;
int value2;
MyClass *myClasses[10];
MyStruct()
{
value = -1;
value2 = 1;
for (std::size_t i = 0 ; i < 10 ; ++i)
{ myClasses[i] = new MyClass(-i); }
}
};
// -- overload of operator<< that permits me to write a MyStruct to a stream
std::ostream &operator<<(std::ostream &stream, const MyStruct &myStruct)
{
stream << "myStruct::"
<< "\n\t value: " << myStruct.value
<< "\n\t value2: " << myStruct.value2
<< "\n\t myClasses: ";
for (std::size_t i = 0 ; i < 10 ; ++i)
{ stream << "\n\t\t " << myStruct.myClasses[i]; }
return stream;
}
int main()
{
std::ofstream outputFile("output.txt");
if (outputFile.is_open() == false)
{ std::cerr << "Could not open file." << std::endl; return -1; }
outputFile << MyStruct() << std::endl; // -- this is where the information is written into the file
outputFile.close();
}
See simple way to write a struct, you could even get it back into the struct the same way with operator>> overload, bonus is you can use on any ostream, which means it will work with sstream, std::cout and everything!
Still this is not really c++-like as there is too much (unprotected) pointers and unchecked magical number sizes (MyClass *myClasses[10]; this is a no-no for me, because it implies this thing: for (std::size_t i = 0 ; i < 10 ; ++i), and this shit gives me shivers).
I would probably use an std::array here
, but I wanted to keep MyStruct as you defined it so the example stay "close" to what you wrote. Another way would have been to use std::unique_ptr or std::shared_ptr.
This can seem as quite a bit of work or intimidating, but you may find that useful in the future. Same goes for using the std containers(array, set, vector, map, etc...), unique_ptr and shared_ptr. But I assure you it's worth giving some time to understand them and learn how to use them. It makes things simpler and safer.
What gave me shivers earlier would be written like this:
std::array<MyClass, 10> myClasses;
Loops would go like this:
for (std::size_t i = 0 ; i < myClasses.size() ; ++i)
{ myClasses[i].type(); }
for (std::array<MyClass, 10>::iterator itC = myClasses.begin() ; itC != myClasses.end() ; ++itC)
{ itC->type(); }
Or even better, a c++11 way to write a loop, that I find easier to read and write:
for (auto myClass : myClasses)
{ myClass.type(); }
Note that if you want to modify myClass inside this one you need to write auto& myClass : myClasses
Hope it helps you.
Using fwrite(&my_struct, sizeof(myStruct), 1, f); is good if your struct my_struct contains purely static data(i.e the data for which memory was allocated at compile time). If it contains dynamic data(i.e the data for which memory is allocated at runtime) then you need to manually store such dynamic data.
Overloading operator<< as shown my #vianney is a good method of saving/serializing dynamic data.
So, here's my code:
/****************************************************************
File: Video.h
Description: class declarations
Author: David && Evan
Class: CSCI 120
Date: 2015 May 13
We hereby certify that this program is entirely our own work.
*****************************************************************/
#ifndef VIDEO_H
#define VIDEO_H
#include <iostream>
#include <string>
#include <vector>
#include "Person.h"
#include "Date.h"
using namespace std;
enum kind {MOVIE, TELEVISION, COMPUTER};
// 'MOVIE' = standalone film of any length, whether it's part of a franchise or not
// 'TELEVISION' = episode from mini- or recurring series
// 'COMPUTER' = online or locally hosted files
/* If need be, we can extend this by adding something for analog home movies,
i.e., camcorder tapes or 8mm film. */
namespace Vids
{
class Video{
public:
Video(); // default constructor
Video(string name, string audience, string location, vector<Person> directors,
vector<Person> actors, Date released);
virtual void display() = 0; // displays information for all objects of Video type
virtual void displayAll() = 0; // displays all information for one object
unsigned char getDirectorSize() const { return directorSize; }
unsigned char getActorSize() const { return actorSize; }
string getName() const { return name; }
string getAudience() const { return audience; }
string getLocation() const { return location; }
Date getReleased() const { return released; }
Date getViewed() const { return viewed; }
string Truncate(string str, size_t width) { // shortens output
if (str.length() > width)
return str.substr(0, width) + "...";
return str;
} // truncate
protected:
short runtimeMinutes;
/* Theoretically runtime could be unsigned, but we might eventually
need negatives for special values. I doubt we'll see one needing
more than 32K minutes, so no worry about overflow. */
unsigned char directorSize;
// number of elements in each vector, shouldn't need more than 255
unsigned char actorSize;
string name; // title of movie
string audience; // PG = "Plenty Guns", PG-13 = "13 or more guns"
string location;
/* Location is a catch-all field for: URL, shelf disc is on, format
type, name of person it is loaned to, etc. */
vector<Person> directors(directorSize);
/* David: I considered using other containers, but none of them
offered any obvious benefits over the vector. */
vector<Person> actors(actorSize);
Date released;
Date viewed;
/* 'viewed' can be used to answer the question: "What haven't i
watched lately?" */
}; // end class Video
} // end namespace Vids
#endif
And compiling [with several other files] gives me this:
$ g++ *.cpp -o Project3
In file included from Computer.cpp:12:
In file included from ./Computer.h:15:
./Video.h:68:29: error: unknown type name 'directorSize'
vector<Person> directors(directorSize);
^
./Video.h:71:26: error: unknown type name 'actorSize'
vector<Person> actors(actorSize);
^
directorSize is declared in the same scope as directors, so why is the compiler not recognizing it?
The line
vector<Person> directors(directorSize);
is not the right syntax for declaring a member variable.
Change it to
vector<Person> directors;
Similarly, change
vector<Person> actors(actorSize);
to
vector<Person> actors;
Given that you can get the number of items in a vector by calling the size() member function, you don't need the member variables:
unsigned char directorSize;
unsigned char actorSize;
Remove them.
Well, this comment is puzzling:
/* Theoretically runtime could be unsigned, but we might eventually
need negatives for special values. I doubt we'll see one needing
more than 32K minutes, so no worry about overflow. */
unsigned char directorSize;
unsigned char maxes out at 255 so if you need up to 32K then you will have to use a different type. In fact it would be better to remove this variable entirely, and retrieve the size by doing directors.size() as needed.
It is possible to initialize the vector in the class definition:
vector<Person> directors{directorSize};
However this would cause undefined behaviour if you hadn't initialized directorSize in the constructor initializer list (because you would be using an uninitialized variable directorSize).
It would be much better to change this to:
vector<Person> directors;
and presumably in your constructor initializer list, or constructor body, you will add some items into this vector.
I'll boil your problem down to a trivial case to demonstrate the problem, along with applying the "m_" member variable prefix popular among some engineers for highlighting a variable that is a "member" of something.
#include <vector>
class Class {
protected:
unsigned char m_directorSize;
std::vector<int> m_directors(m_directorSize);
};
int main()
{
Class x;
}
This does not compile http://ideone.com/VJck4Q and by isolating the problem, we learned a lot.
The line of code:
std::vector<int> m_directors(m_directorSize);
Look at the syntax of this
/typename/ /name/ ( /values/ );
The compiler thinks this is a member-function declaration, which is why it is expecting a type:
std::vector<int> something(unsigned char directorSize);
would declare a member-function called "something" that takes a parameter, directorSize, of type unsigned char. Incidentally: unsigned char is almost guaranteed to be an 8-bit value, capable of storing 0 through 255. That's a terrible choice for a size variable. There is a standard type, size_t for storing non-negative sizes and ssize_t for storing signed sizes.
It's unclear why you think you should be passing directorSize to the vector, but you can't declare a member with a function call.
If you want to shape the default behavior of an object at construction time of your class, you need to use a constructor (or use C++11/C++14, but we don't know if you're doing that):
class Foo_Sized {
std::vector<int> m_vec;
public:
Foo() : m_vec(250) // default construct 250 elements
{}
};
If you were using C++11/14:
class Foo_Sized {
std::vector<int> m_vec = std::vector<int>(250);
};
But if you want to affect one member based on the value of another, the only place you can do that is in a member function, so in this case that means the constructor.
If you're going to create a static array like that, you probably want to be using std::array instead of std::vector - the whole point of vector is that it can grow dynamically.
std::array<int, 250> m_arr;
This declares an array of integers which has a capacity of 250 and has a fixed size. It's faster than a vector but it is always 250 large. You would then have to track the "in-use" count of it and other management overhead yourself.
std::vector<int> vec;
std::cout << vec.size() << '\n'; // prints 0
vec.push(10); // add a value of 10 to the vector.
vec.push(20); // vec is now { 10, 20 }
std::cout << vec.size() << '\n'; // prints 2
vec.push(30); // vec is now { 10, 20, 30 }
std::cout << vec.size() << '\n'; // prints 3
std::cout << vec[0] << '\n'; // prints 10
std::cout << vec[3] << '\n'; // undefined behavior, there is no 3rd element
std::array<int, 3> arr;
std::cout << arr.size() << '\n'; // prints 3: fixed size.
arr[0] = 10; // can't push, fixed size.
arr[1] = 20;
std::cout << arr.size() << '\n'; // still 3, always will be.
arr[2] = 30;
std::cout << arr.size() << '\n'; // still 3, always will be.
std::cout << arr[0] << '\n'; // prints 10
std::cout << arr[3] << '\n'; // compile error: outside fixed size
If you were worrying about memory allocation, you could tell the vector to allocate memory upfront like this:
class Foo_Reserved {
std::vector<int> m_vec;
public:
Foo() : m_vec() // default construct empty
{
m_vec.reserve(250); // reserve memory for 250 elements
}
};
There are a host of other issues with your code, but they aren't directly related to your question so I'm not going to address/highlight them.
But in terms of dealing with your directorSize issues, you should consider providing an accessor that queries the vector or expose a const reference to the vector (this somewhat breaks encapsulation tho since it allows external callers to write code based on assumptions about your internal structure).
class Foo {
public:
using vec_t = std::vector<int>;
protected:
vec_t m_vec;
public:
Foo() : m_vec() // default construct empty
{
}
size_t vecSize() const { return m_vec.size(); }
// or, return a look-don't-touch reference to the vector
const vec_t& getVec() const { return m_vec; }
};
Foo f{}; // C++14 initializer
f.vecSize();
f.getVec().size();
I'm quite new to C++. I've been trying to figure this out for days - there'll be an easy solution no doubt but I haven't been able to find it (after much googling)! My problem is this:
I'm trying to create a class with a member function that reads in characters from a file and stores them in an array. I want to be able to create multiple objects (not sure how many - decided by the user), each with their own arrays filled with characters taken from different files. I think I've managed to do that. How would I then go about accessing the object's array in main?
The code I'm working on is long and messy but something along these lines (char.txt contains simply '12345' in this case):
#include <iostream>
#include <fstream>
using namespace std;
class Something{
public:
void fill_array(char array_to_fill[]){
char next;
ifstream input;
input.open("chars.txt");
input.get(next);
while(!input.eof())
{
for(int i = 0; i < 6; i++)
{
array_to_fill[i] = next;
input.get(next);
}
}
}
};
int main()
{
Something* something = new Something[1];
char array_to_fill[5];
something->fill_array(array_to_fill);
//I'd like to be able to access the array here; for example - to cout the array.
return 0;
}
Apologies if a) my terminology is wrong b) my code is rubbish or c) my question is stupid/doesn't make sense. Also I should add I haven't learnt vectors yet and I'm not supposed to use them for the program I'm making. Any help would be much appreciated. Cheers!
Your class does not store the array at all. It is simply a holder for a method. You probably want something like this, where each instance of the class holds the array. (I changed it to std::string since they are nicer to work with.)
class Something
{
private:
std::string data;
public:
void fill_data( const std::string& filename )
{
ifstream file( filename );
file >> data;
file.close();
}
std::string get_data() const
{
return data;
}
}
int main()
{
std::vector<Something> my_things;
my_things.push_back( Something() );
my_things[0].fill_data( "chars.txt" );
cout << my_things[0].get_data() << std::endl;
my_things.push_back( Something() );
my_things[1].fill_data( "another_file.txt" );
cout << my_things[1].get_data() << std::endl;
}
Since you are using C++, not C, get used to writing C++ code instead of C. (std::vector instead of C arrays (for unknown length arrays), std::string instead of char*, etc).
I think your question is too general for the format of stack overflow, but what you want in this case is to either create a public member, or create a private member with setters and getters.
class Something
{
public:
std::string m_string;
}
int main()
{
Something A;
A.m_string = "toto";
cout << A.m_string;
return 0;
}
Put a string for convenience (you could use a const char* but you will have to understand what is the scope to know when it will not be accessible anymore and you are not quite there yet) and there may be typos since I typed this from a phone.
If you really want to access the chars themselves, pass a char* with a size_t for the length of the array or use std::array if possible.
Right now the method fill_array is creating a local copy of array_to_fill, so any changes that you make to array_to_fill only happen in the local method. To change this, pass by pointer. This way the pointer gets copied instead of the whole array object. I didn't test this but it should look more like this:
void fill_array(char* array_to_fill){
...
}
You don't need to change anything in the main method.
To actually access the elements you can use [] notation. I.e. cout << array_to_fill[0] in the main method.
Edit: I think that change should work.
This is a C++ question. I have a class that contains a string:
class MyClass{
public:
std::string s;
};
And I have an array of MyClass objects:
MyClass * array = MyClass[3];
Now I want to write the array as binaries into a file. I cannot use:
Ofstream.write((char *)array, 3 * sizeof(MyClass))
because the size of MyClass varies.
How can I use Ofstream.write to achieve the purpose? Many thanks.
Overload operator<< for your class. You could do it as follows:
ostream& operator<< (ostream& os, const MyClass& mc)
{
return os << mc.s /* << ... other members*/ << endl;
}
In C++ it is usually done using the BOOST serialization class
Programmatically you could do something like this:
Writing:
std::ofstream ostream("myclass.bin",std::ios::binary);
if (!ostream) return; // error!
std::size_t array_size = 3;
ostream.write(reinterpret_cast<char*>(&array_size),sizeof(std::size_t));
for(MyClass* it = array; it != array + array_size; ++it)
{
MyClass& mc = *it;
std::size_t s = mc.s.size();
ostream.write(reinterpret_cast<char*>(&s),sizeof(std::size_t));
ostream.write(mc.s.c_str(),s.size());
}
Reading
std::ifstream istream("myclass.bin",std::ios::binary);
if (!istream) return; // error!
std::size_t array_size = 0;
istream.read(reinterpret_cast<char*>(&array_size),sizeof(std::size_t));
array = new MyClass[array_size];
for(MyClass* it = array; it != array + array_size; ++it)
{
MyClass& mc = *it;
std::size_t s;
istream.read(reinterpret_cast<char*>(&s),sizeof(std::size_t));
mc.resize(s);
istream.read(mc.s.c_str(),s.size());
}
istream.close(); // not needed as should close magically due to scope
Write an insertion operator for MyClass, like this, that writes out its members to the stream one by one. Then make a loop that walks your array, writing each member to the stream. Remember to write out the array size at some point too, so you know how many members to read when you read the file back.
And, as Klaim says, make sure you open the stream in binary mode.
What exactly do you want to write to file? In C++, you can't make assumptions about the content of an object like you can do in C. std::string for instance typically holds pointers, allocators, string lengths and/or the first few characters. It will certainly not hold the entire char[] you'd get from string::data(). If you have a std::string[3], the three sring::data() arrays will (almost certainly) be non-contiguous, so you will need three writes - each call can only write one contiguous array.
A good way of doing this would be to override the << operator for MyClass:
ostream& operator << (ostream& output, const MyClass& myClass)
{
return output << myClass.Value;
}
You can then simply serialise the strings out of MyClass directly into the file stream:
std::fstream fileStream("output", std::ios::out|std::ios::binary);
for (int i = 0; i < 3; ++i)
fstream << array[i];
Open the stream in binary mode:
std::fstream filestream( "file.name", std::ios::out | std::ios::binary );