Somebody REPLY!!! Function HELP PLEASE!

I have pieced together a small program that reads a file and translates Roman numerals to integers. The program then solves the arithmatic with the integers and displays the answer. After that, it is redisplayed as the Roman numeral answer.

My main focus now is trying to figure out how to finish this program as functions (instead of straight code) that uses a file. This is kind of a from the bottom up approach with learning programming so far, please bear with me. I am having difficulty with functions due to fuzziness as to what type of function I should be writing (int, char, etc , or void). I am stuck guessing how I will pass each value (function parameters?) onto the next function after.

If any one could show me the basic setup of the call stack (protype, main, function) and how the functions swap the values between functions, I'd greatly appreciate it. I am using for study D.S. Malik's "C++ Programming" 5th edition and am not fully grasping his method of function setup yet.

One other thing, why the heck is my ifstream grabbing the last line twice at the end?

Any help would be greatly appreciated.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
  #include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include <sstream>
using namespace std;

void romAns(); // function prototypes that are setup but not used yet //
void arithFunc();



void main()
{
   
string romNums;
string base;
string divd;
string romAns;
string temp;

int i;
int j;
int k;
int conV;
int conVV;
int conVVV;
int answer;
int baseNum;
int divNum;

char opp;
char spaces (' ');

enum romans {I = 1, IV =4, V = 5, IX = 9, X = 10, XL = 40, L = 50, XC = 90, C = 100, CD = 400, D = 500, CM = 900, M = 1000};// this needs to be a function//
 
ifstream rNums;
ofstream numNums;

rNums.open ("Rnum.txt"); // the file name for the input file (text of the file is at the bottom) //
numNums.open ("numMth.txt"); // an output from the program file that is not in use yet //

while (!rNums.eof())
	{
		int conV = 0;
		int conVV = 0;
		rNums >> base;
		rNums.get (spaces);
		rNums >> divd;
		rNums.get (spaces);
		rNums >> opp;
		


		cout << base << " " << opp << " " << divd << " " << '\n';

		

		
	for (int i = 0; i < base.length(); i++ )  //you could use roman.length() if you like
	{
		switch (base[i]) //roman.at(i) is just a more secure way to do it
		{
			case 'M': conV += M; break;
			case 'D': conV += D; break;
			case 'C': conV += C; break;
			case 'L': conV += L; break;
			case 'X': conV += X; break;
			case 'V': conV += V; break;
			case 'I': conV += I; break;
				if (base[i + 1] != 'I' && i + 1 != base.size())
					conV-=1;
				else
					conV+=1;
				break;
		}
		
	}
	
	for (int j = 0; j < divd.length(); j++)  //you could use roman.length() if you like
	{
		switch (divd[j]) //roman.at(i) is just a more secure way to do it
		{
			case 'M': conVV += M; break;
			case 'D': conVV += D; break;
			case 'C': conVV += C; break;
			case 'L': conVV += L; break;
			case 'X': conVV += X; break;
			case 'V': conVV += V; break;
			case 'I': conVV += I; break;
				if (divd[j + 1] != 'I' && j + 1 != divd.size())
					conVV-=1;
				else
					conVV+=1;
				break;
		}
		
	} 
 
 

		switch (opp)
	    {
		    case '+':
				answer = conV + conVV;
				break;
            case '-':
				answer = conV - conVV;
				break;
			case '*':
				answer = conV * conVV;
				break;
			case '/':
				answer = conV / conVV;
				break;
				
			default:
				cout << "No solution... " << endl;
				break;
		}
		


		cout << conV << " " << opp << " "  << conVV << " = " << answer << " or ";

		// my while loop that changes integer back to roman, (I could probably do it in less lines with more practice) //
	while (answer > M)
	{
			if (answer > M)
			{
			answer = answer - M;
			cout << "M";
			}
		
			
			else if (answer < M)

			answer = answer;
	}
			
	while (answer > D)
	{
			if (answer > D)
			{	
		    answer = answer - D;
		     cout << "D";
			}
			else if (answer < D)

			 answer = answer;
	}
	while (answer > C)
	{
			if (answer > C)
			{
		    answer = answer - C;
		 
			 cout << "C";
			}
			else if (answer < C)

			answer = answer;
	}
	while (answer > XC)
	{
			if (answer > XC)
			{
		    answer = answer - XC;
		 
			 cout << "XC";
			}
			else if (answer < XC)

			answer = answer;
	}
	while (answer > L)
	{
			if (answer > L)
			{
		    answer = answer - L;
		    cout << "L";
			}
			else if (answer < L)

			answer = answer;
	}
	while (answer > XL)
	{
			if (answer > XL)
			{
		    answer = answer - XL;
		    cout << "XL";
			}
			else if (answer < XL)

			answer = answer;

	}
	while (answer >= X)
	{
			if (answer >= X)
			{
			answer = answer - X;
		 
			 cout << "X";
			}
			else if (answer < X)
			answer = answer;
	}
	while (answer >= IX)
	{
			if (answer >= IX)
			{
			answer = answer - IX;
		 
			 cout << "IX";
			}
			else if (answer < IX)
			answer = answer;
	}
	while (answer > V)
	{
			if (answer > V)
			{
			answer = answer - V;
		 
			 cout << "V";
			}
			else if (answer < V)

			 answer = answer;
	}
	while (answer >= IV)
	{
			if (answer >= IV)
			{
			answer = answer - IV;
		 
			 cout << "IV";
			}
			else if (answer < IV)

			 answer = answer;
	}
	while (answer > 0)
	{
			if (answer >= 1)
			{
			answer = answer - I;
		 
			 cout << "I";
			}
		    else if (answer < 1)

			answer = answer;
	}
		cout << endl;

	

		/*string convertInt(int answer);
				{
					stringstream temp;//create a stringstream
					temp << answer;//add number to the stream
					cout << temp.str();//return a string with the contents of the stream
				}
				
	   cout << " " << temp << endl;
	   */ // the above is a method to change the integer answer to a string, it's there for another purpose not implemented // 
	   

}
	   
   system("pause");

}


