C++ pass array of struct by value [duplicate] - c++

This question already has answers here:
Does C++ pass objects by value or reference?
(5 answers)
Closed 8 years ago.
I'm having trouble understanding why passing my array, containing elements, to
a function, results in my array no longer containing elements within the function.
Before passing in an array containing 3 objects from my items sturct, the size of
the array is 72 (24 for each object). Once inside the function, the size of my array
is 24, which I assumed to be the size of the first element in my array. However, this
is not the case.
My question, why isn't my array the same in the function as it is outside of the function?
Header File:
#include <iostream>
using namespace std;
// header file for shop items
struct items
{
string name;
int price;
string examine;
};
main file:
#include "shop_items.h"
#include <iostream>
using namespace std;
int getLongestName(items &shop)
{
/*Iterates over each element in array
if int longest < length of element's name, longest = length of element's name.*/
int longest = 0;
// shop size is 24, the size of a single element.
cout << "sizeof(shop) right inside of function:" << sizeof(shop) << endl;
return longest;
}
void test1()
{
// initialize shop items
items sword;
items bow;
items shield;
// set the name, price, and examine variables for each item.
sword.name = "sword"; sword.price = 200; sword.examine = "A sharp blade.";
bow.name = "bow"; bow.price = 50; bow.examine = "A sturdy bow.";
shield.name = "sheild"; shield.price = 100; shield.examine = "A hefty shield.";
// create an array for iterating over the each element in item shop.
items shop[] = {sword, bow, shield};
//sizeOfShop = 72, 24 for each element (the sword, bow and shield).
cout << "sizeof(shop) right outside function: " << sizeof(shop) << endl;
int longest = getLongestName(*shop);
}
int main()
{
test1();
cout << "\n\nPress the enter key to exit." << endl;
cin.get();
}
What is useful about a reference-to-array parameter?
The answer to the above question has helped me a lot at better understanding what it is that I'm trying to do. However, I'm running into different errors when attempting to pass my array by reference as well.

You do not pass the array. You pass only the first element of the array.
int longest = getLongestName(*shop);
Expression *shop is equivalent to shop[0] So inside the function you get the size of one object of type items.
Moreover you declared function getLongestName as having parameter of type reference to an object of type items.
int getLongestName(items &shop);
If you wanted to pass the whole array by reference to the function then you should declare it as
int getLongestName( items ( &shop )[3] );
and the function has to be called as
int longest = getLongestName(shop);
Or as
int getLongestName(items *shop, size_t n);
where the second parameter specifies the number of elements in the array.
And the function has to be called as
int longest = getLongestName(shop, 3 );

Related

How to access member elements of a std::queue data structure? [duplicate]

