Play with elements of Array of Structures in C++ - 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 *.

Related

&temp and *temp in c++

I am new to C++ and trying to convert string into integer. I was using atoi but there are some restrictions so I start using strtol which works perfectly. However, I would like to learn more on *temp and &temp (I have google and learn that it is a temporary space for storage) but would like to learn the difference and when to use which.
char *temp;
int m = strtol (argv[1],&temp,10);
if (*temp != '\0')
*temp is a pointer to a variable named temp and &temp takes the address of that variable
First of all jessycaaaa welcome to Stackoverflow.
I am new to C++ and trying to convert string into integer.
For me this looks like plain C-code. You can compile this with a C++ compiler though.
I was using atoi but there are some restrictions so I start using strtol which works perfectly.
Since you get an undefined behavior using atoi when argv[1] contains something different than a number, strtol is an approach to go for. If you share us a bit more code, we would help you better on your questions.
However, I would like to learn more on *temp and &temp (I have google and learn that it is a temporary space for storage) but would like to learn the difference and when to use which.
First of all you have to distinguish between use and declaration
char *temp;
Here you declare (*-symbol in declaration) a pointer named temp of type char. A pointer is a variable which stores the memory address (where it is pointing to). Here you did not define an address so it most likely will point a random space, but then
int m = strtol (argv[1],&temp,10);
you pass the address of the pointer (&-symbol, use-case, address-of operator) to strtol, so you get an address pointing to the part of the argv[1] where the number literals end, that is all fine. The function also returns the numerical value of the read string as long and is converted to an int.
if (*temp != '\0')
Here you access the value of what the address is pointing to (*-symbol, use-case, dereference operator). \0 is normally set as indication for a null-terminated string. So you are asking if the previously read end part has the null-termination character.
You know what: in C++ there are more elegant ways to accomplish that using stringstreams:
std::stringstream
Just an idea if you don't want to handle too much string manipulation in C and annoyances with pointers.
Also I would read a good book about C (not C++). C++ has also the references don't get confused by those. If you dominate the pointer-concept of C, I'm pretty sure everything else will be very clear for you.
Best regards
* and & are one of the first hurdles that programmers new to C and C++ have to take.
To really understand these concepts, it helps to know a bit more about how memory works in these languages.
First of all: C++ is just C but with classes and many other additional features. Almost all C programs are valid C++ programs. C++ even started out as a language that was compiled to C first.
Memory is, roughly speaking, divided in two parts, a 'stack' and a 'heap'. There are also other places for the code itself and compile-time constants (and maybe a few more) et cetera but that doesn't matter for now. Variables declared within a function always live on the stack. Let's see this in action with a simple example and analyse how memory is organized to build a mental model.
#include <iostream>
void MyFunction() {
int intOnStack = 5;
int* intPtrOnStack = new int(6); // This int pointer points to an int on the heap
std::cout << intOnStack << *intPtrOnStack;
delete intPtrOnStack;
}
int main() { MyFunction(); }
This program prints 56 when executed. So what happens when MyFunction() gets called? First, a part of the stack is reserved for this function to work with. When the variable intOnStack is declared within the function, it is placed in this part of the stack and it is initialized with (filled with) the int value 5.
Next, the variable intPtrOnStack is declared. intPtrOnStack is of type int*. int*'s point to int's by containing their memory-address. So an int* is placed on the stack and it is initialized with the value that results from the expression new int(6). This expression creates a new int on the heap and returns the memory-address of this int (an int*) to it. So that means that intPtrOnStack now points to the int on the heap. Though the pointer itself lives on the stack.
The heap is a part of memory that is 'shared' by all functions and objects within the program. The stack isn't. Every function has its own part of the stack and when the function ends, its part of the stack is deallocated.
So int*'s are just memory-addresses of int's. It doesn't matter where the int lives. int*'s can also point to int's on the stack:
#include <iostream>
void MyFunction() {
int intOnStack = 5;
int* intPtrOnStack = &intOnStack; // This int pointer points to intOnStack
std::cout << intOnStack << *intPtrOnStack;
}
int main() { MyFunction(); }
This prints 55. In this example we also see the &-operator in action (there are several uses of & like the bit-wise-and, I'm not going into them).
& simply returns the memory-address (a pointer!) of its operand. In this case its operand is intOnStack so it returns its memory-address and assigns it to intPtrOnStack.
So far, we've seen only int* as types of pointers but there exist pointer-types for each type of object that has a memory-address, including pointers. That means that a thing like int** exists and simply means 'pointer to a pointer to an int'. How would you get one? Like this: &intPtrOnStack.
Can pointers only live on the stack? No: new int*(&intPtrOnStack). Or new int*(new int(5)).

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...

Please help me to Marshal this array of structs to C++

The C++ code:
typedef struct {
int bd_number; // number of boardset
int bd_copies; // how many copies
int bd_reserve; // only allocate if needed
} bd_t,*bd_p;
typedef struct boardset_info {
int bs_copies;
int bs_demand;
int bs_allocated;
int bs_ontable_avail;
int bs_ontable_needed;
pstatus bs_status;
int bs_played_sofar;
} bsi_t, *bsi_p;
FC_ERRORCODE dropin_boards(bd_p boards) {
int bs;
bs_info = (bsi_p) calloc(total_boardsets+1, sizeof(bsi_t));//total_boardsets=8
for (bs = 1; bs <= total_boardsets; bs++)
bs_info[bs].bs_status = PS_OUTPLAY;
while (boards->bd_number) { //boards-<bd_number is betweeen 1 and 8
if (boards->bd_number < 0 || boards->bd_number > total_boardsets)
{
debprint("***Error dropin_boards***\n");
debprint("boardsetnumber=%d\n",boards->bd_number);
return FC_ERR_PARAM;
}
//code does not reach this point
}
Calling code:
<StructLayout(LayoutKind.Sequential)>
Public Structure Flex_BoardSetInfo
Public SetNumber As Integer
Public Copies As Integer
Public IsReserve As Integer
End Structure
<DllImport("FlexCalc2.dll", CallingConvention:=CallingConvention.StdCall)>
Public Shared Function FlexCalcBoards(ByRef boards() As Flex_BoardSetInfo) As Flex_ErrorCode
End Function
Dim boardsets() = GetBoardSetInfo() // creates an arry of 8 BoardsetInfo Elements
_result = FlexCalcWrapper.FlexCalcBoards(boardsets)
On the last line on the debug file is logged that bd_p->board_number=517237496! The boardnumbers are initialized 1 to 8 and I can check that that has been correctly done before the code passes to the C++ dll.
How do I solve this?
EDIT:
From VB6 we used a hack to get this C++ method working:
Declare Function FlexCalcBoards Lib "FlexCalc2.dll" (firstBoard As BoardsetInfo)
ret=FlexCalcBoards(Boards(0))
So, we passed the first element of the array in stead of the array itself! (Un?)fortunately, Net does not fall for this trick...
Replace ByRef with ByVal. An array already gets marshaled as a pointer.
Using ByRef would only match a bd_t** on the C side.
Well, the answers and comments seemed to indicate that nothing should be wrong, so....
I found three things:
1. Even after rebuilding the entire solution and copying and pasting the new FlexCalc2.dll to the testproject, the old copy of the dll that resided in the Bin folders was NOT replaced.
2. I am a novice in C++, but it seems that you cannot iterate through an array using LBound to UBound when the method has only received a pointer to it. The method shown uses a nifty way to implement a kind of for each, but here it does not work because bd_p->boardnumber returns a very high number (memory address?), but bd_p[index].boardnumber returns the correct number within the range 1-8. I simply sent the length of the array as an extra parameter to the function and I was all set. (Call it the poor man's choice for all I care ;-))
3. Hans Passant was right in stating that when the method signature in C++ is theReturnValue theMethod(theStruct * theArray) that from Net you must pass the array ByVal (In VB6 this generates a syntax error and is not possible). The fact that a pointer to the array was passed is not immediately obvious since the * was already declared in the typedef of the struct.

C++ string.compare()

I'm building a comparator for an assignment, and I'm pulling my hair out because this seems to simple, but I can't figure it out.
This function is giving me trouble:
int compare(Word *a, Word *b)
{
string *aTerm = a->getString();
string *bTerm = b->getString();
return aTerm->compare(bTerm);
}
Word::getString returns a string*
Error:
In member function `virtual int CompWordByAlpha::compare(Word*, Word*)':
no matching function for call to...
...followed by a bunch of function definitions.
Any help?
You're comparing a string to a string pointer, and that's not valid. You want
return aTerm->compare(*bTerm);
You aren't getting the different uses of the * operator. The use of the * in "string* bTerm = b->getString()" means "bTerm is a pointer to a string". The use of the * inside of compare(*bTerm) means "take the value of the location pointed to by bTerm" instead of just using compare(bTerm) which simply attempts to compare the value of bTerm itself, which is a hex address.
This is also happening on the left side of that call:
aTerm->compare(*bTerm); //this statement
(*aTerm).compare(*bTerm); //is the same as this statement
The -> operator just reduces the amount of typing required.
P.S.: This kind of stuff you could have easily figured out from Google or your programming textbook. Although others may disagree, I don't feel that questions about completely basic syntax have any place on Stack Overflow.