/* below is the text file used with the program above */

MCCXXVI    CV    +
MCCXXVI   MCCXXVI    /
V  I  -
MDCLXVI    III   *
DL DXXXXXVIII    -
D  L  /
MDI   CXI    +
XXV    IIII     /
XI  CII  *
you can put almost anything in a function. normally if you see that you are repeating your code. you need to create a function for it. it also depends if you want to return values. you would need learn pass by value and pass by reference.

for starters you can just return void. just to get hang of functions. and no parameters.

create a prototype before main

1
2
// prototype 
void function();


put this after main()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void function()
{
for (int i = 0; i < base.length(); i++ )  //you could use roman.length() if you like
	{
		switch (base[i]) //roman.at(i) is just a more secure way to do it
		{
			case 'M': conV += M; break;
			case 'D': conV += D; break;
			case 'C': conV += C; break;
			case 'L': conV += L; break;
			case 'X': conV += X; break;
			case 'V': conV += V; break;
			case 'I': conV += I; break;
				if (base[i + 1] != 'I' && i + 1 != base.size())
					conV-=1;
				else
					conV+=1;
				break;
		}
		
	}
}


now you can replace

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
for (int i = 0; i < base.length(); i++ )  //you could use roman.length() if you like
	{
		switch (base[i]) //roman.at(i) is just a more secure way to do it
		{
			case 'M': conV += M; break;
			case 'D': conV += D; break;
			case 'C': conV += C; break;
			case 'L': conV += L; break;
			case 'X': conV += X; break;
			case 'V': conV += V; break;
			case 'I': conV += I; break;
				if (base[i + 1] != 'I' && i + 1 != base.size())
					conV-=1;
				else
					conV+=1;
				break;
		}
		
	}


with just in your main function.

function();
Something of this style should work. I've omitted the function details, it's just a case of taking your existing code and putting it in there - with appropriate adjustments.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <iostream>
#include <string>
#include <fstream>

using namespace std;

int romToInt(string str);
int calculate(int a, int b, char op);
string intToRom(int n);

enum romans {I = 1, IV =4, V = 5, IX = 9, X = 10, XL = 40, L = 50,
            XC = 90, C = 100, CD = 400, D = 500, CM = 900, M = 1000};

int main()
{
    string base;
    string divd;
    char opp;

    ifstream rNums("Rnum.txt"); // input file

    while ( (rNums >> base)  && (rNums >> divd) && (rNums >> opp) )
    {
        cout << base << " " << opp << " " << divd << " " << '\n';

        int conV     = romToInt(base);
        int conVV    = romToInt(divd);
        int answer   = calculate(conV, conVV, opp);
        string roman = intToRom(answer);

        cout << conV << " " << opp << " "  << conVV << " = " << answer
             << " or " << roman << endl;
    }

}

// Roman to Integer
int romToInt(string str)
{
    int conV = 0;
    
   // code omitted here
   
    return conV;
}

// Change integer back to Roman
string intToRom(int n)
{
    string result;

    // code omitted here

    return result;
}

int calculate(int a, int b, char op)
{
    int answer = 0;

    // code omitted here

    return answer;
}


For example in function intToRom(), something resembling this - but longer, to cover the other values.
1
2
3
4
5
6
7
8
9
10
11
12
    while (n > M)
    {
         result += "M";
         n -= M;
    }

    while (n > D)
    {
        result += "D";
        n -= D;
    }
    // etc. 
The first reply is understood, but it also does not work. I get an error with base and conV being undefined.
if you want to use variables without passing it to the function. it must be declared in the global scope.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <vector>

using namespace std;

void function();

// global
int Conv = 0;

int main()
{

function();

int x;
cin >> x;
return 0;
}

void function()
{
	cout << Conv << endl;
}


look up variable scope to understand functions better.

the code below will result in errors.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <vector>

using namespace std;

void function();

int main()
{

int Conv = 0;

function();

int x;
cin >> x;
return 0;
}

