I am new to C++ and I am writing the following code.
I needed to iterate over all the addons in my calling function - testFunction. I know this works in C#, but this code is not working. Can anyone please point out the right way to do it in C++?
#include "stdafx.h"
#include <iostream>
#include "resource.h"
int testFunction(char* tester);
int _tmain()
{
int mainProd=2;
int Addons[]={7,8,9,10};
testFunction(mainProd,Addons);
}
void testFunction(int mainProd,int addons[])
{
for(int x = 0 ; addons.length;++x) ---- Not working
{
std::cout<< addons[x];
}
}
I tried to implement vector as below suggestions by you guys
#include "stdafx.h"
#include <iostream>
#include "resource.h"
#include <vector>
void testFunction(std::vector<int> addons);
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<int> Addons ;
for(int i = 0 ;i<10;++i)
{
Addons.push_back(i);
}
testFunction(Addons);
}
void testFunction(std::vector<int> addons)
{
for(int i =0 ; i<addons.size();++i)
{
std::cout<<addons.at(i);
}
}
An array (a raw array) decays into a pointer when passed as an argument to a function, so your array has no size information.
You need to pass the length of the array explicitly into the function to know it inside the function.
Alternatively, and better, use a std::vector and then you'll have the .size() always available when needed.
Apart from using vectors, as Tony suggests, you can use templates and pass the array by reference so that the compiler will deduce the array's size:
template<int N>
void testFunction(int mainProd,int (&addons)[N])
{
for(int x = 0; x < N; ++x) // ---- working
{
std::cout<< addons[x];
}
}
You're using concepts of C# in C++ but, even if we assume that both languages are similar, they're not equal.
The syntax for a ranged-for in C++ is the following:
for (type identifier : container) // note the ':', not ';'
{
// do stuff
}
You can use this for flavour if you have a C++11 compiler.
Btw, it seems that you're using properties on your code:
for(int x = 0 ; addons.length;++x) // what is lenght?
{
std::cout<< addons[x];
}
There's no such thing in C++, if you want to call an object method you need to call it as a function:
// assuming that the object 'addons' have a method
// named 'length' that takes no parameters
addons.length();
But the addons variable isn't an object, is an array (take a look to this tutorial), so it doesn't have a method or property named length; if you need to know its length in order to iterate it you can use in some contexts the sizeof operator (see the tutorial for more information).
Let's suppose that addons were a container:
typedef std::vector<addon> Addons;
Addons addons;
If you want to iterate it using the C++11 range-for, you can write it as follows:
for (addon a : addons)
{
// do stuff with a.
}
Hope it helps.
If you were to use a std::vector or std::array, you could use std::foreach,
std::vector<int> addons = {7,8,9,10};
std::array<int, 4> addons = {7,8,9,10}; // Only use one of these...
std::foreach(addons.begin(), addon.end(), [](int i) {
std::cout << i
});
Code is working with this
for (int i = 0; i < (end(array) - begin(array)); i++)
Return maximum size
Test whether array is empty
array::empty
Element of array
array::size
Array size
sizeof()
If you don't want to use any STL container, you just need to pass the array by reference to the function. Problem here is that you can't define such argument without exact size of the array. This restriction you can overcome making the function as a template, defining the size as the template parameter:
#include <iostream>
template<int N>
void testFunction(int mainProd,int (&addons)[N])
{
for(int x = 0 ; x < N; ++x)
{
std::cout<< addons[x];
}
}
int main()
{
int mainProd=2;
int Addons[]={7,8,9,10};
testFunction(mainProd,Addons);
return 0;
}
Related
I have a problem with the initialization with various parameters in my function.
It works if I have created an array int params [] = {...}. However, it doesn't work if I want to write the parameters directly into the function.
declaration (in the .h)
void phase_an(int led[]);
in the .cpp
void RS_Schaltung::phase_an(int led[])
{
for (size_t i = 0; i < LEN(led); i++) {
digitalWrite(led[i], HIGH);
}
}
if I try this way, it won't work. I would like it to be like that. But I couldn't find anything about it on the internet. ...:
in the Arduino sketch:
RS.phase_an(RS.ampelRot, RS.ampelGelb, ..... ); <--- is there a way to do it like that?
what amazes me is that it works this way:
int p_an [5] = {RS.ampelRot, RS.ampelGelb, RS.ampelGruen, RS.rot, RS.gelb};
...................
RS.phase_an (p_an);
does anyone have a suggestion?
There are several ways of making a function accepting a variable number of arguments here.
However, in your current code there is a problem: when you pass a native array of unknown size as argument of a function (e.g. void f(int a[])), the argument will be managed a pointer to an array, and there is no way inside this function to know the real length of that array. I don't know how LEN() is defined, but chances are high that it doesn't works well in your code.
A safer and more practical alternative is to use a vector<int> instead:
#include <iostream>
#include <vector>
using namespace std;
void f(const vector<int>& a){
for (int i=0; i<a.size(); i++) {
cout<<a[i]<<" ";
}
cout<<endl;
}
int main() {
vector<int> test={1,2,3,4};
f(test);
f({1,2,3,4});
return 0;
}
In this case, you can pass your multiple values between bracket in the function call (e.g. ({RS.ampelRot, RS.ampelGelb, RS.ampelGruen, RS.rot, RS.gelb})and C++ will automatically convert it to a vector.
So a few days ago I asked and received a very good answer in this thread. Assignment and retrieval using subscript and equals operator overloads
Unfortunately my mistake but it was a little to far from my end use scenario, I'm trying to store pointers to the cchar_t class in nucrsesw/ncurses.h This is what I have currently
#include <iostream>
#include <vector>
#include <string>
#include <ncursesw/ncurses.h>
#include <ncursesw/panel.h>
class Matrix {
std::vector<std::vector<cchar_t*>> m;
public:
Matrix(int x = 0, int y = 0) {
m.resize(x);
for (int i = 0; i < x; ++i)
m[i].resize(y);
}
class Proxy {
std::vector<cchar_t*> &mm;
public:
Proxy(std::vector<cchar_t*> &c) : mm(c) {}
cchar_t& operator[](int index) {
return *mm[index];
}
};
Proxy operator[](int index) {
return Proxy(m[index]);
}
};
int main() {
wchar_t wR = u'W';
cchar_t *w;
setcchar(w, &wR, 0, COLOR_PAIR(0), NULL);
Matrix m(1, 1);
m[0][0] = *w;
std::cout << typeid(m[1][1]).name() << std::endl;
}
I keep getting invalid initialization of reference type in the second subscript overload function. It may be obvious but CPP is not my primary language. Does anyone know how this can be adapted to store pointers? Thanks in advance.
Note the code is edited to show exactly what happens when it seg faults on me.
mm is a reference to an std::vector which holds objects of type cchar_t* (pointers to cchar_t objects). The subscript operator of std::vector returns a reference to the object at the appropriate index. In your case, that would be a reference to a pointer to cchar_t.
To fix your problem, you can dereference the obtained pointer in the return statement: simply change it to return *mm[index];.
I'm trying to get one of my argv's (which is an int sent in as a string), to become the length of an array, but the compiler keeps telling at me that num_of _players isn't constant and cant be used.
Any suggestions why?
#include <iostream>
using namespace std;
int main(int argc, char** argv)
{
int num_of_players = stoi(argv[argc - 1]);
int player_list[num_of_players];
return 0;
}
The problem is that declaring arrays in that way requires the size to be provided at compile time. They can not be declared with a value discovered at runtime.
The most basic alternative is to use a dynamic array which you can create manually:
#include <iostream>
using namespace std;
int main(int argc, char** argv)
{
int num_of_players = stoi(argv[argc - 1]);
int* player_list = new int[num_of_players];
// do stuff with player_list here...
delete[] player_list; // REMEMBER to delete[] it!!
return 0;
}
When you create something (like an array) using new or new[] you have to manually dispose of them (incl. give the memory back) using delete or delete[] respectively. However this can be forgotten so it is a potential source of memory leaks. For that reason one would typically use a type that manages the dynamic array automagically like a std::vector.
Because it isn't constant and can't be used.
Like how the size of an int is baked into your program, so is the size of an array. It has 3 elements, or 9 elements, or 512 elements … but this information cannot come from the command-line because it already had to be baked into your program when you compiled it.
Instead, use a "dynamic array" like std::vector that can grow and shrink as needed at runtime.
(Don't use new & you will not forget to delete. Use smart pointers.)
.
As it already written: Because it is not a compile-time known value. This might satisfy your needs:
#include <string>
void fu(size_t num_of_players)
{
std::unique_ptr<int[]> player_list = std::make_unique<int[]>(num_of_players);
player_list[4] = 10;
int x = player_list[4]; // In this example: x = 10
}
int main()
{
fu(10);
}
.
Or, let's say there is a class for "Game":
#include <string>
class CGame // Assume that m_player_list values are not negative
{
public:
CGame(size_t num_of_players) // Constructor
{
m_num_of_players = num_of_players;
m_player_list = std::make_unique<int[]>((num_of_players));
}
int set_player(size_t i, int n)
{
if (i < m_num_of_players) {
m_player_list[i] = n;
return m_player_list[i];
}
return -1; // Out of bounds error
}
int get_player(size_t i)
{
if (i < m_num_of_players)
return m_player_list[i];
return -1; // Out of bounds error
}
protected:
std::unique_ptr<int[]> m_player_list;
size_t m_num_of_players = 0;
};
int main()
{
CGame Game(10); // User input: 10 players
Game.set_player(4, 10);
int x = Game.get_player(4); // In this example: x = 10
return 0;
}
I am trying to create an array of class objects taking an integer argument. I cannot see what is wrong with this simple little code. Could someone help?
#include <fstream>
#include <iostream>
using namespace std;
typedef class Object
{
int var;
public:
Object(const int& varin) : var(varin) {}
} Object;
int main (int argc, char * const argv[])
{
for(int i = 0; i < 10; i++)
{
Object o(i)[100];
}
return 0;
}
In C++ you don't need typedefs for classes and structs. So:
class Object
{
int var;
public:
Object(const int& varin) : var(varin) {}
};
Also, descriptive names are always preferrable, Object is much abused.
int main (int argc, char * const argv[])
{
int var = 1;
Object obj_array[10]; // would work if Object has a trivial ctor
return 0;
}
Otherwise, in your case:
int main (int argc, char * const argv[])
{
int var = 1;
Object init(var);
Object obj_array[10] = { var, ..., var }; // initialize manually
return 0;
}
Though, really you should look for vector
#include <vector>
int main (int argc, char * const argv[])
{
int var = 1;
vector<Object> obj_vector(10, var); // initialize 10 objects with var value
return 0;
}
dirkgently's rundown is fairly accurate representation of arrays of items in C++, but where he is initializing all the items in the array with the same value it looks like you are trying to initialize each with a distinct value.
To answer your question, creating an array of objects that take an int constructor parameter. You can't, objects are created when the array is allocated and in the absence of a trivial constructor your compiler will complain. You can however initialize an array of pointers to your object but you really get a lot more flexibility with a vector so my following examples will use std::vector.
You will need to initialize each of the object separately if you want each Object to have a distinct value, you can do this one of two ways; on the stack, or on the heap. Lets look at on-the-stack first.
Any constructor that take a single argument and is not marked as explicit can be used as an implicit constructor. This means that any place where an object of that type is expected you can instead use an instance of the single parameter type. In this example we create a vector of your Object class and add 100 Objects to it (push_back adds items to a vector), we pass an integer into push_back which implicitly creates an Object passing in the integer.
#include <vector>
int main() {
std::vector<Object> v;
for(int i = 0; i < 100; i++) {
v.push_back(i);
}
}
Or to be explicit about it:
#include <vector>
int main() {
std::vector<Object> v;
for(int i = 0; i < 100; i++) {
v.push_back(Object(i));
}
}
In these examples, all of the Object objects are allocated on the stack in the scope of the for loop, so a copy happens when the object is pushed into the vector. Copying a large number of objects can cause some performance issues especially if your object is expensive to copy.
One way to get around this performance issue is to allocate the objects on the heap and store pointers to the objects in your vector:
#include <vector>
int main() {
std::vector<Object*> v;
for(int i = 0; i < 100; i++) {
v.push_back(new Object(i));
}
for(int i = 0; i < 100; i++) {
delete v[i];
}
}
Since our objects were created on the heap we need to make sure that we delete them to call their deconstructor and, free their memory, this code does that in the second loop.
Manually calling delete has it's own caveats, if you pass these pointers to other code you can quickly loose track of who owns the pointers and who should delete them. An easier way to solve this problem is to use a smart pointer to track the lifetime of the pointer, see either boost::shared_ptr or tr1::shared_ptr which are reference-counted pointers :
#include <vector>
int main() {
std::vector<shared_ptr<Object> > v;
for(int i = 0; i < 100; i++) {
Object* o = new Object(i);
v.push_back(shared_ptr<Object>(o));
}
}
You'll notice that the shared_ptr constructor is explicit, this is done intentionally to make sure that the developer is intentionally stuffing their pointer into the shared pointer. When all references to an object are released the object will automatically be deleted by the shared_ptr, freeing us of the need to worry about it's lifetime.
If you want to stick to arrays, then you must either initialize manually or use the default constructor. However, you can get some control by creating a constructor with a default argument. This will be treated as a default constructor by the compiler. For example, the following code prints out the numbers 0, ..., 9 in order. (However, I'm not sure that the standard dictates that the objects in the array must be constructed in order. It might be implementation dependent, in which case the numbers may appear in arbitrary order.)
#include <iostream>
using namespace std;
struct A {
int _val;
A(int val = initializer()) : _val(val) {}
static int initializer() { static int v = 0; return v++; }
};
int main()
{
A a[10];
for(int i = 0; i < 10; i++)
cout << a[i]._val << endl;
}
Below I have written a sample program that I have written to learn about passing a list of objects to another class. I talk about the problems I am having below.
#include <iostream>
#include <vector>
using namespace std;
class Integer_Class
{
int var;
public:
Integer_Class(const int& varin) : var(varin) {}
int get_var() { return var; }
};
class Contains_List
{
typedef Integer_Class* Integer_Class_Star;
Integer_Class_Star list;
public:
Contains_List(const Integer_Class_Star& listin) : list(listin) {}
Integer_Class* get_list() { return list; }
};
int main (int argc, char * const argv[])
{
// Create a vector to contain a list of integers.
vector<Integer_Class> list;
for(int i = 0; i < 10; i++)
{
Integer_Class temp_int(i);
list.push_back(temp_int);
}
This is where the errors start occuring. Could someone please look at the second class definition and the code below and shed some light on what I'm doing wrong. Thank you so much, as always!
// Import this list as an object into another object.
Contains_List final(list);
// Output the elements of the list by accessing it through the secondary object.
for(int i = 0; i < 10; i++)
{
cout << final.get_list()[i].get_var();
}
return 0;
}
You don't mention what sort of errors you are getting, but one very obvious problem with your code is that the constructor for Contains_List expects a pointer to Integer_Class while the parameter you are sending it (list) is of type vector<Integer_Class>.
A vector is not the same as an array, so you cannot pass it as pointer to the type it contains. Either change your constructor to accept a vector or pointer/reference to vector, or change the code that is causing you problems so that it sends it a pointer to an array.
The 'Contains_List' constructor takes in an 'Integer_Class*'
You declare 'list' to be of type 'vector', yet you pass it to the the 'Contians_List' constructor. You should change the 'Contains_List' class so that it holds a vector instead of an Integer_List array. The two are not interchangeable.
You could also change the vector to be an array of Integer_List's instead, if you so wished.