Vector in c++ using for loop - c++

I am new to c++ in general. So I have been trying to learn about using vectors after someone recently helped with using an Arduino type project to read RFID tags. It really got me thinking I have no clue how to program. So I hit the books!
So here is the question: When I do the following code:
#include <iostream>
#include <vector>
struct Runner{
char runnerTag[32];
uint32_t ts;
};
std::vector<Runner > runners;
int main() {
std::cout << "Hello, Runners!\n";
for (int i = 0; i < 100; i++) {
std::string runnertg = "testTrackTag01";
uint32_t timeStamp = rand() % 100 + 1;
runners[i] = new Runner({runnertg, timeStamp});
}
return 0;
}
I get this annoying little message from xcode:
No matching constructor for initialization of 'Runner'
on line 16 of the above snippet. What in the world am I doing wrong?

The expression new Runner({runnertg, timeStamp}) has a type mismatch. runnertg is of type std::string, while the element Runner::runnerTag is of type char[32].
The expression runners[i] = new Runner({runnertg, timeStamp}); has another type mismatch. The element type of runners is Runner, while the expression new Runner({runnertg, timeStamp}) is of type Runner*.
runners[i] is out-of-bound access. The size of runners is 0. The elements runners[i] for all values of i does not exist.
There is memory leak since there is no matching delete for each new for all code path.
Don't use rand().

A lot of the code you're using is old style C with some C++ STL code mixed in. I will try and tackle a few issues one at at time.
struct is an abstract data type used (in general) to organise primitive data types. While the only difference between a struct and a class is that the latter defaults all members to private and in this case is not functional, it's a good to cut these things of at the pass.
Secondly, an array of chars is cumbersome, messy and prone to error. Try an std::string instead.
Finally, let's create a constructor taking our two parameters.
Thus:
#include <string>
class Runner {
public:
std::string runnerTag;
uint32_t ts;
Runner(std::string, uint32_t);
};
Next thing. Using an array index operator [] to access or modify an std::vector is dangerous and defeats the purpose of using a container and all the wonderful functionality that comes along with it.
Since you know for loops, let's try this:
for (int i = 0; i < 100; i++) {
std::string runnertg = "testTrackTag01";
uint32_t timeStamp = rand() % 100 + 1;
Runner Runner(runnertg, timeStamp);
runners.push_back(Runner);
}
At the end of your code, outside the scope of the main function, define the constructor as follows:
Runner::Runner(std::string rt, uint32_t ts) {
runnerTag = rt;
ts = ts;
}
This should get you started.

You cannot convert std::string to a char array like that. Change the type of the member variable runnerTag to std::string. Also, you are accessing vector elements that don't exist. Use resize to create them. Or better yet, use emplace_back to do both at once. Also, don't use int to iterate containers, but std::size_t. Also, don't use rand(), but the classes from the <random> header. That trick using % creates a non-uniform distribution.

Related

Increment by variable names for a memory address

This may be a very simple answer, I am not sure. I have to give the address of a variable to read in some values in root. I need different variable names because I want to compare them later. Is there a way to all in one step read them into correctly named variables (typed double) that are incrementally named (Detector_P0, Detector_P1, etc.). This is what I have so far: (I have it working for the branchName, but not the &variableName in SetBranchAddress()). Any advice would be greatly appreciated!!!
for (int i = 0; i < nb_det; i++) {
std::string branchVarName = "Detector_P" + std::string(to_string(i));
const char * branchVarNameC;
branchVarNameC = branchVarName.c_str();
All->SetBranchAddress(branchVarNameC,&???);
}
Your best option is to use an array or array like object, such as std::vector or std::array.
If the size of the array is known compile time, prefer to use std::array<double, SIZE>.
If the size of the array is known only at run time, use std::vector<double>.
Example using std::vector:
std::vector<double> data(nb_det);
for (int i = 0; i < nb_det; i++)
{
std::string branchVarName = "Detector_P" + std::string(to_string(i));
const char * branchVarNameC = branchVarName.c_str();
All->SetBranchAddress(branchVarNameC, &(data[i]));
}
Yes, with each Detector_P$ variable there are approximately like 5000 numbers associated with each. When I run this file I do know right away how many there Detector_P variables there will need to be. So I would like to somehow create an array for each or at the very list something I can increment over to compare certain indices
It seems like you need a std::map<std::string, std::vector<double>> to hold the data.
std::map<std::string, std::vector<double>> allDetectorData;
for (int i = 0; i < nb_det; i++)
{
std::string branchVarName = "Detector_P" + std::string(to_string(i));
const char * branchVarNameC = branchVarName.c_str();
All->SetBranchAddress(branchVarNameC, allDetectorData[branchVarName]);
}
That allows you to read as many or as few doubles corresponding to a detector and store them in allDetectorData[branchVarName].
However, what concerns me most is how much of this makes sense to you. It will be worth your while to spend time understanding the container class templates in the standard library really well before venturing into using them in your application. I recommend learning about them from a good textbook.

