I have defined struct with 3 UnicodeString values, so I can create struct variable like this:
someStruct x = {"value1","value2","value3"};
But what I want to do is a DynamicArray of my struct type and I want to add elements to this array without creating them earlier, but assigning struct values the same moment I add an array element.
I tried to do it this way
DynamicArray<someStruct> arrayOfSomeStruct;
arrayOfSomeStruct.Length = 1;
arrayOfSomeStruct[0] = {"value1","value2","value3"};
But it do not work this way. Would you help me with this?
EDIT:
I have found the solution that works but I'm not fully happy with it:
arrayOfSomeStruct[0].atr1 = "value";
arrayOfSomeStruct[0].atr2 = "value";
arrayOfSomeStruct[0].atr3 = "value";
Try to use vectors from the standard library
Vectors are sequence containers representing arrays that can change in size.
You can try the following code :
#include <iostream>
#include <vector>
#include <string>
using namespace std;
struct SomeStruct{
string str1;
string str2;
string str3;
};
int main()
{
vector< SomeStruct > someStructVector; //Create a vector of SomeStruct
someStructVector.push_back( {"str1 ", "str2 ", "str3"} ); //adds {"str1 ", "str2 ", "str3"} to the vector
for( auto ss : someStructVector )//Access the elements of the vector
cout << ss.str1 << ss.str2 << ss.str3 << endl;
return 0;
}
Related
The following code causes a segfault when I try to issue my push_back call. What am I doing wrong?
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main() {
std::string * foo = new std::string("hello world");
cout << *foo << endl;
std::vector<std::vector<std::string *> > my_vecs;
my_vecs[0].push_back(foo); // segfaults
cout << "trying to print my_vecs size of " << my_vecs.size() << " but we never reach that point due to segfault " << endl;
return 0;
}
I'm pretty sure I'm violating one of the contracts for using vector, as the problem is surely not with the STL implementation.
When you create my_vecs it has 0 elements, hence my_vecs[0] does not exists and gives segfault. You have to first reserve at least one element of my_vecs and then you can insert in the vector my_vecs[0] your pointer:
std::vector<std::vector<std::string *> > my_vecs(1);
my_vecs[0].push_back(&foo);
The outer vector must first be explicitly grown, before one can push to its elements.
This may be a little surprising since STL map's automatically insert their keys. But, it's certainly the way it is.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main() {
const int DESIRED_VECTOR_SIZE = 1;
std::string * foo = new std::string("hello world");
cout << *foo << endl;
std::vector<std::vector<std::string *> > my_vecs;
for (int i = 0; i < DESIRED_VECTOR_SIZE; ++i) {
std::vector<std::string *> tmp;
my_vecs.push_back(tmp); // will invoke copy constructor, which seems unfortunate but meh
}
my_vecs[0].push_back(foo); // segfaults
cout << "now able to print my_vecs size of " << my_vecs.size() << endl;
return 0;
}
I'm don't get this to work. I want to initialize the following structure for later use.
map<pair<string,string>, map<string,vector<fs::path>>> filelist;
Thats means I provide the string pair for the first map. (e.g., "id1","id2") with an empty second map that I can fill in later. So I want to do something like this:
filelist.insert(
pair<pair<string,string>, pair<string,vector<fs::path>>>
(make_pair("id1","id2), **empty map??**));
Obviously when when I stick to the vector instead of the nested map I can do this:
filelist.insert(pair<pair<string, string>, vector<vector<fs::path>>>
(make_pair("id1","id2"),{}) );
But how can I initialize an empty map? Or is there an alternative data structure? Thanks
I want to initialize the following structure for later use.
map<pair<string,string>, map<string,vector<fs::path>>> filelist;
You can use operator[] to assign it.
Some thing like follows.
filelist[ std::make_pair("string1", "string2") ] = value();
where, using value = std::map< std::string, std::vector<int>>;
See live action: https://www.ideone.com/lxQir7
is there an alternative data structure?
A suggestion to reduce the complexity of your chosen data-structure is possible, only when you explain your problem and data manipulation requirements more in detail.
#include <iostream>
#include <map>
#include <string>
#include <vector>
using key = std::pair< std::string, std::string>;
using value = std::map< std::string, std::vector<int>>;
int main ()
{
std::map< key , value > filelist;
value vMap;
vMap["string"] = {1,2,3,4};
filelist[ std::make_pair("string1", "string2") ] = vMap;
// to print or access
for(auto& key_itr: filelist)
{
std::cout<< "KEY: " << key_itr.first.first << " " << key_itr.first.second << "\t VALUE: ";
for(auto& val_itr: key_itr.second)
{
std::cout << val_itr.first << " ";
for(const auto& vec: val_itr.second) std::cout << vec << " ";
}
std::cout << std::endl;
}
return 0;
}
You can initialize an empty map, simply by its default constructor.
It is always a better idea to name your newly introduced data types.
After all, it's a relatively complex data structure. Why don't you simplify your problem?
#include <map>
#include <vector>
#include <filesystem>
using namespace std;
using namespace std::filesystem;
using string_to_vector_of_path_map = map<string, vector<path>>;
using pair_of_strings = pair<string, string>;
using my_map = map<pair_of_strings, string_to_vector_of_path_map>;
my_map filelist;
int main()
{
filelist.insert(make_pair(make_pair("id1", "id2"), string_to_vector_of_path_map()));
return 0;
}
I want to make a program that will store the data from the Periodic Table of Elements into an array that I can access whenever I want. I want to do it by making a struct with the data for each element in it, and make an instance of that struct for each element in an array "periodicTable[119]"
Here is my code:
#include <iostream>
using namespace std;
struct element
{
string symbol;
string name;
float atomicWeight;
};
element periodicTable[119];
periodicTable[1].symbol = "H";
periodicTable[1].name = "Hydrogen";
periodicTable[1].atomicWeight = 1.008;
int main()
{
cout << periodicTable[1].symbol << periodicTable[1].name << periodicTable[1].atomicWeight << endl;
return 0;
}
I run linux, and when I try to compile this I get this error: 'error: periodicTable does not have a type'
I would like to know how to make an array of structs correctly, and if anyone has a better way to make a program like this or see any other errors by all means let me know.
You cannot use assignments (or any other statements, for that matter) outside of functions. Use initializers instead:
element periodicTable[119] = {
{"H", "Hydrogen", 1.008}
, {"He", "Helium", 4.003}
, ...
};
Also note that C++ arrays are indexed starting from zero, not from one, so the initial element of the array is periodicTable[0], not periodicTable[1].
Using global variables is not a good idea except that you have a strong reason. So normally you can do as below:
int main()
{
element periodicTable[119];
periodicTable[1].symbol = "H";
periodicTable[1].name = "Hydrogen";
periodicTable[1].atomicWeight = 1.008;
cout << periodicTable[1].symbol << periodicTable[1].name << periodicTable[1].atomicWeight << endl;
return 0;
}
If you really want to use the global variable, you can do like this:
#include <iostream>
using namespace std;
struct element
{
string symbol;
string name;
float atomicWeight;
};
element periodicTable[119]{
{},
{"H", "Hydrogen", 1.008f}, // 1.008 is double, 1.008f is float
};
int main()
{
cout << periodicTable[1].symbol << periodicTable[1].name << periodicTable[1].atomicWeight << endl;
return 0;
}
I have a string array of size 5, and I have n elements in it. How could I determine n? I have tried sizeof(array)/sizeof(array[0]), but that returns the size of the array, which is 5. My code is:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string array[5];
array[0] = "pie";
array[1] = ":P";
array[2] = "YELLOW";
cout << sizeof(array)/sizeof(array[0]);
}
I have a string array of size 5, and I have n elements in it. How could I determine n?
n is 5. Your array has 5 elements, because you declared it to be an array of 5 strings. array[3] and array[4] are just empty strings (""), but they're still there, and completely valid elements.
If you want to count how many non-empty strings your array has, you could use e.g. std::count_if with a lambda:
int numberOfNonEmptyStrings = count_if(begin(array), end(array),
[](string const& s) { return !s.empty(); });
or a handmade loop:
int numberOfNonEmptyStrings = 0;
for (auto const& s : array)
if (!s.empty())
++numberOfNonEmptyStrings;
A built-in array, called a raw array, has no support for a dynamic length. It has a fixed length. For a declared array that fixed length can be found in many ways, including the not-very-safe C idiom you used.
std::vector<Itemtype> from the standard library (header <vector>), manages a raw array plus a dynamic length. And that's apparently exactly what you need. The internal array, called the vector “buffer”, is automatically replaced with a larger one as needed, so you do not even have to specify the capacity up front – you can just add items to the vector.
Adding items to a vector is usually done via a method called push_back, and finding the current number of items, the length, is usually done via the size method, like this:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
vector<string> a;
a.push_back( "pie" );
a.push_back( ":P" );
a.push_back( "YELLOW" );
cout << a.size() << endl;
}
But since std::vector supports initialization via a brace initialization list, you do not have to use push_back for known initial items:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
vector<string> a = { "pie", ":P", "YELLOW" };
cout << a.size() << endl;
}
A final refinement is to use const if it's not intended for that vector to change. This makes it easier to reason about the code. With const you see up front that none of all that code below will be changing this vector, so you can be sure of what values it provides at any point:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
vector<string> const a = { "pie", ":P", "YELLOW" };
cout << a.size() << endl;
}
Disclaimer: code not touched by compiler's dirty hands.
Where you really want a fixed size array, you should preferably use std::array<Itemtype>. It works well with a range-based loop. And it has a size method, like vectors, so you can do things like this:
#include <algorithm> // std::count
#include <iostream>
#include <string> // std::string
#include <array> // std::array
using namespace std;
int main()
{
array<string, 5> const a = { "pie", ":P", "YELLOW" };
cout << "Fixed size: " << a.size() << endl;
int const n_empty = count( begin( a ), end( a ), "" );
cout << "Non-empty strings: " << a.size() - n_empty << endl;
}
You need to make a variable which holds the value of how many strings you have stored so far, and update that variable when you store a string.
Alternatively you could use a standard container instead of a C-style array:
#include <vector>
// ... in main
vector<string> array;
array.push_back("pie");
array.push_back(":P");
array.push_back("YELLOW");
cout << array.size() << '\n';
Standard class std::string has methods size and length that return the number of characters in a string.
For example relative to your code snippet
array[0] = "pie";
array[1] = ":P";
array[2] = "YELLOW";
array[0].size() will return 3,
array[1].size() will return 2,
array[2],size() will return 6
I am reading from a file and take the words as tokens with strtok. I am trying to store the words in a map structure. I don't really know how to insert the tokens in the map.
My code so far:
#include <iostream>
#include <string.h>
#include <fstream>
#include <map>
using namespace std;
//std::map <string, int> grade_list;
int main()
{
std::map <string, int> grade_list;
char text[100];
int nr=0, i=1;
char *ptr;
ifstream myfile("ana.txt");
if(!myfile.is_open())
cout << "Could not open file" << endl;
else
{
myfile.get(text, 100);
ptr = strtok(text, " ,.-?!");
while(ptr != NULL)
{
nr++;
cout << ptr << endl;
ptr = strtok(NULL, " ,.-?!");
grade_list.insert(ptr);
i++;
}
}
cout << "\nAveti " << nr << " cuvinte." << endl;
return 0;
}
std::map is an associative container, provides Key -> Value relationship. In your case it is std::string -> int. So, you should specify Value while inserting too:
grade_list[ptr] = nr;
Also, instead of char array and using strtok I suggest use std::string and boost::algorithm::split, or boost::tokenizer.
I want to see for each word in the file how manny times it appears in the text.
So, you have to change Value type in map to std::size_t(since you din't need to negative values):
std::map <string, std::size_t> grade_list;
And just write:
++grade_list[ptr];
You should probably look at the std::map::insert definition, the value_type parameter is a std::pair< std::string, int > so you should probably write the insert statement as:
grade_list.insert(std::pair< std::string, int >(std::string(ptr), 1));
This will add an entry into the map with the key "token" and the value 1.
What you probably want is more like add an entry if it does not exist or increment the value :
this can be achieved by writing something like
if (grade_list.find(ptr) == grade_list.end())
{
// insert new entry
grade_list.insert(std::pair< std::string, int >(std::string(ptr), 1)); // can be written as grade_list[ptr] = 1;
}
else
{
// increment token
grade_list[ptr] += 1; // can be written as grade_list[ptr]++;
}