PDA

View Full Version : c++/xcode function parameter passing




chaos2828
Mar 24, 2008, 06:23 PM
Hello, all,

I'm learning about passing function parameters in c++, but I'm having no luck doing so with the code below. Has anyone else had difficulties passing such things with xcode? Or have I missed something really dumb in the code?

(I've already turned this assignment in, but need to figure out how to do this properly for future assingments.)

Thanks for looking.


#include <iostream>
#include <fstream>
#include <string>

using namespace std;

char get_Data(ifstream& in_File, char& romanLet); /* gets Roman numbers, character by character, from input file*/

void print_Roman(ofstream& out_File, char& romanLet); /* prints each Roman character to out_File as it's read into file*/


int main ()
{

// Declare variables

char roman1;
int deci;
int decimal1;
int decimal2;
char operator;
int mathResult;

ifstream mp4romanletrdata;
ofstream outRoman;

// Open file
mp4romanletrdata.open("/Users/rob/getDataFunction/build/Release/mp4romanletrdata");
outRoman.open("outRoman");

// Test opening
if (!mp4romanletrdata || !outRoman)
{ cout << "Unable to open files." << endl;
cout << "Program terminates." << endl;
}



do {
outRoman << "The first Roman Number is " ;

// Calculate first number
do {
roman1 = get_Data(mp4romanletrdata, roman1);
if (roman1 != ' ')
print_Roman(outRoman, roman1);
decimal1 += convert_Roman_to_Decimal(roman1, deci);
}
while (roman1 != ' ');
outRoman << " ( " << decimal1 << " )." << endl;

outRoman << "The second Roman Number is " ;

.// there's more to the program, but this is the beginning of my trouble
.
.
return 0;
}
/*****************************************************
BEGIN
get_Data Function:
*****************************************************/
char get_Data(ifstream& in_File, char& romanLet)
{

char romanLetter;


// Get data char from input file

if (in_File.get(romanLetter))
return romanLetter;
else return ' ';


}/****************************************************
END
get_Data
******************************************************/



/*****************************************************
BEGIN
void print_Roman:
*****************************************************/

void print_Roman(ofstream& out_File, char& romanLet)

{
char romanLetter; // sent from get_Data

out_File << romanLetter; // decimal value totaled in main


}/****************************************************
END
void print_Roman
******************************************************/



Cromulent
Mar 24, 2008, 06:32 PM
Please use code tags when posting your code in future it backs it much easier to read.

In simple terms passing arguments should just be a case of making sure the prototype is correct and then passing the said arguments. For example (in short hand code):



int randomFunction(int, int, int);

int main()
{
int a, b, c;

a = 1;
b = 2;
c = 3;

randomFunction(a, b, c);

return 0;
}

int randomFunction(int a, int b, int c)
{
int x;
a + b + c = x;

printf("%d", x);

return 0;

}



Edit : After looking at your code, why are you passing memory references to the functions? Surely you should be passing the actual file handler or at least a pointer?

chaos2828
Mar 24, 2008, 07:07 PM
(I'll go back and fix the code. Sorry.)

The assignment required passing one function's parameters to another function. We have learned to do that by using reference parameters. Pointers don't come up for another 200 pages or so.

lee1210
Mar 24, 2008, 07:41 PM
I tried *hard* to grok what was going on here. It's admittedly been 8 years since I've seen C++.. but I think I have the general idea. I'm holding back on style criticism, as you didn't ask for a critique, but I will say the style could use some work (I'm not just talking about the indentation lost in the post).

The code you posted would not compile, but I poked at it for a while and came up with this:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

char get_Data(ifstream& in_File, char& romanLet); /* gets Roman numbers, character by character, from input file*/

void print_Roman(ofstream& out_File, char& romanLet); /* prints each Roman character to out_File as it's read into file*/

int convert_Roman_to_Decimal(char,int);

int isRoman(char);

int main ()
{

// Declare variables

char roman1 = ' ';
int deci = 0;
int decimal1 = 0;
int decimal2 = 0;
char o = ' ';
int mathResult = 0;

ifstream mp4romanletrdata;
ofstream outRoman;

// Open file
mp4romanletrdata.open("./mp4romanletrdata");
outRoman.open("outRoman");

// Test opening
if (!mp4romanletrdata || !outRoman)
{
cout << "Unable to open files." << endl;
cout << "Program terminates." << endl;
}



{
outRoman << "The first Roman Number is " ;

// Calculate first number
do {
roman1 = get_Data(mp4romanletrdata, roman1);
if (isRoman(roman1)) {
print_Roman(outRoman, roman1);
decimal1 += convert_Roman_to_Decimal(roman1, deci);
}
} while (roman1 != ' ');
outRoman << " ( " << decimal1 << " )." << endl;

outRoman << "The second Roman Number is " ;
}
// there's more to the program, but this is the beginning of my trouble


return 0;
}
/*****************************************************
BEGIN
get_Data Function:
*****************************************************/
char get_Data(ifstream& in_File, char& romanLet)
{

char romanLetter;


// Get data char from input file

if (in_File.get(romanLetter)) {
cout << "Read the letter: " << romanLetter << endl;
return romanLetter;
} else {
return ' ';
}


}/****************************************************
END
get_Data
******************************************************/

int convert_Roman_to_Decimal(char a,int b){
return 1;
}


/*****************************************************
BEGIN
void print_Roman:
*****************************************************/

void print_Roman(ofstream& out_File, char& romanLet)

{

out_File << romanLet; // decimal value totaled in main


}/****************************************************
END
void print_Roman
******************************************************/

int isRoman(char testChar) {
int retVal = 0;
switch(testChar) {
case 'I' :
case 'V' :
case 'X' :
case 'L' :
case 'C' :
case 'D' :
case 'M' : retVal = 1;
break;
default: retVal = 0;
break;
}
cout << "Testchar is: " << testChar << "\t is? " << retVal << endl;
return retVal;
}

The function calls seem fine. The other logic seemed a bit off. In print_Roman you passed in a char variable, then declared a similarly named variable, then printed that local thing instead of what was passed in. Also, a lot of variables were not initialized. I can't say i that was hurting or not, but it's better to be sure.

You didn't leave your implementation of convert_Roman_to_Decimal, but I don't know how you would implement it the way you have things set up. I don't believe you can parse roman numerals one character at a time.

In a previous thread you started, i posted this:
http://forums.macrumors.com/showthread.php?p=5172983#post5172983

If you keep track of things a bit differently it might be possible, but I really thing tokenizing is the right way to go about it.

Of everything I saw the function calls actually seemed sound. It may have been some of the other logic that was muddling things up.

-Lee

Edit: I don't mean to sound harsh, I realize you are just starting out. I'd just like to promote good style from the start, and posting questions with usable code samples people can play with. People here like to help, but they'll be much more willing if you make it easier to concentrate on the functionality of the code, not getting something that will build. Also, at least when I was trying to get it to build my compiler choked on "char operator". Operator is a reserved word in C++, so I'd avoid it even if it makes the most sense.

chaos2828
Mar 24, 2008, 08:04 PM
The function calls seem fine. The other logic seemed a bit off. In print_Roman you passed in a char variable, then declared a similarly named variable, then printed that local thing instead of what was passed in. Also, a lot of variables were not initialized. I can't say i that was hurting or not, but it's better to be sure.

You didn't leave your implementation of convert_Roman_to_Decimal, but I don't know how you would implement it the way you have things set up. I don't believe you can parse roman numerals one character at a time.

This was the assignment: take an input file read an additive roman numeral in one character at a time, print it out one character at a time, translate it to a decimal one character at a time, do a math problem with it, translate the result to roman numerals and print it out. All done with functions. If the logic seems a bit off, it may because this particular problem drove me over the edge. And you can parse 'em one at a time, but it does hurt!


Can you elaborate on what you mean by tonkenizing? Your usage doesn't sync with how my book uses the term. I don't mean to be obtuse, but I'm new!


Of everything I saw the function calls actually seemed sound. It may have been some of the other logic that was muddling things up.

That's quite possible. I'm still not getting those references to pass in much simpler programs though.

chaos2828
Mar 24, 2008, 08:23 PM
Edit: I don't mean to sound harsh, I realize you are just starting out. I'd just like to promote good style from the start, and posting questions with usable code samples people can play with. People here like to help, but they'll be much more willing if you make it easier to concentrate on the functionality of the code, not getting something that will build. Also, at least when I was trying to get it to build my compiler choked on "char operator". Operator is a reserved word in C++, so I'd avoid it even if it makes the most sense.

No worries. You can't scare me.

(I changed operator in the final version, I didn't save the changes tho' ... too much caffeine.)

lee1210
Mar 24, 2008, 08:42 PM
Here's what I came up with. Not sure where the operator comes from, I just used +.

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

char get_Data(ifstream& in_File, char& romanLet); /* gets Roman numbers, character by character, from input file*/

void print_Roman(ofstream& out_File, char& romanLet); /* prints each Roman character to out_File as it's read into file*/

int convert_Roman_to_Decimal(char&,int&);

int isRoman(char&);

string decimalToRoman(int&);

int main ()
{

// Declare variables

char roman1 = ' ';
int temp = 0;
int deci = 0;
int decimal1 = 0;
int decimal2 = 0;
int result = 0;
char o = ' ';
int mathResult = 0;

ifstream mp4romanletrdata;
ofstream outRoman;

// Open file
mp4romanletrdata.open("./mp4romanletrdata");
outRoman.open("outRoman");

// Test opening
if (!mp4romanletrdata || !outRoman)
{
cout << "Unable to open files." << endl;
cout << "Program terminates." << endl;
}



{
outRoman << "The first Roman Number is " ;

// Calculate first number
decimal1=0;
do {
roman1 = get_Data(mp4romanletrdata, roman1);
if (isRoman(roman1)) {
print_Roman(outRoman, roman1);
temp = convert_Roman_to_Decimal(roman1,deci);
if(temp != -1) {
decimal1 += convert_Roman_to_Decimal(roman1, deci);
}
}
} while (roman1 != '\n');
outRoman << " ( " << decimal1 << " )." << endl;
decimal2=0;
outRoman << endl << "The second Roman Number is ";
do {
roman1 = get_Data(mp4romanletrdata, roman1);
if (isRoman(roman1)) {
print_Roman(outRoman, roman1);
temp = convert_Roman_to_Decimal(roman1,deci);
if(temp != -1) {
decimal2 += convert_Roman_to_Decimal(roman1, deci);
}
}
} while (roman1 != '\n');
outRoman << " ( " << decimal2 << " )." << endl;
result=decimal1 + decimal2;
outRoman << "The result of " << decimal1 << " + " << decimal2
<< " = " << decimalToRoman(result) << endl;
}
// there's more to the program, but this is the beginning of my trouble


return 0;
}
/*****************************************************
BEGIN
get_Data Function:
*****************************************************/
char get_Data(ifstream& in_File, char& romanLet)
{

char romanLetter;


// Get data char from input file

if (in_File.get(romanLetter)) {
//cout << "Read the letter: " << romanLetter << endl;
return romanLetter;
} else {
return ' ';
}


}/****************************************************
END
get_Data
******************************************************/

int convert_Roman_to_Decimal(char& a,int& b){
int retVal = 0;
switch(a) {
case 'I' : retVal=1;
break;
case 'V' : retVal=5;
break;
case 'X' : retVal=10;
break;
case 'L' : retVal=50;
break;
case 'C' : retVal=100;
break;
case 'D' : retVal=500;
break;
case 'M' : retVal=1000;
break;
default: retVal = -1;
break;
}
return retVal;
}


/*****************************************************
BEGIN
void print_Roman:
*****************************************************/

void print_Roman(ofstream& out_File, char& romanLet)

{

out_File << romanLet; // decimal value totaled in main


}/****************************************************
END
void print_Roman
******************************************************/

int isRoman(char& testChar) {
int retVal = 0;
switch(testChar) {
case 'I' :
case 'V' :
case 'X' :
case 'L' :
case 'C' :
case 'D' :
case 'M' : retVal = 1;
break;
default: retVal = 0;
break;
}
//cout << "Testchar is: " << testChar << "\t is? " << retVal << endl;
return retVal;
}


string decimalToRoman(int& dec_num){
string ret = "";
int temp = dec_num; //Using a temp var b/c pass by ref. Don't want to change value
while(temp > 0) {
//cout << "Temp is: " << temp << " ret is: " << ret << endl;
if(temp >= 1000) {
ret.append("M");
temp-=1000;
} else if(temp >= 500) {
ret.append("D");
temp-=500;
} else if(temp >= 100) {
ret.append("C");
temp-=100;
} else if(temp >= 50) {
ret.append("L");
temp-=50;
} else if(temp >= 10) {
ret.append("X");
temp-=10;
} else if(temp >= 5) {
ret.append("V");
temp-=5;
} else {
ret.append("I");
temp-=1;
}
}
return ret;
}

Again, there are shortcuts on the roman numerals. If you pass in 4, you'll get IIII instead of IV, but it seems like that would suffice for this exercise. I don't know how different the rest of your code was from this, but the general calling mechanics seem to work.

-Lee

lee1210
Mar 24, 2008, 08:49 PM
Didn't expand on the tokenization in that last post. I meant to break the string into meaningful tokens. For example, if you have:
MMCMCCCIVII

The tokens are:
M = 1000
M = 1000
CM = 900
C = 100
C = 100
C = 100
IV = 4
I = 1
I = 1

in the case of roman numerals you have to break things up into the meaningful chunks that can be interpreted as a single decimal number. As you can see, the result would be much different if you treated each character atomically(as its own token). The maximum token length for roman numerals is 2, so that makes it a little easier.

Generally when someone says tokenize they mean break apart a string into components. The *most* common case is breaking on a separator such as a tab, :, etc. In this case where the components are broken is less obvious.

-Lee

chaos2828
Mar 24, 2008, 08:58 PM
Lee,

I really didn't have any problems writing the individual functions, and they all worked fine independently. I didn't post them all here because the problem was getting my parameters to pass between them, and the first calls/functions are sufficient to illustrate that.

Since there are still people who haven't turned in this assignment, I'm not interested in posting everything I wrote on the remote chance they'll feel free to plagiarize my sorry stuff. If what I've posted doesn't illuminate the problem, I'll have to wait for the prof to return it.

Thanks for looking though...

ScoobyMcDoo
Mar 25, 2008, 02:14 PM
So, chaos, I'm not sure you ever figured this out, so I thought I would share what I noticed. Basically, you are not assigning to nor using the values or references you are passing. I detailed it in the code snippets below:



/*****************************************************
BEGIN
get_Data Function:
*****************************************************/
// So you are passing in a reference to romanLet here, but never
// assigigning to it.
char get_Data(ifstream& in_File, char& romanLet)
{

char romanLetter;


// Get data char from input file

if (in_File.get(romanLetter))
// instead of the line below, returning the value
// assign it
// return romanLetter;
romanLet = romanLetter; // now you are sending the value back to the caller
// else return ' ';
// same here
else
romanLet = ' ';

// now return it
return romanLet;

}/****************************************************
END
get_Data
******************************************************/



/*****************************************************
BEGIN
void print_Roman:
*****************************************************/
// Now in this function, there is no reason to pass by reference, so
//void print_Roman(ofstream& out_File, char& romanLet)
void print_Roman(ofstream& out_File, char romanLet)

{
// You really don't have to create this romanLetter variable here,
// but if you really want to, you need to set it to what you passed in
// otherwise it just contains garbage.

char romanLetter( romanLet ); // sent from get_Data

out_File << romanLetter; // decimal value totaled in main


}/****************************************************
END
void print_Roman
******************************************************/

Hope that helps.

chaos2828
Mar 26, 2008, 01:33 PM
Scooby, thanks for looking.

When I've tried it that way, I get this: "error: declaration of 'std::string name;' shadows a parameter" and it won't compile. It does compile the way I've got it, but the results are junk.

sh0ck3r
Mar 26, 2008, 06:45 PM
Hey, I'm having a problem with XCode when opening input documents..
Where is the root folder for them? I mean.. in MS Windows the instruction infile.open("test.txt"); would be ok if you had the test.txt file within the project folder, but in XCode that doesn't happen.. i'm only able to open that file if I explicit all the path to the file: "/users/.../test.txt" :S

chaos is your .open function working properly? this is because you have outRoman.open("outRoman"); just like me, except for the .txt suffix..

P.S: I'm using XCode 3.0 btw.

lee1210
Mar 26, 2008, 06:51 PM
Hey, I'm having a problem with XCode when opening input documents..
Where is the root folder for them? I mean.. in MS Windows the instruction infile.open("test.txt"); would be ok if you had the test.txt file within the project folder, but in XCode that doesn't happen.. i'm only able to open that file if I explicit all the path to the file: "/users/.../test.txt" :S

chaos is your .open function working properly? this is because you have outRoman.open("outRoman"); just like me, except for the .txt suffix..

P.S: I'm using XCode 3.0 btw.

See this thread, it is applicable to your issue:
http://forums.macrumors.com/showthread.php?t=460868

sh0ck3r
Mar 26, 2008, 07:24 PM
lee1210 i had already read that i guess.. but it didn't resolve anything.

Fortunatly, shortly after I posted I found the answer in another thread..
http://forums.macosxhints.com/archive/index.php/t-35892.html

As for me, my program was running under the user root directory.. :\

Sorry to change the subject of the post. Thanks anyways ;)

ScoobyMcDoo
Mar 26, 2008, 09:53 PM
Scooby, thanks for looking.

When I've tried it that way, I get this: "error: declaration of 'std::string name;' shadows a parameter" and it won't compile. It does compile the way I've got it, but the results are junk.

That error is unrelated and is because of some other error in your program. The errors in your program I pointed out are indeed errors and the recommendations are correct - but take them or leave them.