Can't make arrays with unspecified length

Basically I am trying to make an array which will get larger every time the user enters a value. Which means I never know how long the array will be. I don't know if this is something to do with my class or anything.
#pragma once
#include <iostream>
#include <string>
#define dexport __declspec(dllexport)
//Im making an DLL
using namespace std;
class dexport API {
private:
string users[] = {"CatMan","ManCat"}; //Line With Error Incomplete Type Is Not Allowed
public:
string getAllUsers(string list[]) {
for (unsigned int a = 0; a < sizeof(list) / sizeof(list[0]); a = a + 1) {
return list[a];
}
}
};
It gives me an error Incomplete type is not allowed. I really have no idea what to do.
Compiler Error
There are a few things wrong with your code. For starters, an array has a fixed size, so, even if your code did compile, it wouldn't work. Normally, the compiler would infer the size of your array from the length of the initializer; but you are creating a class, and it needs to know it, hence the error.
This will solve your compilation problem:
string users[2] = {"CatMan","ManCat"};
But then your array has a fixed size, and that is not what you want, so you need an std::vector:
#include <vector>
[...]
vector<string>users = {"CatMan","ManCat"};
Now you can use the '[]' operator to access the strings, and users.push_back to add new users.
The next problem you need to solve is the way you are trying to return your value: you shouldn't use an argument as an out value (although you can, with either a reference or a pointer). You should decide whether you want to return a reference to your vector, a copy of your vector, or a const reference, for example:
// Returning a copy
vector<string> getAllUsers() {
return users;
}
// Returning a reference
vector<string>& getAllUsers() {
return users;
}
Finally, you are creating a library: you should know that if you want to share memory between different processes, you need to use some kind of shared memory. Currently, every program will keep its own copy of the API.
What you are looking for is an std::vector.
You can find more info here.
It's somewhat similar to an array, except that it allows variable length.
You can use std::vector. It allocate and copy elements to new place if it got out space.
If you wanna make the class yourself for educational reason here is what you should try as a basic solution:
You allocate some memory up front and store its length as capacity. You need a variable(size) to store the number of elements already entered to the class e.g. via a push_back function. Once the size reached capacity, you need to reallocate memory copy over all the elements and then delete the old memory.

Using arrays and structures within functions in c++

