By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,238 Members | 1,787 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,238 IT Pros & Developers. It's quick & easy.

Passing Structure to a function

P: n/a
I am a little confused with code I am looking at. My c++ book does not go
into passing a structure to a function so I pulled out a c book which does.
and I do not understand the prototype verses the actual function call. I
will post the code below of the structure, the prototype and and function
call and if someone can explain this I would be very appreciative:

struct data
{
float amount;
string fname;
string lname;
} rec;

//prototype
void print_rec(struct data x);
//function call
print_rec(rec);

Where I am confused at is with the difference between the prototype and and
the function call. Where does the x come from in the passing parameters??

Thank you,
Shawn Mulligan

Jul 19 '05 #1
Share this Question
Share on Google+
5 Replies


P: n/a
While your below code will technically work as presented, it will not work
this way if you extended it to, say, need to print out more than two of
these structs.

The reason it works is because "phone" is a global identifier, meaning that
the print() function can see it and use it. However, it you were to make
phone[] a local variable to main() (see below), it would no longer be seen
in print(). This is why there is a way to pass in arguments to the
function.
The "x" stuff in your original question is just that -- an argument for the
function itself. It isn't seen as an error as it is technically allowed to
not have a variable name for an argument -- incase you never need to use it.

Here's a modified version of your code that may help:

#include <string>
#include <iostream>

struct phonerec
{
string fname;
string lname;
}; // Don't need a global here -- we'll use a local in main() instead.

using namespace std;

// While the original was completely correct, giving a desciptive
// variable name for arguments is helpful for IDEs that use
// prototypes to remind you what a function expects (VC++
// comes to mind, but I know others do too)

void print(struct phonerec theRecord);

int main()
{
phonerec data[5]; // Heres our local data. Also, to make it more
interesting, we'll have 5.
int x;
x = 0;

// The collection stuff is nearly identical to yours, except I modified it
to collect 5 of them.
// The reason I used < is because I find it "cleaner" to do it this way,
instead of <=4,
// because the second can make the actual number seem misconstrued (I see
it
// atleast once a day from some of the first-year programmers I teach)

while(x<5)
{
cin >> phone[x].fname;
cin >> phone[x].lname;
x++;
}

// Here's where things go a bit different. Instead of calling print with
the entire list,
// print() will be modified to take in single entry and print it out.
So, it's now up to main()
// to loop through them.

x = 0; // always remember to reset your 'x'!
while (x < 5)
{
print(data[x]); // send the 'x'th element in the array to print().
}
return 0;
}

void print(struct phonerec theRecord) // Note: you don't have to name the
argument the same as the prototype, but descriptive names are nice here,
too.
{
cout << theRecord.fname<<" "<< theRecord.lname<<endl;
}

If you have any more questions don't hesitate to ask :)

- Alex

"kazack" <ka****@talon.net> wrote in message
news:wY********************@news1.epix.net...
Okay here is my code for a simple store first name last name of 2 people
passing it to a function to print both records to the screen. Please let
me know what is wrong with this is anything. The code works with no problem but is it the proper way of doing it?

Also must a structure be defined outside of main?
The books do not cover that but that is where it is showing all defined
structures at. I did try moving the structure into main with the following code and got like 6 different compile errors. So I just wanted to know for sure if this is not the case how would you modify the code to work while
putting a structue inside of main. From everything I was taught so far you want as little as possible outside of main so that the scope is not global.

#include <string>
#include <iostream>

using namespace std;
void print(struct phonerec);
struct phonerec
{
string fname;
string lname;
}phone[2];

int main()
{
int x;
x = 0;
while(x<=1)
{
cin >> phone[x].fname;
cin >> phone[x].lname;
x++;
}
print(phone[2]);

return 0;
}
void print(struct phonerec)
{
int x = 0;
while (x<=1)
{
cout << phone[x].fname<<" "<<phone[x].lname<<endl;
x++;
}
}

Thank You for your help and understanding once again,
Shawn Mulligan

---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.536 / Virus Database: 331 - Release Date: 11/3/2003
Jul 19 '05 #2