This question already has answers here:
Compilation Error: void value not ignored as it ought to be in std::queue::pop() [duplicate]
(2 answers)
Invalid use of void expression with a Queue and .pop()
(2 answers)
Why doesn't std::queue::pop return value.?
(6 answers)
Closed 2 years ago.
Coding in C+, using Visual Studio 2019, I have a structure defined. I am creating a queue of that data structure and have pushed 2 elements into the queue. Now the question is how to access the members of the structure elements inside the queue?? Any guidance is appreciated!
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <queue>
typedef struct _myqueuestruct
{
string name;
int citypin;
int employeeId;
}myqueuestruct;
int main()
{
queue<myqueuestruct> myQ;
myqueuestruct myQelement;
myQelement.name = "Harry";
myQelement.citypin = "Ohio";
myQelement.employeeId = "345";
// Insert some elements into the queue
myQ.push(myQelement);
myQelement.name = "John";
myQelement.citypin = "Jaipur";
myQelement.employeeId = "223";
// Insert some elements into the queue
myQ.push(evtSvcElement);
//myQ.size();
//queue<myqueuestruct>::iterator it = myQ.begin();
for (int i = 0; i < myQ.size(); i++)
{
cout << myQ.front();
myQ.pop(); //???? How do I access the member values of the elements of the queue?
}
while (1);
return 0;
}
Well, front returns a reference to the first element, so like this:
std::cout << myQ.front().name; // and similarly for other elements
Or, for example, make a referenence yourself:
auto& ref = myQ.front();
ref.name = "foo";
ref.citypin = 42;
// etc.
I have modified your code to get it compiling and working: (Note: I have used C++17 standard using g++ to compile this code but it should work for visual studio 2019
#include <iostream>
#include <queue>
typedef struct _myqueuestruct
{
std::string name;
std::string citypin;
int employeeId;
}myqueuestruct;
int main()
{
std::queue<myqueuestruct> myQ;
myqueuestruct myQelement;
myQelement.name = "Harry";
myQelement.citypin = "Ohio";
myQelement.employeeId = 345;
// Insert some elements into the queue
myQ.push(myQelement);
myQelement.name = "John";
myQelement.citypin = "Jaipur";
myQelement.employeeId = 223;
// Insert some elements into the queue
myQ.push(myQelement);
while (myQ.size() > 0)
{
auto & e = myQ.front();
std::cout << "Name: " << e.name
<< " CityPin: " << e.citypin
<< " EmployeeId: " << e.employeeId << std::endl;
myQ.pop();
}
return 0;
}
I would like to point out a few changes I have to make in your above code:
in your struct definition you used int datatype but you assigned char string to the same. I have modified the datatype to be std::string.
using while loop for iterating through all the elements and using myQ.size() every time instead of using for loop.
std::cout - holding the element reference in a local variable inside the loop and printing all member variables.
Improvements you can make to above code:
There are multiple transient copies of the object being created when you push the object into the queue. I would suggest refer std::queue documentation here: http://www.cplusplus.com/reference/queue/queue/ and try to enhance above code with
emplace_back
overload operator<< for your class for printing class members, this would help you learn about operator overloading.

void class Arrays Sequential and Binary Search Using

I'm currently at my wits end trying to figure out how to do this, and was hoping someone could help.
The objectives the assignment is to:
Display the original sorted array of student records.
Display the sequential search result of student records.
Display the binary search result of student records.
The Full Instructions are:
a. Create three array of 12+ students records including ID’s, student names, and
the corresponding e-mail address’,– student ID’s are sorted in order. (No sort program needed for now.)
b. Sequential Search five ID’s which are from the sorted array and a 6th ID which is not from the array.
c. Binary Search five ID’s which are from the sorted array and a 6th ID which is not from the array.
d. Execution and output:
Display the original sorted array of student records.
Display the sequential search result of student records.
Display the binary search result of student records.
Any Help would be greatly appreciated
#include <iostream>
#include <iomanip>
#include <string>
#include <cmath>
#include <algorithm>
using namespace std;
struct Student {
string name;
int stuID;
string email;
};
// Show the student information
void showAllInfo(Student *studentArray, int stuCount) {
cout << "Student Info: "<<endl <<endl<<
"\t\tStudent Name"<<"\t\tStudent ID"<<"\t\tStudent Email"<<endl<<endl ;
for (int i = 0; i < stuCount; i++)
{
cout<<"\t\t"<< studentArray[i].name<<"\t\t"<<studentArray[i].stuID<<"\t\t\t"<< studentArray[i].email<<endl;
}
cout << endl;
}
//Sort out the arrays for the student information
void firstArray()
{
Student studentArray[12];
studentArray[0].name = "Bob McBoberston";
studentArray[0].stuID = 00;
studentArray[0].email = "BMcboberts#txstate.edu";
studentArray[1].name = "Shelby Donald";
studentArray[1].stuID = 1;
studentArray[1].email = "SDonald#txstate.edu";
studentArray[2].name = "Ronald Mcdonald";
studentArray[2].stuID = 2;
studentArray[2].email = "RMcdonald#txstate.edu";
studentArray[3].name = "Dick Cheney";
studentArray[3].stuID = 3;
studentArray[3].email = "DCheney#txstate.edu";
studentArray[4].name= "Ben Dover";
studentArray[4].stuID=4;
studentArray[4].email="BDover#txstate.edu";
studentArray[5].name="Ash Katchum";
studentArray[5].stuID=5;
studentArray[5].email="AKatchum#txstate.edu";
studentArray[6].name="Brock Whatever";
studentArray[6].stuID=6;
studentArray[6].email="BWhatevr#txstate.edu";
studentArray[7].name="Yugi Oh";
studentArray[7].stuID=7;
studentArray[7].email="YugiOh#txstate.edu";
studentArray[8].name="Johnny Bravo";
studentArray[8].stuID=8;
studentArray[8].email="JBravo#txstate.edu";
studentArray[9].name="Tom N. Jerry";
studentArray[9].stuID=9;
studentArray[9].email="Tnjerry#txstate.edu";
studentArray[10].name="Fred Flinstone";
studentArray[10].stuID=10;
studentArray[10].email="FFlinstone#emial.com";
studentArray[11].name="Son Goku";
studentArray[11].stuID=11;
studentArray[11].email="sGoku#txstate.edu";
studentArray[12].name="Johnny Test";
studentArray[12].stuID=12;
studentArray[12].email="JTest#txstate.edu";
}
void secondArray()
{
Student studentArray2[12];
studentArray2[0].name = "Rick Sanchez";
studentArray2[0].stuID = 13;
studentArray2[0].email = "RSanchez#txstate.edu";
studentArray2[1].name="Morty Smith";
studentArray2[1].stuID = 14;
studentArray2[1].email = "MSmith#txstate.edu";
studentArray2[2].name = "Summer Smith";
studentArray2[2].stuID = 15;
studentArray2[2].email = "SSmith#txstate.edu";
studentArray2[3].name = "Jerry Smith";
studentArray2[3].stuID = 16;
studentArray2[3].email = "JSmith#txstate.edu";
studentArray2[4].name="Mr. Meeseeks";
studentArray2[4].stuID=17;
studentArray2[4].email="MMeeseeks#txstate.edu";
studentArray2[5].name="Mr. PoopyButtHole";
studentArray2[5].stuID=18;
studentArray2[5].email="MPoopyButt#txstate.edu";
studentArray2[6].name="Tiny Rick";
studentArray2[6].stuID=19;
studentArray2[6].email="TRick#txstate.edu";
studentArray2[7].name="Pickle Rick";
studentArray2[7].stuID=20;
studentArray2[7].email="PRick#txstate.edu";
studentArray2[8].name="Beth Smith";
studentArray2[8].stuID=21;
studentArray2[8].email="BSmith#txstate.edu";
studentArray2[9].name="Bird Person";
studentArray2[9].stuID=22;
studentArray2[9].email="BmPerson#txstate.edu";
studentArray2[10].name="Squanchy";
studentArray2[10].stuID=23;
studentArray2[10].email="Squanchy#txstate.edu";
studentArray2[11].name="King Flippy Nips";
studentArray2[11].stuID=24;
studentArray2[11].email="KFlippyNipa#txstate.edu";
studentArray2[12].name="Mr> Goldenfold";
studentArray2[12].stuID=25;
studentArray2[12].email="MGoldenfold#txstate.edu";
}
void thirdArray()
{
Student studentArray3[13];
studentArray3[0].name = "Santa Claus";
studentArray3[0].stuID = 26;
studentArray3[0].email = "SClause#txstate.edu";
studentArray3[1].name = "Jason Riha";
studentArray3[1].stuID = 27;
studentArray3[1].email = "JRiha#txstate.edu";
studentArray3[2].name = "B-Rad Cragg";
studentArray3[2].stuID = 28;
studentArray3[2].email = "BRad#txstate.edu";
studentArray3[3].name="Roger Legrand";
studentArray3[3].stuID = 29;
studentArray3[3].email = "RLegrand#txstate.edu";
studentArray3[4].name="David De La O";
studentArray3[4].stuID=30;
studentArray3[4].email= "DDelao#txstate.edu";
studentArray3[5].name="Ian Sporn";
studentArray3[5].stuID=31;
studentArray3[5].email="ISporn#txstate.edu";
studentArray3[6].name="Morgan Taylor";
studentArray3[6].stuID=32;
studentArray3[6].email="Mytaylor#txstate.edu";
studentArray3[7].name="Sam Huggins";
studentArray3[7].stuID=33;
studentArray3[7].email="SHuggins#txstate.edu";
studentArray3[8].name="Shaun Huggins";
studentArray3[8].stuID=34;
studentArray3[8].email="ShuHuggins#txstate.edu";
studentArray3[9].name="Serena Huggins";
studentArray3[9].stuID=35;
studentArray3[9].email="SerHuggins#txstate.edu";
studentArray3[10].name="Kylie Parziale";
studentArray3[10].stuID=36;
studentArray3[10].email="KParziale#txstate.edu";
studentArray3[11].name="Jimmy Fallon";
studentArray3[11].stuID=37;
studentArray3[11].email="JFallon#txstate.edu";
studentArray3[12].name="Tom Goat Brady";
studentArray3[12].stuID=38;
studentArray3[12].email="TGBrady#txstate.edu";
studentArray3[13].name="Harry Giblets";
studentArray3[13].stuID=39;
studentArray3[13].email="HGiblets#txstate.edu";
}
int main() {
int stuCount = 39;
firstArray();
secondArray();
thirdArray();
showAllInfo(studentArray,stuCount);
return 0;
}
So you have a few problems. The first is that your arrays are declared inside the functions you've written, so no other code is going to be able to access them. You should declare your arrays inside the main function so that they can be passed as parameters to other functions. If you don't know how to pass an array as a parameter then the rest of this assignment is going to be difficult for you.
Anyway lets start like this, you don't need to write function to set up your arrays, you can do it directly in main, like this
int main()
{
Student firstArray[12] = {
{ "Bob McBoberston", 0, "BMcboberts#txstate.edu" },
...
};
Student secondArray[12] = {
...
};
Student thirdArray[12] = {
...
};
...
}
Now that the arrays are set up you need to write a function to do the sequential search (binary search is more complex, so leave that one for now).
Think about what parameters a function needs and what return value it has. This is always the first step when writing a function, but it's also one that many newbies struggle with.
In the case a sequential search function it needs to know 1) which array is it going to search, 2) how big that array is, 3) what id you are searching for. These are the parameters. It seems reasonable for the function to return the index in the array of the person it's found, or a special value -1 if it doesn't find the id. That's not the only way to do it, but it'll do for now. So putting that together we have
// look for 'id' in 'array' and returns the index if found or -1 if not found
int sequential_search(Person array[], int array_size, int id)
{
...
}
In your main function you would use this function something like this
int main()
{
...
// look for person with id 5
int id = 5;
int index = sequential_search(firstArray, 12, id);
if (index == -1)
cout << "ID " << id << " not found\n";
else
cout << "ID " << id << " is " << firstArray[index].name << "\n";
}
Get the idea? Hopefully this gives you a start. You can do the rest, and ask again if you get into difficulties.