I am trying to create a program that randomly generates the position of "ships". I'd like a structure to keep track of multiple aspects of the ships including their positions and an array to keep track of multiple ships.
The error I'm getting seems to be occurring in the first for loop within "main" at the line fleet[i] = ship_position (fleet[i], i); The error reads:
error: cannot convert 'ship_stats' to 'ship_stats*' for argument '1' to 'ship_stats ship_position(ship_stats*, int)'
Also, previously, I did not think the second "i" within the brackets of that line was necessary, but when I tried compiling without it the error I received was:
error: expected primary-expression before ']' token
#include <string>
#include <cstdlib>
#include <ctime>
using namespace std;
int rand_range (int low, int high) {
return rand() % (high - low + 1) + low;
}
struct ship_stats {
int x_coordinate;
int y_coordinate;
int weapon_power;
};
ship_stats fleet[5]; // Create fleet of 5 ships linked to the structure
ship_stats ship_position (ship_stats fleet[], int ship_num) {
//Randomly generate a starting position for each ship
int low_x = 0; //Set max and min ranges for ship position
int high_x = 1024;
int low_y = 0;
int high_y = 768;
fleet[ship_num].x_coordinate = rand_range (low_x, high_x);
fleet[ship_num].y_coordinate = rand_range (low_y, high_y);
return fleet[ship_num];
}
int main () {
int num_ships = 5;
for (int i = 0; i < num_ships; i++)
fleet[i] = ship_position (fleet[i], i); // <-- error is here
}
The mechanical point you have been given is that if you want to pass "raw" arrays as parameters in C++ (or C), you can't say fleet[]. That will not compile, as you noted. But don't just put a random index value in the brackets--that gets you an array element, not the array itself.
It's a somewhat gross oversimplification to say you pass the "whole raw array" just by saying fleet. You're really passing the address of the first element, e.g. fleet ends up being equivalent to &fleet[0]. Crude though that is, it comes from C's heritage...and it means that if the function you're calling knows the size of the "raw" array, then that address can be meaningfully used as a means of accessing any subsequent value in it.
But in "idiomatic" C++, one rarely wants to use a "raw" C-style array. The std::vector solves several weak points of raw arrays, and is a good choice for beginners.
You can choose to pass vectors "by value" (which makes a copy) or "by reference" (which is a bit like passing by pointer, the only choice for a raw array). Vectors don't have to know their size in advance, and their size can change over the course of your program. Not only that, the size comes along with the vector when it's passed as a parameter. And very importantly, vectors speak an abstract "collection protocol", which means they're usable with #include <algorithm>.
But there are several other points. You have made a ship_position() function that "constructs" a ship. This oddly shaped function returns a value (the instance of a constructed ship), yet also mutates your "fleet" so that the ship is in that position. Why would you need to return the value and assign it to the location in the fleet...if that mutation of the fleet was already part of the function?
And in C++, the best mechanism for "constructing" something is...a constructor. ship_position() is what we would call a "free function"--it doesn't live within ship_stat's definition, yet it seems to have an eerie knowledge of how to manipulate ships.
(Supporting Note: Where does weapon_power fit into all this? Whose job is it to initialize it, or not? This is where a single point of responsibility of a "constructor" comes into place, to say that a constructed ship has all its fields covered.)
If this is to be a proper C++ program, you shouldn't think of ship_stats as a struct that is operated on by "free functions". Instead, you need to think of Ship as a class with some data, and some code. The randomization of a ship should be inside your class... the act of putting a random ship into a collection should be using push_back into a vector (or emplace_back, but that's very much skipping ahead).
Try not to use raw C arrays in C++ programs unless you really know what you're doing. (Or don't use C++ features and instead tag your question C, the answers will be very different.)
Like already stated in the comments you are trying to pass one ship_stats to function thats waiting for an array of them , so for the function to work it should look like this
ship_stats ship_position (ship_stats fleet, int ship_num) {
//Randomly generate a starting position for each ship
int low_x = 0; //Set max and min ranges for ship position
int high_x = 1024;
int low_y = 0;
int high_y = 768;
fleet.x_coordinate = rand_range (low_x, high_x);
fleet.y_coordinate = rand_range (low_y, high_y);
return fleet;
}
Try
#include <string>
#include <cstdlib>
#include <ctime>
#include <iostream>
using namespace std;
int rand_range(int low, int high) {
return rand() % (high - low + 1) + low;
}
struct ship_stats {
int x_coordinate;
int y_coordinate;
int weapon_power;
};
ship_stats fleet[5]; // Create fleet of 5 ships linked to the structure
ship_stats ship_position(ship_stats IndividualShip, int ship_num) {
//Randomly generate a starting position for each ship
int low_x = 0; //Set max and min ranges for ship position
int high_x = 1024;
int low_y = 0;
int high_y = 768;
IndividualShip.x_coordinate = rand_range(low_x, high_x);
IndividualShip.y_coordinate = rand_range(low_y, high_y);
return IndividualShip;
}
int main() {
int num_ships = 5;
for (int i = 0; i < num_ships; i++) {
fleet[i] = ship_position(fleet[i], i); // <-- error is here
}
}
In the above code, I've changed the function parameters of ship_position to accept an individual ship rather than the array as a whole. Your code should compile. Also, if this is C++ rather than C, consider using the for loop
for (ship_stats& j : fleet)
std::cout << j.x_coordinate << " " << j.y_coordinate << endl;
to output the results of your program, using < iostream > of course.