P: n/a
Okay I follow it now. well in the mean time I have been working on a
project just to understand the concept of structures. It is a little
phonebook program that inputs firstname, last name and phone number. I have
the input, output to file and menu done. I have not yet worked on the
search feature yet. But before I go further I just want to make sure I am
on the right track with all of this. So here is my code I have been working
on.

NOTE: THIS IS NOT A PROBLEM IN ANY OF MY BOOKS: I also do not have no
error checking at all in this program for I am the only one going to be
using it and it is only to understand the segment on Structures:

#include <string>
#include <iostream>
#include <fstream>
using namespace std;

int Menu();
void Menu_Selection(int,struct phonerec phone);
void Input_New_Record(struct phonerec phone);
void Write_To_File(struct phonerec phone);

struct phonerec
{
string fname;
string lname;
string number;
};
int main()
{
phonerec phone;
int Menu_Choice;
Menu_Choice = Menu();

if(Menu_Choice != 3)
{
Menu_Selection(Menu_Choice,phone);
main();
}
return 0;
}
void Menu_Selection(int Menu_Choice,struct phonerec phone)
{
switch(Menu_Choice)
{
case 1:
{
Input_New_Record(phone);
break;
}
case 2:
{
//Reserved For Menu Option 2 to search for record
// When this feature is set up it will input one record at
// a time into the struct and check to see if search is equal
// and will do this for all records. I know this is not the
//most efficient way but it lets me know if I am using
//structs properly.
break;
}
}
}

void Input_New_Record(struct phonerec phone)
{
cout << "Enter The First Name: ";
cin >> phone.fname;
cout << endl << "Enter The Last Name: ";
cin >> phone.lname;
cout << endl << "Enter The Phone Number: ";
cin >> phone.number;
Write_To_File(phone);
}

void Write_To_File(struct phonerec phone)
{
ofstream outdata;
outdata.open("phonebook.dat",ios::app);
outdata << phone.fname;
outdata << ",";
outdata << phone.lname;
outdata << ",";
outdata << phone.number;
outdata << endl;
outdata.close();
}
int Menu()
{
int choice;
while(choice != 1 && choice !=2 && choice !=3)
{
cout << endl << endl << endl;
cout << "1. Input New Record" << endl;
cout << "2. Search For A Record" << endl;
cout << "3. Quit Program" << endl;
cout << "Please Enter A Choice: ";
cin >> choice;
}
return choice;
}

Thank you once again. And also how valuable are unions? From what I have
glanced at all it is is a renamed structure or something along that line.
Is it something worth reading or skip it? I know I really don't want to
skip nothing but I don't want to waste time with stuff that I will not use
either.

Shawn Mulligan
Jul 19 '05 #3

P: n/a
In article <kw********************@news1.epix.net>,
kazack <ka****@talon.net> wrote:

struct data
{
float amount;
string fname;
string lname;
} rec;
This does two things:

(1) It defines a data type named 'data', as a struct with the specified
fields.

(2) It declares a variable named 'rec', of type 'data'.

The usual practice in C++ is to separate the two actions:

struct data
{
float amount;
string fname;
string lname;
};

data rec;

This is mainly because data types are usually defined outside of any
function, so they are available in any function in the current scope,
whereas variables are usually declared inside a function, so they are
directly usable only within that function.

To put it another way, types are usually defined globally, but variables
are usually defined locally.
//prototype
void print_rec(struct data x);


The "struct" keyword is completely unnecesary here, in C++. C++ compilers
accept it only for backward compatibility with C.

--
Jon Bell <jt*******@presby.edu> Presbyterian College
Dept. of Physics and Computer Science Clinton, South Carolina USA
Jul 19 '05 #4

P: n/a


kazack wrote:


#include <string>
#include <iostream>
#include <fstream>
using namespace std;

int Menu();
void Menu_Selection(int,struct phonerec phone);
void Input_New_Record(struct phonerec phone);
void Write_To_File(struct phonerec phone);
This will not work. Youcan't use struct phonerec before
it is declared.
Always remember: The compiler reads you source code
from top to bottom. Every word he does not know from
what has been read previously, is an error (it could
be a typo). Thus you need to move the prototypes
down until struct phonerec is introduced to the compiler.