void function()
{
	cout << Conv << endl;
}
No offence intended, the first reply was very basic, it requires you to do some additional work, for example function() does not use any parameters, which is why it doesn't work unless you add the parameters yourself.

In my earlier reply I did most of the work for you by using functions with suitable parameters. There's a very modest (or small) amount of work involved in completing the task from that starting point.

Last edited on
if you want to use variables without passing it to the function. it must be declared in the global scope.

Global variables are almost never a good idea. Much better to pass the parameters you need into the function.
Right, that is what I am trying to do Mikey. I need to pass some of the variables as a both value-returning and void (paramters)? And Chervil, thank you for the file input stream correction. The doubling of the last line is gone and it is easier to understand how ifstream plugs into the while loop scope. I do know that I have to piece this together myself. I am just confused on how to pass variables between functions without making them global, as that is how my program is originally, is it not? According to the assignment the functions must not reference global variables.
I am just confused on how to pass variables between functions without making them global, as that is how my program is originally, is it not?

Well, I didn't provide a full explanation, but I did at least show you how it is done.

The code above does actually pass all the required parameters already - there's nothing you need to add in that regard.

If you need to actually understand the passing of parameters, and the returning of results, then perhaps you need to go through the basics as shown in the two tutorial pages.
http://www.cplusplus.com/doc/tutorial/functions/
http://www.cplusplus.com/doc/tutorial/functions2/

The only part which I put at the global scope was the enum which is not a variable, but effectively a set of constants here.

Here's one of the functions fully completed for you:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
int calculate(int a, int b, char op)
{
    int answer = 0;

    switch (op)
    {
        case '+':
            answer = a + b;
            break;

        case '-':
            answer = a - b;
            break;

        case '*':
            answer = a * b;
            break;

        case '/':
            answer = a / b;
            break;

        default:
            cout << "No solution... " << endl;
            break;
    }

    return answer;
}
Last edited on
I'm even more confused now Chervil. I can do only one function and then the rest leave me stumped.

My first function is to run ifstream and grab the file, it looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void fileFeed()
{
string base;
string divd;
char opp;

ifstream rNums;
ofstream numNums;

rNums.open ("Rnum.txt");
numNums.open ("numMth.txt");

while ((rNums >> base)  && (rNums >> divd) && (rNums >> opp)) // this is the new way, and it removes the doubling of the last line.
	{
		cout << base << " " << opp << " " << divd << " " << '\n';
	}

}


What I need to do next is take fileFeed() and process the roman nums. into integers. I cannot figure out how to pass base & divd into the romToInt function you have explained in your first post. I am trying to find a way to run that function within the fileFeed function and return the values for the calculate function. This program is driving me crazy, I am a bit obssessed right now with learning how to do this function within a function, and overall mastering the basics of functions. I feel a bit defeated at the moment.
Last edited on
I cannot figure out how to pass base & divd into the romToInt function you have explained in your first post.

I pasted the code for that already:
26
27
28
29
        int conV     = romToInt(base);
        int conVV    = romToInt(divd);
        int answer   = calculate(conV, conVV, opp);
        string roman = intToRom(answer);


I'm lost as to see what is the sticking point here. I already did 99% of the work for you.
Last edited on
The sticking point Chervil: everything is to be a function, and nothing is to be set in global.

I don't understand why you cannot simply explain how to pass base and divd to another function to be used? Nowhere can I find a simple straight forward explanation. I tried the above example, and I cannot get it to work within another function, because when I write the other function it is asking me to define base and divd again. Is there a way to save base and divd from the fileFeed function inside main? Also, can I set the enum Romans inside a function for defintion so that it references the values?
The sticking point Chervil: everything is to be a function, and nothing is to be set in global.

That's exactly what Chervil is doing - showing you how to pass variables from main into the functions without making them global. What on earth is the problem now? He's shown you what to do!
OK, let me look at this some more and I'll see if I can get help.

My own difficulty is that the original code I posted does actually work - I tested it. After that I omitted some of the details simply to keep down the size of the post - and also to give you a little bit of something to do. If I'd just pasted the entire code and you ran it, how much would you learn?

I don't know whether or not you ever got that first version to work (which as I say I tested, so I'm certain that the structure is correct). Because I don't know whether you got that far, I don't know how best to advise.

What I do see is that you have moved on from that version, changed the code by introducing a new function. Now that's perfectly fine, nothing wrong with that as an idea. But as you can tell, I'm not sure at what point in this whole thing it fell apart for you.

I don't understand why you cannot simply explain how to pass base and divd to another function to be used?
I illustrated it by example - that's one part of the explanation. I also pointed you towards two tutorial pages - that's the other part of the explanation.

Did you read through the tutorial? Have you tried to compile and run the examples and see what happens when you do so? That's the way to begin to understand the subject. Plus, you could also try modifying the example code from the tutorial, play around with it, see whether what happens matches what you expect to happen.

To be honest, if I sat down next to you we could work through it together and I'm sure you'd be pretty much up to speed after about 30 minutes. But trying to do this online is much harder - for both of us.
Last edited on
Topic archived. No new replies allowed.