Creating a C++ array that can be several types

I have a function that returns a void*. Right now, when this function is completed, a UINT16* array is returned as the void*. The UINT16 array is created at the start of the method, but now I need a way to determine the type of array and create that type instead. For example, some data processing occurs and determines that an array of type int should be created, so an int array is created and returned. Other types like double and byte can also be created.
How do I go about achieving this?
My current code has
UINT16* data_out = new UINT16[arraySize];
I know I can create a large if/else or switch statement, but I'm wondering if there is a better way.
Something like that perhaps ?
This will not work, but thanks for the upvote. In fact it could work, but you'll have to know the type returned by Foo to be able to use it. But the type is determined inside Foo, that's a serious conception drawback. You should rethink the way you want this to work.
enum class ArrayType
{
Int,
Double
};
template <typename T>
T* CreateArray(size_t size)
{
T* t = new T[size];
return t;
}
void* Foo(param1, param2, etc..)
{
size_t size;
ArrayType type;
.. Do things to determine the type
switch(type)
{
case ArrayType::Int:
return CreateArray<int>(size);
case ArrayType::Double:
return CreateArray<double>(size);
default:
return 0;
}
return 0;
}
Uhm... sorry if this is more of a question than a comment... :| I can't comment rn.
If you want a core solution, you could create a linked list class that has different type outlets. Basically, instead of having just an UINT_64* next;, you would have:
int* nextInt;
double* nextDouble;
And so on and so forth. Then, if you want to tag a double along, you could just use the nextDouble outlet. To find which outlet to go to, just check if the int is pointing to anything; if not, go next. I know this seems like a REALLY annoying and bulky option, but I suppose it does the job.
I'm not sure why you have to use a practically untyped return value using void*, but let's suppose that there are reasons for it.
There are actually two issues, namely creating the array and using it then.
When creating an array of different types based on some logic, you somehow have to deal with if or switch(); how else would you express the logic determining the desired result type? But, if you like, you could also use something like result = malloc(nrOfItems*sizeOfItem), and determine sizeOfItem on any logic you like, even based on arithmetic calculations.
The more interesting or critical thing is how the caller shall use the result of the respective function, as accessing the elements of an array requires knowledge about the type or the size of the elements in it.
Suppose, for example, the following code:
void* getSomeItems() {
if (std::rand() > 100000)
return new char[200];
else
return new double[200];
}
int main() {
void* someItems = getSomeItems();
double c = ((double*)someItems)[199]; // Critical!
// how shall we know if element type is double?
// if rand() decided to create items of type char,
// this code accesses non allocated memory
...
So, unless your function can give back the information on which type has been created (and actually also the size of the array), the return value is almost needless.
I'd suggest not to use void* for this. If you know the type before calling the function, you could use templates, vectors, or other things. If you do not know type and/or size before calling, return a structure that - besides the allocated array - also provides type/size information.
BTW: do not forget to delete[] / free the result at the end.
Void * functions can be fun and do some very interesting things... (Sorry for linking a previous answer of mine, but it's the first example which came to me.) But they aren't safe, and have zero type checking...
So in your case, you only need a simple template function, and the auto keyword. Something like:
#include <iostream>
#include <iomanip>
template <typename T>
T * returnAnArray (int size) {
T * data_out = new T[size];
return data_out;
}
int main() {
int size = 3;
auto array = returnAnArray<double>(3);
for(int i=0;i<size;++i)
array[i] = 0;
for(int i=0;i<size;++i){
std::cout << std::setprecision(2);
std::cout << array[i] << std::endl;
}
delete [] array;
return 0;
}
I did have some fun, and did create a void * function:
template <typename T>
void * returnVoidPointerToArray(int size) {
return new T[size];
}
The function, when used, must be cast for it could return something:
auto chArray = (char*)returnVoidPointerToArray<char>(size);
But the output looks like:
5.00
5.00
5.00
ggg
ggg
ggg
Program ended with exit code: 0
Note how double are a single value, but the same function also initialized a 2d array of characters... Cool, right? Albeit, it's a dirtier, different way of templating functions.
And, like the commenter said, probably a good idea to use unique pointers. :)
And like the other commenter said, I cast the array to char* and got a char* array. :)

