Accessing a array of Structs using pointer notation - c++

I am trying to learn C++ on my own and was trying out this. I have a struct one of whose member is an array of another structs. I have a question about alternative notation.
The structs that I have defined are
struct employeeRecordT {
string name;
string title;
string ssnum;
double salary;
int withholding;
};
struct payrollT {
int num;
employeeRecordT *array;
} payroll;
I am allotting memory to payroll using the following construct
payroll.array = new employeeRecordT[payroll.num];
where payroll.num is indicating the number of elements in the array. I can access the element name of the employeeRecordT by using the array notation e.g.
payroll.array[i].title
I wanted to know how to access this using the pointer notation, I have tried
payroll.(array+i)->name = "Vikas";
and I get the following error message from g++
toy.cc:30:13: error: expected unqualified-id before '(' token
toy.cc:30:14: error: 'array' was not declared in this scope
I am trying to understand what I should be using and why? Could you guys help explain.
Thanks in advance.
Regards,
Vikas

(payroll.array+i)->name = "Vikas";
array is a member of payroll, so when you were doing payroll.(array+i), the bracket notation (i.e. "do this first") was trying to use a variable array, and not the one within the scope of payroll.
Of course, using C++, the better solution is Neils. Use a std::vector instead of your own dynamically allocated storage if possible.

If it hurts, don't do it. Use a std::vector of your structures instead.

Related

How can I initialize an array in C++ using a variable initialized at runtime? [duplicate]

