Pass variable to PUGIXML xml_tree_walker - c++

I am using pugixml to parse a file. I have been using an xml_tree_walker and I have a variable I want to modify as the walker walks through the xml. I am currently using a global variable but don't want to. Is there a way to pass a variable to the walker by reference? If this is the case, would that mean I would need to modify the for_each function prototype in the pugixml source?
Below is the way I am currently using the walker.
struct simple_walker: pugi::xml_tree_walker
{
virtual bool for_each(pugi::xml_node& node)
{
for (int i = 0; i < depth(); ++i) std::cout << " "; // indentation
std::cout << node_types[node.type()] << ": name='" << node.name() << "', value='" << node.value() << "'\n";
some_global = node.name(); // I don't want this to be a global
return true; // continue traversal
}
};
I am calling the walker like so:
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_file(XML_FILE);
simple_walker mySimpleWalker;
doc.traverse(mySimpleWalker);

One thing you can do is keep a member reference in your walker to the object you are capturing information in. Something like:
struct captured_info // where my captured info goes
{
std::string name;
int value;
std::time_t date;
// ...
};
struct simple_walker: pugi::xml_tree_walker
{
// must supply a captured_info object to satisfy
// this constructor
simple_walker(captured_info& info): info(info) {}
virtual bool for_each(pugi::xml_node& node)
{
for (int i = 0; i < depth(); ++i) std::cout << " "; // indentation
std::cout << node_types[node.type()] << ": name='" << node.name() << "', value='" << node.value() << "'\n";
info.name = node.name();
info.value = std::stoi(node.value());
// ... etc
return true; // continue traversal
}
captured_info& info;
};
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_file(XML_FILE);
captured_info info; // the output!!!
simple_walker mySimpleWalker(info); // configure for output
doc.traverse(mySimpleWalker);
std::cout << info.name << '\n'; // etc...

Related

How to transfer object to function as it's class'es member

For example: I have class "ListNode" which is linked list member, and i overloaded a [] operator for List class itself, but every time i need to get data from a node, i need to write list[0]->getData() or if I want to set new data, I need to write list[0]->setData(*somedata*).
But I want to make it be able to work like for example like list[0] = 5, so first Node's data is setted to 6. Same with functions. What should I do if I have Node which has int data, and I need to transfer it's data to a function, but without writing Node->getData() all the time?
You can make your operator[] return a reference to the element you want to access.
The example below is a simplified version of what would be a proper solution, including a const version for the operator[].
[Demo]
#include <iostream> // cout
#include <stdexcept> // range_error
struct Node
{
int value{};
Node* next{};
int& operator[](size_t pos)
{
if (pos == 0) { return this->value; }
else if (next == nullptr) { throw std::range_error{"out of bounds"}; }
else { return (*next)[pos - 1]; }
}
};
int main()
{
Node n5{5, nullptr};
Node n4{4, &n5};
Node n3{3, &n4};
Node n2{2, &n3};
Node list{1, &n2};
try
{
std::cout << "list[3]: " << list[3] << "\n";
list[3] = 25;
std::cout << "list[3]: " << list[3] << "\n";
std::cout << "list[13]: " << list[13] << "\n";
}
catch (const std::exception& exc)
{
std::cout << "Error: " << exc.what() << ".\n";
}
}

Access map element via pointer in C++

