loop with while statement

I am trying to write a simple money exchange program. The following should happen: User enters maximum five currency-exchange rate pairs. Then gives the amount of money they want to exchange. The program calculates the equivalent value. If they would like to stop entering currencies they may enter x (the program terminates).

The problem is that from the second loop it does not let the user enter anything, it just gives the result as 0.
I assume the program should get the first value (currency in this case) before the loop starts so it can decide it is valid value or not ("x").
Can I have some help please?

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
#include <iostream>
#include <string>
using namespace std;

int main(){
  string currency;
  double rate{0};
  double pound{0};
  double resoult{0};
  int counter{1};
  
  cout << "Enter max.5 currency/ exchange rate for Pounds" << endl;
  getline (cin, currency);
  cin >> rate;
  
  
  while(currency != "x" && counter <= 4){ 
  
  cout << "\nHow many Pounds do you want to exchange?";
  cin >> pound;
  resoult = pound*rate;
  
  cout << "\nExchanged currency: " << currency
   << " In pounds: " << resoult;
  
  cout << "\n\nEnter max.5 currency/ exchange rate for Pounds" << endl;
  getline (cin, currency);
  cin >> rate;
  counter++;
  
  }
  
}
This is more something to do with how getline() works. I don’t remember exactly what it is that happens, but I think I remember how to solve the problem. After each getline(), discard any '\n's using cin.ignore('\n',some_arbitrary_number);. That might be excessive, but that’s what I can remember. I suggest looking up "problems with getline()" or something like that and/or also waiting for someone with more experience to answer you.
This is more something to do with how getline() works.

It is the interaction between std::cin and std::getline in mixed usage.

std::getline retrieves the entire input line, including the carriage return. std::cin leaves the carriage return in the input stream, so the next std::getline retrieves it and makes an invalid value.

std::cin::ignore lets you extract the carriage return from the input stream and discard it.

http://www.cplusplus.com/reference/istream/istream/ignore/

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
#include <iostream>
#include <string>
#include <limits>

int main()
{
   std::cout << "Welcome to the Exchequer\n"
      << "A total of 5 transactions can be done\n";

   int counter { 1 };

   do
   {
      std::cout << "\nEnter currency name (x to quit): ";
      std::string currency;
      std::getline(std::cin, currency);

      if ("x" == currency)
      {
         break;
      }

      std::cout << "Exchange rate for Pounds: ";
      double rate { };
      std::cin >> rate;
      std::cout << '\n';

      std::cout << "How many Pounds do you want to exchange? ";
      double pound { };
      std::cin >> pound;
      std::cout << '\n';

      std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

      double resoult { pound * rate };

      std::cout << "Exchanged currency: " << currency
         << " in Pounds: " << resoult << '\n';

      counter++;
   } while (counter <= 5);
}

Welcome to the Exchequer
A total of 5 transactions can be done

Enter currency name (x to quit): A
Exchange rate for Pounds: 1.5

How many Pounds do you want to exchange? 12.75

Exchanged currency: A in Pounds: 19.125

Enter currency name (x to quit): B
Exchange rate for Pounds: 2.345

How many Pounds do you want to exchange? 17.5

Exchanged currency: B in Pounds: 41.0375

Enter currency name (x to quit): C
Exchange rate for Pounds: 4

How many Pounds do you want to exchange? 5

Exchanged currency: C in Pounds: 20

Enter currency name (x to quit): D
Exchange rate for Pounds: 6

How many Pounds do you want to exchange? 15

Exchanged currency: D in Pounds: 90

Enter currency name (x to quit): E
Exchange rate for Pounds: 2.5

How many Pounds do you want to exchange? 1000

Exchanged currency: E in Pounds: 2500

(Terminating early):
Welcome to the Exchequer
A total of 5 transactions can be done

Enter currency name (x to quit): Chubs
Exchange rate for Pounds: 2.3

How many Pounds do you want to exchange? 700

Exchanged currency: Chubs in Pounds: 1610

Enter currency name (x to quit): x


A easier-to-remember version of std::cin::ignore:

std::cin.ignore(32767,'\n');

No need to include <limits> then.
Last edited on
@medosz, a do/while loop might be a better choice over a while loop. A do/while is guaranteed to execute at least one time since the condition is checked at the end of the loop. A while loop might not execute even once.

Line 8, let's say counter was wrongly set to int counter { 8 };*. The while loop at lines 13-43 will terminate without running even one time.

Change line 13 to do and line 43 to } while (counter <= 5);.

NOW your loop will execute even if counter was improperly set.

*mistyping happens, programmers are human too. Amazing, ain't that.
Line 8, let's say counter was wrongly set to int counter { 8 };*. The while loop at lines 13-43 will terminate without running even one time.

Change line 13 to do and line 43 to } while (counter <= 5);.

NOW your loop will execute even if counter was improperly set.

If there's a problem with your code, the very worst thing you could do is make the code behave as if nothing is wrong. You want it to be as obvious as possible when there are bugs in your code, so that you can quickly and easily find and fix them.

Your suggestion is the equivalent of jamming a nail into a plug instead of a fuse, so that you never have to worry about a blown fuse.
Last edited on
Terminating prematurely is not code behaving as if nothing is wrong. Terminating prematurely is decidedly WRONG.

What I suggested isn't the most robust way to write code, but then it is something a beginner would deal with.

When I want a loop that executes at least once, even if the test condition is not accidentally bollixed, then a do/while loop is preferable to a while loop.
Last edited on
Terminating prematurely is not code behaving as if nothing is wrong. Terminating prematurely is decidedly WRONG.

Terminating prematurely is exactly what assertions do, and they're an extremely powerful tool in debugging software during software development.

Now, in the production code, you might also want to have defensive programming in there to handle errors more cleanly.

But fineagling your code so that problems and bugs are made harder to see than they would be, is not a sensible approach to software development.
Last edited on
Now, in the production code....

Something of little to no concern for someone learning to code.

Later, after time and experience, it is of vital importance.

Maybe I imprecisely conflated the reason(s) for using a do/while loop with possible error conditions.

I freely admit I am not the best coder around. Obviously you would code a simple example MUCH differently than I would.

But fineagling your code so that problems and bugs are made harder to see than they would be, is not a sensible approach to software development.

My example(s) aren't even remotely how I would write "production code." They are less than robust for the sheer necessity of not being too excessive for a beginner to grasp.

Learning to troubleshoot defective code is as much a part of learning to program as writing code.

As is learning the best way to use a language feature.

So shoot me for trying to be helpful.
Something of little to no concern for someone learning to code.

My point exactly. Doing things to hide bugs, and make it seem as if the software is working normally when there might be problems under the hood, is something you might consider doing in production code.

It's not something to encourage beginners to do. They need to be able to see clearly and easily when they've done something wrong, so that they can learn from their mistakes and fix them. (To be honest, so do the rest of us, no matter how experienced we are.)

Learning to troubleshoot defective code is as much a part of learning to program as writing code.

Indeed. But... are you suggesting learners write their code in such a way as to make it harder to see when there's a problem? And if so... why?

So shoot me for trying to be helpful.

Oh, drop the histrionics. We (I hope) are people having a rational discussion about good and bad ways to write code. Passive-aggressive snark like this is not helpful to you, me, or - most importantly - to the OP.
Last edited on
Topic archived. No new replies allowed.