This question already has an answer here:
Array[n] vs Array[10] - Initializing array with variable vs numeric literal
(1 answer)
Closed 12 months ago.
What i would like to do is declare an array with "dim" size :int A[dim];.
Now, this works if I declare something like const int dim = 1 but doesn't with const int dim = round(x);, which is what i need to do. (Where x comes from cin >> x.)
Note: With "doesn't work" i refer to Visual Studio Code throwing red wavy line under dim in int A[dim]; and displaying the following when hovering it with my mouse:
`
expression must have a constant valueC/C++(28)
main.cpp(15, 11): the value of variable "dim" (declared at line 13) cannot be used as a constant
`
This is the relevant code:
#include <iostream>
using namespace std;
int main(){
float x;
cin >> x;
const int dim = round(x);
int A[dim];
int i = 0;
}
}
Given the context i believe the error is caused by one of two reasons:
Some characteristic of round() that makes the const int dim = round(x) not recognized as constant from the array later.
The problem is the x and not the round() so cin >> x is the reason.
[Thanks for whoever can explain me what I'm missing or point to some documentation that does. I have done some research but I haven't found a solution to this. Also this is my first question on SO, so tell me if I should change/improve something]
EDIT: Apparently the problem isn't in the round(x) as I previously thought because simply replacing const int dim = round(x); with const int dim = x; gives the same "error".
So the problem has to do with cin >> x .
EDIT 2 Note: I'm looking for a solution that doesn't use std::vector. We haven't studied it yet in the course so I believe the algorithm(from which i took the relevant code) shouldn't comprehend it.
Final Edit I didn't realize that, as #paulmckenzie clarified, using cin made the array dynamic because the imput comes in runtime, it was a really stupid error but I apologize, I'm really a beginner. In my defense we really haven't talked about dynamic size arrays so I guess that's what threw me off. I realized from the beginning I was missing something very basic, sorry for wasting time, I'll put even more time analyzing everything before posting next time.
The size of an array variable must be compile time constant in C++. User input is not compile time constant, hence it cannot be used as the size of an array variable.
In order to create an array with runtime size, you must instead create a dynamic array. The simplest way to do that is to use std::vector from the standard library.
EDIT 2 Note: I'm looking for a solution that doesn't use std::vector.
It's possible to create a dynamic array without std::vector, but that requires the use and understanding of more advanced concepts. Using new expressions directly is more difficult, error prone and is something that isn't (or shouldn't) be done in most programs in practice.
Of course, another solution is to just not use user input but rather an array with constant size.

Play with elements of Array of Structures in C++

I have just started learning c++ and I am stuck over here.
I made a structure
...
struct student{
string name;
int roll;
};
...
And then, I called it globally. student s1[20]; Inside my main function,
I did something like this
...
int count=0;
student *p;
p=s1;
cout<<"Enter the Number of records, you wish to consider.";
cin>>arraySize;
p = new student[arraySize];
while (count!=arraySize) {
cout<<"Enter name.";
cin>>*(p+count)->name; //Error comes over here
}
...
The error message, I get is Indirection requires pointer operand. Can some one Please help me out with this ??
You could either use pointer arithmetic as you are doing
(p+count)->name
or more canonically use [] to index into the array
p[count].name
The reason you are getting an error is because you are combining * which dereferences your pointer with -> which also dereferences your pointer. You could just do one or the other
(p+count)->name
(*(p+count)).name
Though as I said for readability I would prefer using index notation []
Using *(p+count)->name makes no sense.
Picking up from here, foo->bar calls method bar on the object pointed by pointer foo.
So, you should either do (p+count)->name or (*(p+count)).name.
Note the brackets, they're necessary as . has greater precedence than *.

Dynamic memory allocation initialisation in C++ class

(I'm not posting my code as this is for a project, however I have tried to get help for this issue but have had no luck)
Hi there, I am trying to initialise the size of an array of pointers (char*) which is a private member variable of my class class A
I'm using the constructor to set the size by setting an integer variable (also a member variable) which will then be used to create my array of pointers.
I have done this so far:
// Constructor - 'int value' is set to a value
private:
int value;
char ** myArray = new char*[value];
So basically I want an array of pointers in which each element can point to a string. I am passing string variables to myArray by using (char*) stringVar.c_str();
Although all of this works, I am getting some pretty weird errors when trying to store variables and have even gotten this error:
free (): invalid next size (fast)
It's weird because even when myArray is of size 4, when I try to access, say, the 3rd element, I get the same error as above.
I am very new to C++ and am very intent on solving these issues. I've had to resort to this forum for help and am looking forward to some ideas from you guys :)
if you are new C++ programmer and want work with C++ String list is better work with std::vector<std::string> for complete tutorial of how using vectors see:
http://www.cplusplus.com/reference/vector/vector/
but in you question is String list size fixed?or not?
if string list is not fixed you must malloc space for array first time in constructor and then realloc array when you want insert a string in your string list for example:
class A{
private:
char** arrayy;
int arrayysize;
A(){
arrayy = (char**)calloc(1,sizeof(char*));
arrayysize = 1;
}
insertToarrayy(char* data){
strcpy(arrayy[arrayysize-1],data);
arrayy = (char**)realloc(arrayy,arrayysize+1);
arrayysize += 1;
}
}

Dynamic Memory Allocation in C++ structs

I don't understand the syntax required for dynamically allocating members of a struct in c++. Basically, I need to fill char array members to exact size using a temp array and strlen. Here is my struct:
struct card
{
char *rank;
char *suit;
char color;
bool dealt;
char *location;
};
Here is the function that uses the struct:
bool importCard(card *deckPtr, char *deckName);
I created an array of 52 cards and assigned a pointer to it, and passed it to the function as the first parameter. (deckPtr) Here is a loop in the function that is supposed to read in card info to the struct data members.
for(index=0;index<52;index++,deckPtr++)
{
fin >> *temp;
charCount=stringLength(temp);
deckPtr.*rank = new char[charCount+1];
stringCopy(*temp, deckPtr.*rank);
fin >> *temp;
charCount=stringLength(temp);
deckPtr.*suit = new char[charCount+1];
stringCopy(*temp, deckPtr.*suit);
if(deckPtr.*suit==('d')||deckPtr.*suit==('h'))
{
(*deckPtr).color='r';
}
else
{
(*deckPtr).color='b';
}
(*deckPtr).dealt=false;
deckPtr.*location = new char[11];
stringCopy(unshPtr, deckPtr.*location);
}
I am getting three compile errors: "rank" "suit" and "location" are "not declared in this scope." What am I doing wrong? Thanks!
The syntax is deckPtr->rank, deckPtr->suit, deckPtr->location = new char[...];.
But your coding style is more like C than C++. Instead, if you use modern C++, with convenient RAII classes like std::string, your code becomes much more simplified: just use std::string instead of raw char* pointers, and you don't have to pay attention to memory allocation and memory freeing: it's all automatically managed by std::string and destructors.
#include <string>
struct card
{
std::string rank;
std::string suit;
char color;
bool dealt;
std::string location;
};
And instead of your custom stringCopy() function you can just use the "natural" operator= overload for std::string (i.e. destString = sourceString;).
And to build an array of 52 cards, just use std::vector:
#include <vector>
std::vector<card> cards(52);
Again, memory allocation is automatically managed by std::vector (and, unlike raw C arrays, you can query the vector for its own element count, using its size() method).
You probably want to use deckPtr->rank, deckPtr->suit, and deckPtr->location to assign something to the char pointers (alternatively, (*deckPtr).rank etc.). Note that * in char *var is not part of the name of the variable. It just states that the variable is a pointer to char.
You need deckPtr->foo instead of deckPtr.*foo
Your problem is that the dereference operator is operating on foo, not on deckPtr, which makes no sense to the C++ compiler, so it uses instead the pointer to member operator. This operator is used to execute member function pointers on an object, which is completely different from accessing a member. Chances are good that in an intro-level c++ class (like it appears you are in) you will never have to worry about using or understanding that operator.
In general, in C/C++ whenever you have a pointer to a struct, you want to use the -> operator, not .. foo->bar is equivalent to (*foo).bar, but it keeps you from messing up and forgetting the parentheses. There's a reason that C had an arrow operator - it's easier and clearer. In my not-so-humble opinion, teachers that impose such arbitrary restrictions actually teach students to write bad code and reinvent wheels, but I don't have their experience in teaching programming...

C++ pass array argument to a function

I want to pass a reference to an array from one object GameModel to another PersonModel, store reference and then work with this array inside PersonModel just like inside GameModel, but...
I have a terrible misunderstanding of passing an array process: In the class PersonModel I want to pass an array by reference in a constructor (see code block below). But the marked line throws the compile error
PersonModel::PersonModel( int path[FieldSize::HEIGHT][FieldSize::WIDTH], int permissionLevel ) {
this->path = path; //<------ ERROR here:
//PersonModel.cpp:14:22: error: incompatible types in assignment of 'int (*)[30]' to 'int [31][30]'
this->permissionLevel = permissionLevel;
}
Here is the header file PersonModel.h
#ifndef PERSON_MODEL
#define PERSON_MODEL
#include "data/FieldSize.h"
namespace game{
class IntPosition;
class MotionDirection;
class PersonModel {
protected:
int path[FieldSize::HEIGHT][FieldSize::WIDTH];
int permissionLevel;
public:
PersonModel( int path[FieldSize::HEIGHT][FieldSize::WIDTH], int permissionLevel );
void setMotionDirection ( MotionDirection* md);
void step(long time);
void reset(long time);
};
}
#endif
As I see now, I can change the int path[FieldSize::HEIGHT][FieldSize::WIDTH]; declaration to int (*path)[FieldSize::WIDTH]; but it is much more confusing.
Help me understand this topic: what is the proper way to store the passed reference to an array to work with it later, like with usual 2D array.
UPDATE:
This array is a map of game field tiles properties represented by bit-masks, so it is read-only actually. All the incapsulated objects of GameModel class should read this array, but I definitely don't want to duplicate it or add some extra functionality.
There are no frameworks just bare Android-NDK.
I think you've fallen into the classic trap of believing someone who's told you that "arrays and pointers are the same in C".
The first thing I'd do would be to define a type for the array:
typedef int PathArray[FieldSize::HEIGHT][FieldSize::WIDTH];
You then don't need to worry about confusions between reference to array of ints vs array of references to ints.
Your PersonModel then contains a reference to one of these.
PathArray &path;
and, because its a reference it must be initialised in the constructors initialization list rather than in the constructor body.
PersonModel::PersonModel( PathArray &aPath, int aPermissionLevel ) :
path(aPath),
permissionLevel(aPermissionLevel)
{
}
Of course, holding references like this is a little scary so you might want to consider using a boost::shared_ptr or something similar instead to make the lifetime management more robust.
You cannot assign arrays as you do with value types in C++
int path[x][y] resolves to the type int (*)[y]
Possible solutions are:
Using memcpy/copy
Using std::array
You can't assign to an array like that. However you can use the fact that an array is a contiguous memory area, even when having an array of arrays, and use e.g. memcpy to copy the array:
memcpy(this->path, path, FieldSize::HEIGHT * FieldSize::WIDTH * sizeof(int));
You would have to pass a pointer to the 2d-array as you cannot pass the array as you have stated in the code snippet.
I would suggest using the STL array type. Admittedly std::array is C++ '11 standard and therefore old compiler may not support it. You can also use vector which has been around longer.
vector<vector<int>>path;
You will have to resize the 2d-vector in the constructor.
Indexing would look a bit funny:
path[1].[1] ....
With vectors, you can then pass it by reference.
the name of the array is a pointer on first element
so,
you can try
PersonModel( int (*path)[FieldSize::HEIGHT][FieldSize::WIDTH], int permissionLevel );
In C++ '=' implemented for primitive types like int and double but not for array(array is not a primitive type), so you should never use '=' to assign an array to new array, instead you should use something as memcpy to copy array. memcpy copy a memory over another memory, so you can use it to copy an array over another array:
// memcpy( dst, src, size );
memcpy( this->path, path, FieldSize::HEIGHT * FieldSize * WEIGHT * sizeof(int) );