Also: The keyword struct is superflous here.

struct phonerec
{
string fname;
string lname;
string number;
};

int main()
{
phonerec phone;
int Menu_Choice;
Menu_Choice = Menu();

if(Menu_Choice != 3)
{
Menu_Selection(Menu_Choice,phone);
main();
}
return 0;
}

void Menu_Selection(int Menu_Choice,struct phonerec phone)
{
switch(Menu_Choice)
{
case 1:
{
Input_New_Record(phone);
break;
}
case 2:
{
//Reserved For Menu Option 2 to search for record
// When this feature is set up it will input one record at
// a time into the struct and check to see if search is equal
// and will do this for all records. I know this is not the
//most efficient way but it lets me know if I am using
//structs properly.
break;
}
}
}

void Input_New_Record(struct phonerec phone)
{
cout << "Enter The First Name: ";
cin >> phone.fname;
This will not work.
It will not work for the same reason that

void foo( int i )
{
i = 5;
}

does not what you think it does.
Both functions (yours and mine) receive a *copy* of the
callers argument. Altering that copy will not alter the
variable the caller has used to make the call. While in
my example it is not obvious that this was the intended
behaviour, in your example it is: You want the entered
values routed to whoever has called this function.

Take your book and study again: 'call by value' versus 'call by reference'
cout << endl << "Enter The Last Name: ";
cin >> phone.lname;
cout << endl << "Enter The Phone Number: ";
cin >> phone.number;
Write_To_File(phone);
}

void Write_To_File(struct phonerec phone)
{
ofstream outdata;
outdata.open("phonebook.dat",ios::app);
outdata << phone.fname;
outdata << ",";
outdata << phone.lname;
outdata << ",";
outdata << phone.number;
outdata << endl;
outdata.close();
}

int Menu()
{
int choice;
while(choice != 1 && choice !=2 && choice !=3)
{
cout << endl << endl << endl;
cout << "1. Input New Record" << endl;
cout << "2. Search For A Record" << endl;
cout << "3. Quit Program" << endl;
cout << "Please Enter A Choice: ";
cin >> choice;
}
return choice;
}

Thank you once again. And also how valuable are unions?
They are not used much often.
From what I have
glanced at all it is is a renamed structure or something along that line.
You read wrong.
A union is a collection where all members share the same memory region.
In contrast to a struct where everey member has its own memory.
Is it something worth reading or skip it?


Nothing is worth to be skipped.
If you think learning to program is something you can learn fast, in a week
or two, you are mistaken. It takes its time and there are lots of things
to learn. Reserve at least half a year to learn the basics.

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 19 '05 #5

P: n/a
"kazack" <ka****@talon.net> wrote in message news:<GA********************@news1.epix.net>...
[snip]
#include <string>
#include <iostream>
#include <fstream>
using namespace std;

int Menu();
void Menu_Selection(int,struct phonerec phone);
void Input_New_Record(struct phonerec phone);
void Write_To_File(struct phonerec phone);
You don't need the 'struct' keyword to refer to a structure type,
only to declare/define it. I suspect the only reason you used the
'struct' keyword above is because otherwise you got compiler errors.
The reason for the errors is that phonerec hasn't been declared or
defined yet. You should probably move the structure defintion (below)
so that it precedes the function declarations, and then remove the
'struct' keyword from the function declarations.

What you have actually done is essentially equivalent to this:

struct phonerec;
void Menu_Selection(int, phonerec phone);
void Input_New_Record(phonerec phone);
void Write_To_File(phonerec phone);

The first line above declares (but does not define) the phonerec
structure. A structure declaration merely says that a structure
exists but not what its members are. Some uses of a type require
its defintion (e.g., creating an instance of the type), but others
require only its declaration (e.g., creating a pointer or reference
to the type).

A declaration like the one above is called a "forward declaration"
because it declares a struct which will defined later. This is
sometimes necessary. For example, if struct A contains a member of
type B* and struct B contains a member of type A*, then either A
or B must be forward declared.