computer lab with pointers

I have this assignment with managing computer labs. Specifically, there are 4 labs, each has a different number of computers. Hence, I want to create a 2D array with pointers, but after trying different stuff, I count on you for this error (please!!!). Below is a part of my programme, up to where the annoying bug comes up.
I got a run-time error after 1 run (terminate called after throwing an instance of std::bad_array_new_length what(): std::bad_array_new_length) when I leave the line with comment //PROBLEM HERE as such.
Add a & in front of lab room, the compiler gave me the error: lvalue required as left operand of assignment.
Newbie in C++, first time with pointers, I'd appreciate any help.
#include <iostream>
using namespace std;
//Global variables
const int SIZE = 4;
typedef int* Stations;
Stations *labroom;
//Function declaration:
void numberOfComputers();//Receive number of computers in each lab
int menu();//Display menu options for users
void menu_processor(int option);//process user's option
int main()
{
numberOfComputers();
menu();
menu_processor(menu());
return 0;
}
void numberOfComputers ()
{ char ans;
for (int i=0;i<SIZE;i++)
{
cout<<"Enter the number of computer stations in lab "<<i+1<<": ";
do
{
cin.get(ans);
} while (ans!='\n');
labroom [i] = new int [ans-'0'];//PROBLEM HERE
cout<<"\n";
}
}
That's not c++ code, it's just (ugly) C.
In C++ we have array for static arrays and vector for dynamic arrays.
First of all, choose the name of your variables or function in a smart way: prefer getNumberOfComputersFromUser instead of numberOfComputers. What numberOfComputers means? A function name must describe what it is doing.
Here a simplified snippet:
#include <vector>
#include <array>
#include <iostream>
using namespace std;
using Station = int;
using LabRooms = array<vector<Station>, 4>;
LabRooms getNumberOfComputersFromUser()
{
LabRooms labRooms;
int roomIndex = 0;
for(auto& computersInLab : labRooms)
{
cout << "Enter the number of computer stations in lab " << ++roomIndex << ": ";
auto computerCount = 0;
cin >> computerCount;
computersInLab.resize(computerCount);
}
return labRooms;
}
Explain
array requires two template arguments: the type and the size. Elements are statically allocated, no need to new because we already know how many rooms we have. The list of computers in each room is not know so we use vector that can dynamically increase or decrease.
using LabRooms = array<vector<Station>, 4>; it's the same of typedef array<vector<Station>, 4> LabRooms but it's clearer I think
for( auto& computersInLab : labRooms) iterate over labRooms and get a reference to its elements (in this case a reference to a vector of Station. This is the same of:
for(int i = 0; i < labRooms.size(); ++i)
{
auto& computersInLab = labRooms[i];
...
}
computersInLab.resize(computerCount); resize the list of computers with the value specified from the user.
Now, labRooms is an array of 4 elements, each element is a list of Station.

c++ pointer to function and void pointers iteraction resulting in wierd things

Im making a little project at home about genetic algorithm. But im trying to make it generic, so i use pointers to function and void pointers. but i think it might be making some problems.
The main goal of this section of the project is to get a pointer to a function, which return a certain struct. The struct containing a void pointer
and when im trying to view the value of where it points too it isn`t quite right.I suspect that maybe the interaction between these two might be causing me some problems.
details:
struct:
struct dna_s{
int size;
void *dna;
};
population is a class contaning all the population for the process. besides, it contains 2 functions as well, init_func and fitter_func which are both pointers to functions.
pointer to function definition:
typedef dna_s (*init_func_t)();
typedef int (*fitter_func_t)(dna_s);
population class:
class population{
private:
// Parameters
int population_size;
node *pop_nodes;
// Functions
init_func_t init_func;
fitter_func_t fitter_func;
public:
population(int pop_size,init_func_t initialization_func){
// Insert parameters into vars.
this->population_size = pop_size;
this->init_func = initialization_func;
// Create new node array.
this->pop_nodes = new node[this->population_size];
for(int i = 0;i < this->population_size; i++){
dna_s curr_dna = this->init_func();
char *s = static_cast<char*>(curr_dna.dna);
cout << s << endl;
this->pop_nodes[i].update_dna(curr_dna);
}
}
};
You can see that in the constructor im inserting a pointer to function, init_func. this function is generating random words.
init_func:
dna_s init_func(){
string alphanum = "0123456789!##$%^&*ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
char init_s[STRING_SIZE+1] = {};
dna_s dna;
// Generate String
for(int i = 0; i < STRING_SIZE; i++){
init_s[i] = alphanum[rand() % alphanum.size()];
}
cout << "-->" << init_s << endl;
// Insert into struct.
dna.size = STRING_SIZE;
dna.dna = static_cast<void*>(&init_s);
// Return it
return dna;
}
the main function is not so interesting but it might be connected:
int main(){
// Init srand
srand(time(0));
// Parameters
int population_size = 10;
population pop(population_size, init_func);
}
now for the interesting part, whats the problem?
in the init_func the cout prints:
-->e%wfF
which is all good
but in the population class the cout prints:
e%Ω²(
and the wierd thing is the first 2 characters will always be the same, but the other 3 will always be this string Ω²(.
example:
-->XaYN7
XaΩ²(
-->oBK9Q
oBΩ²(
-->lf!KF
lfΩ²(
-->RZqMm
RZΩ²(
-->oNhMC
oNΩ²(
-->EGB6m
EGΩ²(
-->osafQ
osΩ²(
-->3#NQt
3#Ω²(
-->D62l0
D6Ω²(
-->tV#mu
tVΩ²(
Your code has a few lifetime issues. In your dna_S struct:
void *dna;
This is a pointer, it points to an object that exists elsewhere. Then, in your init_func:
dna_s init_func(){
...
char init_s[STRING_SIZE+1] = {};
dna_s dna;
...
dna.dna = static_cast<void*>(&init_s);
...
return dna;
}
init_s is a variable that exists inside init_func, you make dna point to that variable and then leave the function. init_s ceases to exist at this point, dna is pointing nowhere useful when the population constructor gets it, causing undefined behavior.
You could work around that by allocating memory with new char[], like you did for pop_nodes, but you are responsible for deleting that memory when it is no longer used.

Why does printing a string array output hexadecimal?

Why does the following program print "0x2ffee4" to the console?
#include <string>
#include <iostream>
using namespace std;
int main() {
string city1[] = "toronto";
cout << city1;
return 0;
}
The first line shouldn't compile, but there's a GCC bug that makes it compile and behave equivalently to something like
std::string city1[] = {"toronto", "toronto", "toronto", "toronto",
"toronto", "toronto", "toronto", "toronto"};
(8, because "toronto" is 8 characters including the terminating null. Yes, that means that if you used "Chargoggagoggmanchauggagoggchaubunagungamaugg", it would create an array of 46 strings, each storing "Chargoggagoggmanchauggagoggchaubunagungamaugg".)
Needless to say, you shouldn't rely on a compiler bug.
Under GCC's buggy behavior, city1 would be an array of std::strings; there's no operator << overload that support printing such a thing. Instead, in std::cout << city1, the array decays to a pointer to its first element, and the address stored in the pointer is printed instead.
You probably meant to write std::string city1 = "toronto";. One string, not an array of it.
The answer given by T.C. is correct, I would also like to mention that if you was expecting to print out "toronto" to the console using cout then you would want to do this:
include <string>
include <iostream>
int main() {
using namespace std;
// string city1[] = "toronto"; // Compiler Error - Do Next Line Instead
string city1[] = { "toronto" };
cout << city1[0];
return 0;
}
Any time you want to initialize an array of any type during declaration you need to use = { }; To set each array's element separated by commas. Look at this code sample:
#include <string>
#include <iostream>
int main() {
using namespace std;
string cities[] = { "New York", "Philadelphia", "Chicago", "Boston" };
// Same As Above Except Size Of Array Is Defined First Then The Elements
string cities[4];
cities[0] = "New York";
cities[1] = "Philadelphia";
cities[2] = "Chicago";
cities[3] = "Boston";
unsigned index = 0;
for ( ; index < 4; index++ ) {
cout << cities[index] << endl;
}
return 0;
}
If you are not initializing the array when declaring it then you must specify the array's size.
int main() {
int iArray[]; // Compiler Error
int iArray[] = { 4, 3, 2, 1, 6 }; // Okay and is the same as
int iArray[5]; // Okay
iArray[0] = 4;
iArray[1] = 3;
iArray[2] = 2;
iArray[3] = 1;
iArray[4] = 6;
return 0;
}
If you are not using the bracket operator with an index value to send to the console output stream std::cout then the hex value you are getting is correct as
T.C had already stated; it is returning the address of the first index. This is why in c / c++ arrays and pointers are similar (they are not the same, but behave almost like one another). The main difference with arrays is that they are constant in size, the size has to be known at compile time, and can not be dynamically changed in size without having to store the contents into a temp variable while creating a new array with a larger size then copying all the data into the new array and then cleaning up the old array. With pointers they do not behave this way, pointers can be dynamically allocated on the heap using new, but also must be deleted when that variable has no more use to prevent memory leaks, if the pointer is delete before hand and something tries to access it that memory address is no longer valid and doesn't belong to the caller, these are normally seen as unhandled exceptions, heap corruption, etc. and will crash your program. The same goes for arrays when you try to index them past their bounds.
#include <iostream>
int main() {
// Arrays Are 0 Indexed
int iArray[3] = { 1, 2, 3 };
// If you try to do this to access the last element
std::cout << iArray[3] << std::endl; // Program Will Crash
// Since Arrays Are 0 Indexed And The Size Of The Array Is 3
// The 3rd Value Is Indexed At 2, And By Trying To Index Location Of Array
// At 3, This Memory Doesn't Belong To You, And It Is Undefined Behavior.
// This Memory Could Contain Nothing, Random Data, Or Even Data That Belongs To
// Something Else Which If Changed Can Even Cause System Failure
return 0;
}