I switched from c to c++ recently and just can't figure out what I'm doing wrong here.
I would like to access and set the member of a map via another function.
Here is my example which you can just copy to cpp.sh or so if you like
#include <iostream>
#include <map>
using namespace std;
struct test{
int i;
int j;
};
void addValues(test* val){
if (val == NULL){
val = new test();
cout<<"new";
}
val->i = 10;
val->j = 12;
}
void printVal(test* val){
cout<<"finish " << val->i << " " << val->j;
}
int main()
{
map<string, test*> bla = {{"test1",NULL}};
addValues(bla.at("test1"));
printVal(bla.at("test1"));
return 0;
}
code from my project is a little bit more complex but it's basically this problem. I created a test in addValues() and have not deleted it. Why am I not able to print this value in printVal()? What am I missing?
Thanks in advance!
Parameters are passed by value. Pointers are no exception to that. Your addValues modifies a local copy of the pointer when a nullptr is passed. Modifying that local copy does not affect the pointer in the map. Pass the pointer by reference:
void addValues(test*& val){
if (val == nullptr){
val = new test();
cout<<"new";
}
val->i = 10;
val->j = 12;
}
Or better yet, do not use raw pointers in the first place. Moreover, consider to write a constructor that initializes the members of test instead of relying on the caller to initialize them.
Example :
#include <iostream>
#include <map>
//using namespace std; NO teach yourself not to do this.
struct test
{
int i = 0; // <== in c++ you can initialize values of structs
int j = 0;
};
// this instead of printVal
std::ostream& operator<<(std::ostream& os, const test& t)
{
os << "i = " << t.i << ", j = " << t.j << "\n";
return os;
}
int main()
{
std::map<std::string, test> map =
{
{"test1",{1,1}},
{"test2",{2,2}},
};
// loop over all entries in the map
// range based for loop.
// each entry in the map is a key,value pair (not they key, not the value but a pair)
// https://en.cppreference.com/w/cpp/language/range-for
std::cout << "range based for over keyvalue pairs\n";
for (const auto& kv : map)
{
// note kv.second is where we use operator<< from earlier.
std::cout << "Key : " << kv.first << ", value : " << kv.second << "\n";
}
std::cout << "\n";
// structured bindings make code more readable
// https://en.cppreference.com/w/cpp/language/structured_binding
std::cout << "range based for using structured bindings \n";
for (const auto& [key, value] : map)
{
std::cout << "Key : " << key << ", value : " << value <<"\n";
}
std::cout << "\n";
return 0;
}

ADTF recording file format