How to copy a structure with pointers to data inside?

I am using the CUDD package for BDDs manipulation.
I want to make a copy for a big data structure in it that is called the DdManager.
The problem is : this data structure has so many pointers inside it , so when I make a direct copy it is a "shallow" copy(as some use the term) i.e. : the pointers in the new copy point to the same places pointed to by the original copy , so when I change in anyone of them I also change in the other which is undesirable ....
Trying to make a copy function by hand is not feasible because the data structure is really big and very detailed with many pointer to other complex structures also !!!
I have tried the vector solutions described here but I did not get the expected result because there are many nested structures and pointers and I want a completely new copy.
Here is a code sample of what I want to do :
#include <iostream>
#include <cstdlib>
#include <string.h>
#include <vector>
using namespace std;
struct n1
{
int a;
char *b;
};
struct n2
{
int **c;
struct n1 *xyz;
};
typedef struct
{
vector<struct n2> x;
}X;
int main()
{
struct n2 s1;
s1.xyz = (struct n1*)malloc(sizeof(struct n1));
s1.xyz->a = 3;
s1.xyz->b = (char*)malloc(5);
s1.xyz->b[0] = '\0';
strcat(s1.xyz->b,"Mina");
s1.c = (int**)malloc(5 * sizeof(int*));
for(int i = 0; i < 5; i++)
s1.c[i] = (int*)malloc(5 * sizeof(int));
for(int i = 0; i < 5; i++)
for(int j = 0 ; j < 5 ; j++)
s1.c[i][j] = i + j;
X struct1,struct2;
vector<struct n2>::iterator it;
it = struct1.x.begin();
it = struct1.x.insert(it,s1);
it = struct2.x.begin();
it = struct2.x.insert(it,struct1.x[0]);
cout<<"struct2.x[0].c[1][2] = "<<struct2.x[0].c[1][2] <<" !"<<endl; // This is equal to 3
(struct2.x[0].c[1][2])++; //Now it becomes 4
cout<<"struct2.x[0].c[1][2] = "<<struct2.x[0].c[2][2] <<" !"<<endl; //This will print 4
cout<<"s1.c[1][2] "<< s1.c[1][2]<<" !"<<endl; // This will also print 4 ... that's the wrong thing
return 0;
}
Despite other saying that you have to
make a copy function by hand
...to solve this, I think that's the wrong approach for you. Here's why, and here's a suggestion.
You're trying to create a copy of a CUDD ddManager object, which is an integral part of the complex CUDD library. CUDD internally uses reference counts for some objects (which might help you here...) but the ddManager object effectively represents an entire instance of the library, and I've no ideas how the reference counts would work across instances.
The CUDD library and it's associated C++ wrapper doesn't seem to provide the necessary copy constructors for creating separate copies of the ddManager, and to add these would probably involve serious effort, and detailed internal knowledge of a library that you are just trying to use as a client. While it's possible to do this, it's complex thing to do.
Instead, I'd look at trying to write out the current BDD to a file/stream/whatever, and then read it back into a new instance of a ddManager. There's a library called dddmp that should help you with this.
I'd also recommend that the C++ wrapper was modified to make the ddManager class non-copyable.
"Trying to make a copy function by hand is not feasible because the data structure is really big and very detailed with many pointer to other complex structures also !!! "
This is exactly what you have to do.
The objective approach means that you don't write one big do-it-all copy method. Instead, every object (structure) copies only itself, and then call it's sub-object copy methods, etc, etc until there is nothing more left to copy.
There is no such thing as "vector solution", vector is simply the smallest object with it's smallest copy method.
There is no difference between struct and class, so just write them copy methods.
Only you know the structure of your data, so you're the only One who can save the humankind (or copy this data).