It is also possible for a struct to be declared but not defined at
all, or at least not publicly. This is called an "opaque struct".
The FILE structure in the C runtime library is an example of this.
Windows handles are another example. Yet another is the "Pimpl idiom"
(Google is your friend).
struct phonerec
{
string fname;
string lname;
string number;
};
int main()
{
phonerec phone;
int Menu_Choice;
Menu_Choice = Menu();
I recommend using an enum rather than an int for Menu_Choice. Then
you can use meaningful names instead raw numbers like 1, 2, 3.

I also like function names to be verbs and type names to be nouns.
Menu would be a good name for a class that represented a menu. A
better name for your function in my opinion would be Show_Menu.

Note that you can also declare and initialize a variable in one
step, and this is usually preferred in C++, e.g.:

MenuChoice choice = Show_Menu();

if(Menu_Choice != 3)
{
Menu_Selection(Menu_Choice,phone);
main();
}
Note that you're passing phone by value to Menu_Selection. This
means a copy of phone is passed to the function. Anything the
function does with phone will only modify its copy. The phone
object in main will be untouched.

Also, you probably just want to have a loop here rather than
calling main recursively:

for (MenuChoice choice = Show_Menu();
choice != QuitMenuItem;
choice = Show_Menu())
{
Process_Command(choice, &phone);
}

return 0;
}
void Menu_Selection(int Menu_Choice,struct phonerec phone)
{
switch(Menu_Choice)
{
case 1:
{
Input_Phone_Record(phone);
break;
}
case 2:
{
//Reserved For Menu Option 2 to search for record
// When this feature is set up it will input one record at
// a time into the struct and check to see if search is equal
// and will do this for all records. I know this is not the
//most efficient way but it lets me know if I am using
//structs properly.
break;
}
}
}
Again, I would choose a more verb-like name for the above function
(e.g., ProcessCommand) and use an enum instead of raw integers to
represent the menu selection.

Also, phone is passed by value throughout your program, which
means if any function modifies phone it changes only its own copy.
I would probably use something more like the following function
declarations:

void Process_Command(MenuChoice choice, phonerec* phone);
phonerec Input_Phone_Record();
void Write_Phone_Record(const phonerec& phone);

In the first function, phone is an "in/out" parameter so it is
declared as a pointer (alternatively it could be declared as a
non-const reference). The second function does not use the value
of the existing phone record but simply returns a new one. In the
third function, phone is an "in" parameter; it could be passed by
value but it is more efficient to declare it as a const reference.
void Input_New_Record(struct phonerec phone)
{
cout << "Enter The First Name: ";
cin >> phone.fname;
cout << endl << "Enter The Last Name: ";
cin >> phone.lname;
cout << endl << "Enter The Phone Number: ";
cin >> phone.number;
Write_To_File(phone);
}

void Write_To_File(struct phonerec phone)
{
ofstream outdata;
outdata.open("phonebook.dat",ios::app);
outdata << phone.fname;
outdata << ",";
outdata << phone.lname;
outdata << ",";
outdata << phone.number;
outdata << endl;
outdata.close();
}
The following function is essentially equivalent to the
one above but is, I think, a little more concise and readable.
Also the parameter is declared as a const reference which
reduces unnecessary copying of the phonerec structure.

void Write_Phone_Record(const phonerec& phone)
{
ofstream outdata("phonebook.dat", ios::app);
outdata << phone.fname << ',' << phone.lname << ',' << phone.number << endl;
}
int Menu()
{
int choice;
while(choice != 1 && choice !=2 && choice !=3)
{
cout << endl << endl << endl;
cout << "1. Input New Record" << endl;
cout << "2. Search For A Record" << endl;
cout << "3. Quit Program" << endl;
cout << "Please Enter A Choice: ";
cin >> choice;
}
return choice;
}

Thank you once again. And also how valuable are unions?
They have their place, but for the most part they're dangerous and evil.
From what I have
glanced at all it is is a renamed structure or something along that line.


There's a crucial difference. All the members of a union share the same
storage. So if you have a union of, say, an int, a long, and a char*, only
one of those members is actually valid at any given time -- and it's up to
you the programmer to know which.

It looks like you've picked a good learning excercise. Good luck!
Jul 19 '05 #6

This discussion thread is closed

Replies have been disabled for this discussion.