I am coding an ADTF recording file reader in C++. I have already read the header using the structure specified here
https://support.digitalwerk.net/adtf_libraries/adtf-streaming-library/v2/DATFileFormatSpecification.pdf
typedef struct tagFileHeader {
int ui32FileId;
int ui32VersionId;
int ui32Flags;
int ui32ExtensionCount;
long long ui64ExtensionOffset;
long long ui64DataOffset;
long long ui64DataSize;
long long ui64ChunkCount;
long long ui64MaxChunkSize;
long long ui64Duration;
long long ui64FileTime;
char ui8HeaderByteOrder;
long long ui64TimeOffset;
char ui8PatchNumber;
char _reserved[54];
char strDescription[1912];
} tFileHeader; // size is 2048 Bytes
I read the heder
ifstream file("myfile.dat", std::ifstream::binary);
char buffer[2048];
file.read(buffer, 2048);
const tagFileHeader* header = reinterpret_cast<const tagFileHeader*>(buffer);
And now I need to read the chunks. This is the chunks header, extracted from the same document
typedef struct tagChunkHeader {
long long ui64TimeStamp;
int ui32RefMasterTableIndex;
int ui32OffsetToLast;
int ui32Size;
short ui16StreamId;
short ui16Flags;
long long ui64StreamIndex;
} tChunkHeader; // size is 32 Bytes
Reading the chunks
for (int c = 0; c < header->ui64ChunkCount; ++c)
{
char chunkHeaderBuffer[32];
file.read(chunkHeaderBuffer, 32);
const tChunkHeader* chunk = reinterpret_cast<const tChunkHeader*>(chunkHeaderBuffer);
//Skeep chunk data
file.seekg(chunk->ui32Size, ios_base::cur);
}
I don't know how to interpret the chunk data. Is this specified in another document that I am missing?
Thanks
For the sake of completeness:
The chunk data layout depends on the original sample data and the used serialization. So there is not one single data layout. You have to deserialize the chunk data with the correct deserialization implementation and can then interpret the deserialized data with the correct struct definition. The information about the used serialization is stored within the index extension of a stream.
As C-3PFLO has already stated, the adtf_file library does all this for you, but you need all required deserializer plugins.
Here is a example (based on upcoming ADTF File Library 0.5.0) how to access dat files and extend the reader with additional adtffileplugins. Use this read dat files which contains e.g. flexray data recorded with ADTF 2.x:
/**
* #file
* ADTF File Access example
*
* #copyright
* #verbatim
Copyright # 2017 Audi Electronics Venture GmbH. All rights reserved.
This Source Code Form is subject to the terms of the Mozilla
Public License, v. 2.0. If a copy of the MPL was not distributed
with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular file, then
You may include the notice in a location (such as a LICENSE file in a
relevant directory) where a recipient would be likely to look for such a notice.
You may add additional accurate notices of copyright ownership.
#endverbatim
*/
#include <adtf_file/standard_adtf_file_reader.h>
#include <stdio.h>
#include <iostream>
#include <sstream>
#include <map>
// initalize ADTF File and Plugin Mechanism
static adtf_file::Objects oObjects;
static adtf_file::PluginInitializer oInitializer([]
{
adtf_file::add_standard_objects();
});
void query_file_info(adtf_file::Reader& reader)
{
using namespace adtf_file;
//setup file version
uint32_t ifhd_version = reader.getFileVersion();
std::string adtf_version("ADTF 3 and higher");
if (ifhd_version < ifhd::v400::version_id)
{
adtf_version = "below ADTF 3";
}
//begin print
std::cout << std::endl << "File Header" << std::endl;
std::cout << "------------------------------------------------------------------------------" << std::endl;
std::cout << "File version : " << reader.getFileVersion() << " - " << adtf_version << std::endl;
std::cout << "Date : " << reader.getDateTime().format("%d.%m.%y - %H:%M:%S") << std::endl;
std::cout << "Duration : " << reader.getDuration().count() << std::endl;
std::cout << "Short description : " << getShortDescription(reader.getDescription()) << std::endl;
std::cout << "Long description : " << getLongDescription(reader.getDescription()) << std::endl;
std::cout << "Chunk count : " << reader.getItemCount() << std::endl;
std::cout << "Extension count : " << reader.getExtensions().size() << std::endl;
std::cout << "Stream count : " << reader.getStreams().size() << std::endl;
std::cout << std::endl << "Streams" << std::endl;
std::cout << "------------------------------------------------------------------------------" << std::endl;
auto streams = reader.getStreams();
for (const auto& current_stream : streams)
{
auto property_stream_type = std::dynamic_pointer_cast<const PropertyStreamType>(current_stream.initial_type);
if (property_stream_type)
{
std::string stream_meta_type = property_stream_type->getMetaType();
std::cout << "Stream #" << current_stream.stream_id << " : " << current_stream.name << std::endl;
std::cout << " MetaType : " << stream_meta_type << std::endl;
property_stream_type->iterateProperties(
[&](const char* name,
const char* type,
const char* value) -> void
{
std::cout << " " << name << " - " << value << std::endl;
});
}
}
}
class StreamsInfo
{
typedef std::map<uint16_t, std::chrono::microseconds> LastTimesMap;
typedef std::map<uint16_t, std::string> StreamNameMap;
public:
StreamsInfo(adtf_file::Reader& reader)
{
auto streams = reader.getStreams();
for (auto current_stream : streams)
{
_map_stream_name[current_stream.stream_id] = current_stream.name;
UpdateType(current_stream.stream_id, current_stream.initial_type);
}
}
~StreamsInfo() = default;
std::string GetDiffToLastChunkTime(const uint16_t& stream_id, const std::chrono::microseconds& current_time)
{
return GetLastTimeStamp(_map_last_chunk_time, stream_id, current_time);
}
std::string GetDiffToLastSampleStreamTime(const uint16_t& stream_id, const std::chrono::microseconds& current_time)
{
return GetLastTimeStamp(_map_last_stream_time, stream_id, current_time);
}
std::string GetStreamName(const uint16_t& stream_id)
{
return _map_stream_name[stream_id];
}
void UpdateType(const uint16_t& stream_id, const std::shared_ptr<const adtf_file::StreamType>& type)
{
auto property_stream_type = std::dynamic_pointer_cast<const adtf_file::PropertyStreamType>(type);
if (property_stream_type)
{
_map_stream_meta_type[stream_id] = property_stream_type->getMetaType();
}
}
std::string GetLastStreamMetaType(const uint16_t& stream_id)
{
return _map_stream_meta_type[stream_id];
}
private:
std::string GetLastTimeStamp(LastTimesMap& map_last_times,
const uint16_t& stream_id,
const std::chrono::microseconds& current_time)
{
std::chrono::microseconds result(-1);
LastTimesMap::iterator it = map_last_times.find(stream_id);
if (it != map_last_times.end())
{
result = current_time - it->second;
it->second = current_time;
}
else
{
if (current_time.count() != -1)
{
map_last_times[stream_id] = current_time;
}
}
if (result.count() >= 0)
{
return a_util::strings::format("%lld", result.count());
}
else
{
return "";
}
}
LastTimesMap _map_last_chunk_time;
LastTimesMap _map_last_stream_time;
StreamNameMap _map_stream_name;
StreamNameMap _map_stream_meta_type;
};
void access_file_data(adtf_file::Reader& reader, const std::string& csv_file_path)
{
using namespace adtf_file;
//load stream information
StreamsInfo stream_info(reader);
std::cout << std::endl << "File data" << std::endl;
std::cout << "------------------------------------------------------------------------------" << std::endl;
utils5ext::File csv_file;
csv_file.open(csv_file_path, utils5ext::File::om_append | utils5ext::File::om_write);
//set the labels
csv_file.writeLine("stream;stream_name;chunk_type;stream_type;chunk_time;samplestream_time;chunk_time_delta_to_lastofstream;samplestream_time_delta_to_lastofstream");
size_t item_count = 0;
for (;; ++item_count)
{
try
{
auto item = reader.getNextItem();
std::chrono::microseconds chunk_time = item.time_stamp;
std::string chunk_type;
auto type = std::dynamic_pointer_cast<const StreamType>(item.stream_item);
auto data = std::dynamic_pointer_cast<const Sample>(item.stream_item);
auto trigger = std::dynamic_pointer_cast<const Trigger>(item.stream_item);
std::chrono::microseconds sample_time(-1);
std::string sample_time_string("");
if (type)
{
//the type change is part of the
chunk_type = "stream_type";
stream_info.UpdateType(item.stream_id,
type);
}
else if (data)
{
chunk_type = "sample";
auto sample_data = std::dynamic_pointer_cast<const DefaultSample>(data);
if (sample_data)
{
sample_time = sample_data->getTimeStamp();
sample_time_string = a_util::strings::format("%lld", sample_time.count());
}
}
else if (trigger)
{
chunk_type = "trigger";
}
csv_file.writeLine(a_util::strings::format("%d;%s;%s;%s;%lld;%s;%s;%s",
static_cast<int>(item.stream_id),
stream_info.GetStreamName(item.stream_id).c_str(),
chunk_type.c_str(),
stream_info.GetLastStreamMetaType(item.stream_id).c_str(),
chunk_time.count(),
sample_time_string.c_str(),
stream_info.GetDiffToLastChunkTime(item.stream_id, chunk_time).c_str(),
stream_info.GetDiffToLastSampleStreamTime(item.stream_id, sample_time).c_str()
));
}
catch (const exceptions::EndOfFile&)
{
break;
}
}
csv_file.close();
}
adtf_file::Reader create_reader(const a_util::filesystem::Path& adtfdat_file_path)
{
//open file -> create reader from former added settings
adtf_file::Reader reader(adtfdat_file_path,
adtf_file::getFactories<adtf_file::StreamTypeDeserializers,
adtf_file::StreamTypeDeserializer>(),
adtf_file::getFactories<adtf_file::SampleDeserializerFactories,
adtf_file::SampleDeserializerFactory>(),
std::make_shared<adtf_file::sample_factory<adtf_file::DefaultSample>>(),
std::make_shared<adtf_file::stream_type_factory<adtf_file::DefaultStreamType>>());
return reader;
}
int main(int argc, char* argv[])
{
if (argc < 3 || argv[1] == NULL || argv[2] == NULL)
{
std::cerr << "usage: " << argv[0] << " <adtfdat> <csv> [<adtffileplugin> ...]" << std::endl;
return -1;
}
//set path for adtfdat|dat and csv file
a_util::filesystem::Path adtfdat_file = argv[1];
a_util::filesystem::Path csv_file = argv[2];
try
{
//verify adtf|dat file
if (("adtfdat" != adtfdat_file.getExtension())
&& ("dat" != adtfdat_file.getExtension()))
{
throw std::runtime_error(adtfdat_file + " is not valid, please use .adtfdat (ADTF 3.x) or .dat (ADTF 2.x).");
}
//verify csv file
if ("csv" != csv_file.getExtension())
{
throw std::runtime_error(csv_file + " is not valid, please use .csv for sample data export.");
}
//check for additional adtffileplugins
for (int i = 3; i < argc; i++)
{
a_util::filesystem::Path adtffileplugin = argv[i];
if ("adtffileplugin" == adtffileplugin.getExtension())
{
adtf_file::loadPlugin(adtffileplugin);
}
}
//setup reader
auto reader = create_reader(adtfdat_file);
//print information about adtfdat|dat file
query_file_info(reader);
//export sample data
access_file_data(reader, csv_file);
}
catch (const std::exception& ex)
{
std::cerr << ex.what() << std::endl;
return -2;
}
return 0;
}
Is there any reason why you try to reimplement an ADTF DAT File Reader ? It will be provided by the ADTF Streaming Library and should provide to access any data stored in a dat file. See the File Access Example (https://support.digitalwerk.net/adtf_libraries/adtf-streaming-library/v2/api/page_fileaccess.html) how to use the reader as well as the API itself and all other examples.
Hint: You can also use the successor - ADTF File Library with the same possibilities but with two more benefits: Complete Open Source to see how the (adtf)dat file handling works and also support for files created with ADTF 3.x. See https://support.digitalwerk.net/adtf_libraries/adtf-file-library/v0/html/index.html
For those interested in downloading the streaming Library, here follows the link
https://support.digitalwerk.net/projects/download-center/repository/show/adtf-libraries/adtf-streaming-library/release-2.9.0

C++ memory and design question on small project

I try to create a small library to listen for multiple mice on MAC and PC. (right now MAC)
I have started something simple that does not work ATM. Since I am a noob in C++ I wanted to ask the community for help in this matter. How should I design it in code? I wanted to use smart pointers here is my code, feedl free to download it:
Github:
Open Source Project
Everything in one file:
Device Class
class Device;
class Device {
public:
Device(){
std::cout << "###### Create Device - Empty" << std::endl;
this->x_previous = 0;
this->y_previous = 0;
this->x_current = 0;
this->y_current = 0;
}
Device( size_t _deviceID, std::string _device_name){
std::cout << "###### Create Device - 0.0/0.0" << std::endl;
this->device_id = std::make_shared<size_t>(_deviceID);
this->device_name = std::make_shared<std::string>(_device_name);
this->x_previous = 0;
this->y_previous = 0;
this->x_current = 0;
this->y_current = 0;
}
Device(size_t _deviceID, std::string _device_name, float _xStart, float _yStart){
std::cout << "###### Create Device - " << _xStart << "/" << _yStart << std::endl;
this->device_id = std::make_shared<size_t>(_deviceID);
this->device_name = std::make_shared<std::string>(_device_name);
this->x_previous = _xStart;
this->y_previous = _yStart;
this->x_current = _xStart;
this->y_current = _yStart;
}
~Device(){
std::cout << "###### Destroyed Device" << std::endl;
}
const size_t getId () const{
return (size_t)this->device_id.get();
};
const std::string getName() const{
return "Not Implementet yet"; //this->device_name.get() does not work because of std::basic_string wtf?
};
const float getDeltaX() const{
return x_previous - x_current;
};
const float getDeltaY() const{
return y_previous - y_current;
};
private:
std::shared_ptr<size_t> device_id;
std::shared_ptr<std::string> device_name;
float x_previous;
float y_previous;
float x_current;
float y_current;
};
Devices Class
class Devices{
public:
Devices(){
std::cout << "###### Created Empty Devices List" << std::endl;
this->list = std::unique_ptr<std::list<Device> >();
}
explicit Devices(std::unique_ptr<std::list<Device> > _list){
std::cout << "###### Created Moved Devices List" << std::endl;
this->list = std::move(_list);
}
~Devices(){
std::cout << "###### Destroyed Devices List" << std::endl;
}
std::unique_ptr<std::list<Device> > list;
void getDevicesArray() {
CFMutableDictionaryRef usb_dictionary;
io_iterator_t io_device_iterator;
kern_return_t assembler_kernel_return_value;
io_service_t device_id;
// set up a matching dictionary for the class
usb_dictionary = IOServiceMatching(kIOUSBDeviceClassName);
if (usb_dictionary == NULL) {
std::cout << "failed to fetch USB dictionary" << std::endl;
return; // still empty
}
// Now we have a dictionary, get an iterator.
assembler_kernel_return_value = IOServiceGetMatchingServices(kIOMasterPortDefault, usb_dictionary, &io_device_iterator);
if (assembler_kernel_return_value != KERN_SUCCESS) {
std::cout << "failed to get a kern_return" << std::endl;
return; // still empty
}
io_name_t device_name = "unkown device";
device_id = IOIteratorNext(io_device_iterator); // getting first device
while (device_id) {
device_id = IOIteratorNext(io_device_iterator); //set id type: io_service_t
IORegistryEntryGetName(device_id, device_name); //set name type: io_name_t
this->list.get()->push_back(Device(device_id, device_name));
}
//Done, release the iterator
IOObjectRelease(io_device_iterator);
}
void printDeviceIDs(){
for (auto const& device : *this->list.get()) {
std::cout << "#" << device.getId() << std::endl;
std::cout << "| name: " << "\t" << device.getName() << std::endl;
std::cout << "#-----------------------------------------------#" << std::endl;
}
}
};
main
int main(int argc, const char *argv[])
{
std::shared_ptr<Devices> devices;
devices->printDeviceIDs();
devices->getDevicesArray();
devices->printDeviceIDs();
}
Someone knows of a good pattern for that?
Also maybe I use smart pointers completely wrong?
Also the iOKit library is from 1985 or something so it is not very descriptive...
Thanks in advance.
As mentioned by other users this is more of a review rather than a error code question;
being that said the only thing I can find is the following:
std::unique_ptr<std::list<Device> > list;
you should change that to the following:
std::list<Device> list;
and on your main
int main(int argc, const char *argv[])
{
std::shared_ptr<Devices> devices;
devices->printDeviceIDs();
devices->getDevicesArray();
devices->printDeviceIDs();
}
should probably only suffice to use:
Devices devices; devices.printDeviceIDs();

Concept of data storing in c++

I have a Spieler class and a Verein class with a vector of Spieler members.
Now if I change something of the Players like the Staerke(german for strength) by using a function of this class in the player class it does not automatically change the value for this player.
Here is the code:
#include <vector>
#include<iostream>
#include <string>
using namespace std;
class Spieler
{
public:
void setinformation(int a, string b, string c, int d)
{
ID = a;
Vorname = b;
Nachname = c;
Staerke = d;
}
void getinformation()
{
cout << "ID: " << ID << endl;
cout << "Vorname: " << Vorname << endl;
cout << "Nachname: " << Nachname << endl;
cout << "Staerke: " << Staerke << endl << endl;
}
void setStaerke(int x)
{
Staerke = x;
}
int getStaerke()
{
return Staerke;
}
private:
string Vorname, Nachname;
int Staerke, ID;
};
class Verein
{
public:
void setSpielerListe(vector<Spieler> x)
{
Spielerliste = x;
}
vector<Spieler> getSpielerListe()
{
return Spielerliste;
}
string getVereinsName()
{
return VereinsName;
}
int getVereinsID() const
{
return VereinsID;
}
void setVereinsID(int x)
{
VereinsID = x;
}
int getGesamtstaerke()
{
Gesamtstaerke = 0;
vector<Spieler> b;
b = getSpielerListe();
for (size_t i = 0; i < b.size(); i++)
{
Gesamtstaerke = Gesamtstaerke + b[i].getStaerke();
}
return Gesamtstaerke;
}
void Vereinsinformationen()
{
vector<Spieler> list;
int id;
string vereinsname;
int gesamtstaerke;
id = getVereinsID();
vereinsname = getVereinsName();
gesamtstaerke = getGesamtstaerke();
list = getSpielerListe();
cout << "VereinsID: " << id << endl;
cout << "Vereinsname: " << vereinsname << endl;
cout << "Gesamstaerke: " << gesamtstaerke << endl << endl;
cout << "Spieler: " << endl;
for (size_t i = 0; i < list.size(); i++)
list[i].getinformation();
}
private:
vector<Spieler> Spielerliste;
int VereinsID, Gesamtstaerke;
string VereinsName;
};
vector<Spieler> spieler;
int main()
{
Spieler Spieler1;
Spieler1.setinformation(0, "Peter", "Pan", 10);
spieler.emplace_back(Spieler1);
Verein Team1;
Team1.setSpielerListe(spieler);
Spieler1.setStaerke(20);
Team1.Vereinsinformationen();
cin.get();
return 0;
}
I'm really new into c++ and programming so the code might be terrible.
Guess it has to do with pointers, I'm really not into the concept of storing data in c++, try to get it by trial & error; So how to change the Staerke in a way that it is changed in the Teams Playerlist too?
The problem is you are storing full object in the vector and not pointers. When you run this line:
spieler.emplace_back(Spieler1);
a copy of Spieler1 is made and put in the vector. So modifying it in the main will have no effect in the vector. Also not that you are copying the vector when setting in Verein class.
You should use pointer if this is what you are after or better yet have a function to modify strength from Verein class taking its id and new strength as parameters might be a good idea. Something like this:
void setStaerke(int id, int x)
{
vector<Spieler>::iterator it = Spielerliste.begin();
while (it != Spielerliste.end())
{
if ((*it).GetId() == id)
{
(*it).setStaerke(x);
break;
}
}
}
If you have access to C++11, it could be made more elegantly.
Hereby you pass and store a copy from the vector into the object:
Team1.setSpielerListe(spieler);
Therefore changes to the original vector and the contained objects will not affect the member.
Further, I don't have much experience with emplace_back, but the more usual way to append an object to a std::vector would also append a copy:
spieler.push_back(Spieler1);
Therefore changes to the original object would not affect the object you've appended to the container.
Make sure you better understand when objects are copied.
For reference:
http://en.cppreference.com/w/cpp/container/vector/emplace_back
http://en.cppreference.com/w/cpp/container/vector/push_back
How to pass objects to functions in C++?