You are here:

C++/Tweaking my source code

Advertisement


Question
Hey Ralph!

Its me again, I asked you a question yesterday and your feedback was by far the best one I'd gotten from any of the 10 websites where I posted up my question.

But I was wondering, regarding my yesterday's code, is there any way in which the program can tell me that I'm entering reservations in seats already booked?

For example, let's say seat 2 B was reserved. Upon asking to continue reserving I accidentally enter in 2 B again. In this case can my program like give a output statement saying "That seat is already reserved"? If yes, how would I go around doing it? Would it be a for loop?

For example:

for (row7 = "7 A B X D")
if (letter == "C")
cout << "That position is already taken"

But when I try this my code messes up (it wont compile). Here is my code without the errors.
___________________________________________________________
#include <iostream>
#include <string>
using namespace std;
int main ()
{
   int row;
   string letter;
   char letter2;
   int num = 1;
   int num2 = 2;
   int num3 = 3;
   int num4 = 4;
   int num5 = 5;
   int num6 = 6;
   int num7 = 7;

   string row1 = "1  A B  C D";
   string row2 = "2  A B  C D";
   string row3 = "3  A B  C D";
   string row4 = "4  A B  C D";
   string row5 = "5  A B  C D";
   string row6 = "6  A B  C D";
   string row7 = "7  A B  C D";
   
   cout << row1 << endl;
   cout << row2 << endl;
   cout << row3 << endl;
   cout << row4 << endl;
   cout << row5 << endl;
   cout << row6 << endl;
   cout << row7 << endl;
   
   do
   {
   cout << "Enter the row number where you would like to reserve a seat"<< endl;
   cout << endl;
   cout << "Your options are from 1 through 7, as shown to you." << endl;
   cin >> row;
   cout << "Now enter the letter in that row where you would like to reserve a seat" << endl;
   cout << endl;
   cout << "Already reserved seats are marked with an 'X'." << endl;
   cout << "Ensure you enter in a capital letter" << endl;
   cout << endl;
   cin >> letter;
   
   if (row == num && letter == "A" )
   row1 = "1  X B  C D";
   else if (row == num && letter == "B")
   row1 = "1  A X  C D";
   else if (row == num && letter == "C" )
   row1 = "1  A B  X D";
   else if (row == num && letter == "D" )
   row1 = "1  A B  C X";
   
   if (row == num2 && letter == "A")
   row2 = "2  X B  C D";
   else if (row == num2 && letter == "B")
   row2 = "2  A X  C D";
   else if (row == num2 && letter == "C")
   row2 = "2  A B  X D";
   else if (row == num2 && letter == "D" )
   row2 = "2  A B  C X";
   
   if (row == num3 && letter == "A")
   row3 = "3  X B  C D";
   else if (row == num3 && letter == "B")
   row3 = "3  A X  C D";
   else if (row == num3 && letter == "C")
   row3 = "3  A B  X D";
   else if (row == num3 && letter == "D")
   row3 = "3  A B  C X";
   
   if (row == num4 && letter == "A")
   row4 = "4  X B  C D";
   else if (row == num4 && letter == "B" )
   row4 = "4  A X  C D";
   else if (row == num4 && letter == "C")
   row4 = "4  A B  X D";
   else if (row == num4 && letter == "D")
   row4 = "4  A B  C X";
   
   if (row == num5 && letter == "A")
   row5 = "5  X B  C D";
   else if (row == num5 && letter == "B")
   row5 = "5  A X  C D";
   else if (row == num5 && letter == "C")
   row5 = "5  A B  X D";
   else if (row == num5 && letter == "D")
   row5 = "5  A B  C X";          
   
   if (row == num6 && letter == "A")
   row6 = "6  X B  C D";
   else if (row == num6 && letter == "B")
   row6 = "6  A X  C D";
   else if (row == num6 && letter == "C")
   row6 = "6  A B  X D";
   else if (row == num6 && letter == "D")
   row6 = "6  A B  C X";
   
   if (row == num7 && letter == "A")
   row7 = "7  X B  C D";
   else if (row == num7 && letter == "B")
   row7 = "7  A X  C D";
   else if (row == num7 && letter == "C")
   row7 = "7  A B  X D";
   else if (row == num7 && letter == "D")
   row7 = "7  A B  C X";
   
       
   cout << "Thank you!";
   cout << endl;
   cout << "Updated Seating Arrangement" << endl;
   cout << endl;
   cout << row1 << endl;
   cout << row2 << endl;
   cout << row3 << endl;
   cout << row4 << endl;
   cout << row5 << endl;
   cout << row6 << endl;
   cout << row7 << endl;
   cout << endl;
   
   cout << "Would you wish to continue reserving seats? Y/N" << endl;
   cin >> letter2;
   }
   while ( letter2 == 'y' || letter2 == 'Y');    
  
   cout << "End of program." << endl;

system ("pause");
return 0;
}
__________________________________________________________

if I add

for (row7 = "7 A B X D")
if (letter == "C")
cout << "That position is already taken";

for instance, it wont compile. I just tried adding one before the rest to check for compilation errors and it gave my one. Is there any way to fix this?

Answer
Might I suggest that before rushing in and using language features you have not used before like for-loops you take a step back and read up on them in your text book? It will probably save you (and me!) a lot of time.

Please also note that I am not going to have the time to devote to continuing this level of detail in my answers to you. Each one takes quite a while (two hours plus for example) to write up.

Now a for-loop is a special syntax used to represent the following loop structure:

   initialisation-expression;
   while (condition-expression)
   {
       repeated-statements;
       update-expression;
   }

For example:

   int i(0); // initialisation-expression
   while ( i<10 /*condition-expression*/)
   {
       std::cout << "The square of " << i << " is " << i*i << '\n';
       ++i; // update-expression
   }

The for-loop equivalents of these are as follows:

   for ( initialisation-expression; condition-expression; update-expression )
   {
       repeated-statements;
   }

And the example as a for-loop:
   
   for ( int i(0); i<10; ++i )
   {
       std::cout << "The square of " << i << " is " << i*i << '\n';
   }

Note that for requires three expressions: an expression to initialise loop data, typically an integer value, most often initalised 0, an expression to test whether the loop continues, and an expression to update data – typically incrementing the loop variable initialised in the initialisation expression.

From this we can see that your version:

   for (row7 = "7 A B X D")

is ill-formed because it only has one expression, an initialisation expression.

There are several ways to do what you wish with your current program structure. The obvious way is to put the test for already booked with the if-clause statements that set the Xs, for example:

   if (row == num5 && letter == "A")
   {
   // Test that A is in A position and not an X already
       row5 = "5  X B  C D";
   }

How can you test for the presence of characters in a string? Well you are using the C++ library std::string type. That is good because it has many find operations.

The one to use here would look like the following:

   if ( row5.find('A')== string::npos )
   {
       cout << "Sorry seat already taken, please try another\n";
       continue;  // continue around loop once more.
   }

The version of find I am using looks for a specific single character (as indicated by the single quotes around the A). The return from find is a value that represents the position of the character in the string, or the special value string::npos if the character were not found. So the test I am using is true if A is not found in the row5 string. If A is not found in the row5 string it is not there presumably because it has already been replaced by an X, indicating that the position has been taken. In this case a message is displayed and then I use a new keyword, continue.

When executing looped code there are occasionally times when something occurs and you wish to skip the rest of the repeated statements. To skip and start the next loop iteration we can use the continue statement (continue from start of next iteration), as I have done above. To skip and leave the loop there is the break statement (i.e. break out of the loop).

Using continue should work so long as letter2 is still a 'y' or a 'Y', which should be the case as it is only modified at the end of the loop (I think).

Of course following this plan to its completion means making such a change to every if-clause that sets up your seating plan and this is going to get tedious. However that is how your program is currently set up.

You have a worse problem though. Your code at the moment can only ever show a single seat used per row. Let’s look at why:

You run your program and set row 1 seat A this executes:

   if (row == num && letter == "A" )

   row1 = "1  X B  C D";

So row1 contains: "1  X B  C D"

Second time around you set row 1 B. This executes:

   else if (row == num && letter == "B")

   row1 = "1  A X  C D";

Now row1 contains: "1  A X  C D"

It should contain: "1  X X  C D"

The problem is that by setting the whole string each time you effectively overwrite and wipe out any previous bookings on the same row!

Lucky for us that the string type has a set of replace operations that can replace parts of a string!

We use replace in conjunction with find. Remember that I said find returns a position value to indicate where it found a match. Well this can be used to specify which part of a string to replace.

We can change the above to the following:

   if (row == num && letter == "A" )
   {
       string::size_type pos( row1.find('A') );
       row1.replace( pos, 1, 1, 'X' );
   }
   else if (row == num && letter == "B" )
   {
       string::size_type pos( row1.find('B') );
       row1.replace( pos, 1, 1, 'X' );
   }

You can see that the first argument, pos, and the last argument 'X' passed to replace are obviously where were are replacing text and what we are replacing it with, but what are the two 1 values in the middle for? They specify how many characters of row1 should be replaced (starting at the character at position pos), and with how many occurrences of X respectfully. In this case we wish to replace only the single character at pos with only a single X so both values are 1.

We can merge the above code with the test for already booked:

   if (row == num && letter == "A" )
   {
       string::size_type pos( row1.find('A') );

       if ( pos == string::npos )
       {
         cout << "Sorry seat already taken, please try another\n";
         continue;  // continue around loop once more.
       }

       row1.replace( pos, 1, 1, 'X' );
   }
   else if (row == num && letter == "B" )
   {
       string::size_type pos( row1.find('B') );

       if ( pos == string::npos )
       {
         cout << "Sorry seat already taken, please try another\n";
         continue;  // continue around loop once more.
       }

       row1.replace( pos, 1, 1, 'X' );
   }

However, this is still going to be tedious to do. I shall propose a revised structure that uses very little in the way of additional features. The pseudo-code for this revised structure is:

Get the row number and seat letter.

Check the row is in the range [1,5] and the letter is one of "ABCD",
    if not display a message and ask again.

Set update_row to one of row1, row2, row3, row4 or row5
   as indicated by the entered row number.
   
Find and replace entered letter in update_row with X.
   If the letter is not found in update_row display message and continue.

Set one of row1, row2, row3, row3 or row5 as indicated by the entered row number
   to equal update_row.

These steps all go within the do..while loop. The improvements are:

- We know that the entered values are good before using them.
- We work on a single intermediate copy of the required row string so do not
 have to replicate the logic of updating the string.
- We can use the entered letter in place of explicit usage of 'A', 'B', 'C' and
 'D', and so can perform the update for any seat position using only a single
  set of statements.

On the other hand we have to copy the correct row string into the update_row variable and the update_row variable back into the relevant row variable, which yields tedious code again.

You have almost all the C++ you require to implement the above changes. I shall give you the following hints:

- letter is a string. Why? Consider making it a char and use 'A', 'B', 'C' and
 'D' in place of "A", "B", "C" and "D" (if indeed any such need still exists).
- You can use a string find operation to check that the entered letter is valid.
 For this you will probably need a string containing the valid characters:

     string row_chars("ABCD");

- Consider the following use of find:

   string::size_type pos( update_row.find(letter) );

Please note that all the code shown here has not been tested or even compiled, is for example and demonstration purposes only. It may contain mistakes or typos. If so then please accept my apologies, and have fun correcting my mistakes!

Now a word on code style, layout and formatting.

You might have noticed that I use indentation when writing code. The convention is that whenever you have statements that are inside another statement, such as inside an if or do or while, you indent the code. You do not seem to be doing this (although it may be due to posting through AllExperts, I am never quite sure). In your code for example I would expect indentation something like:

int main()
{
   int    row;
   string letter;
   char   letter2;
   int    num = 1;

// ...

   do
   {

       cout << "Enter the row number where you would like to reserve a seat"
         << endl;

       cout << endl;

       cout << "Your options are from 1 through 7, as shown to you." << endl;

       cin >> row;

   // ...

       if (row == num && letter == "A" )
         row1 = "1  X B  C D";
       else if (row == num && letter == "B")
         row1 = "1  A X  C D";

   // ...

   }
   while ( letter2 == 'y' || letter2 == 'Y');    

   cout << "End of program." << endl;

   system ("pause");

   return 0;
}

Correctly indenting code helps you and others see which code is associated with which statements and can help show mistakes. That is, it helps with humans understanding the structure of the code. Code should always be as clearly formatted and as clearly expressed as possible. The compiler does not care but us humans do. You might say that your code is not going to be seen by anyone else. Well that is not true is it? You are posting it to me for a start, and not privately either which means the question (and my answer) will likely appear on the AllExperts web site for the whole world to view!

Exactly how much to indent and the positioning relationship between outer statement, braces and inner statements as well as whether to allow tab characters or convert them to spaces are all personal things. As are whether to allow long lines.

I tend to go for spaces and no tab characters as tab spacing changes depending on what program you are using (and what user settings are in effect in some cases) – for some it is 4 spaces, for others 5, or 8 or 3 or 2 etc. which causes your beautifully formatted code to look totally messed up when viewed with the wrong tab spacing settings. I also try to keep code on lines of 80 characters or less, as not all people have screens (or printers) that can display long lines, and long lines are less easy to read (at least for English readers).

As to indentation style, I tend to stick to either 4 spaces, as above, or a 2+2 combination:

int main()
{
 int     row;
 string letter;
 char   letter2;
 int    num = 1;

// ...

 do
   {

     cout << "Enter the row number where you would like to reserve a seat"
         << endl;

     cout << endl;

     cout << "Your options are from 1 through 7, as shown to you." << endl;

     cin >> row;

   // ...

   }
 while ( letter2 == 'y' || letter2 == 'Y');    

Finally I also tend to always use braces even when they are not required as in the case where an if, else, while, for etc. is followed by only a single statement. This is from the observation that over time you are quite likely to add more code to the block and at that point you _must_ add in the braces (see my examples above that expand your if clauses for instance). This however is my very personal preference (and in some special, rare, cases I may even not bother):

       if (row == num && letter == "A" )
         {
         row1 = "1  X B  C D";
         }
       else if (row == num && letter == "B")
         {
         row1 = "1  A X  C D";
         }

Hope this has been of use. Keep practicing and have fun!  

C++

All Answers


Answers by Expert:


Ask Experts

Volunteer


Ralph McArdell

Expertise

I am a software developer with more than 15 years C++ experience and over 25 years experience developing a wide variety of applications for Windows NT/2000/XP, UNIX, Linux and other platforms. I can help with basic to advanced C++, C (although I do not write just-C much if at all these days so maybe ask in the C section about purely C matters), software development and many platform specific and system development problems.

Experience

My career started in the mid 1980s working as a batch process operator for the now defunct Inner London Education Authority, working on Prime mini computers. I then moved into the role of Programmer / Analyst, also on the Primes, then into technical support and finally into the micro computing section, using a variety of 16 and 8 bit machines. Following the demise of the ILEA I worked for a small company, now gone, called Hodos. I worked on a part task train simulator using C and the Intel DVI (Digital Video Interactive) - the hardware based predecessor to Indeo. Other projects included a CGI based train simulator (different goals to the first), and various other projects in C and Visual Basic (er, version 1 that is). When Hodos went into receivership I went freelance and finally managed to start working in C++. I initially had contracts working on train simulators (surprise) and multimedia - I worked on many of the Dorling Kindersley CD-ROM titles and wrote the screensaver games for the Wallace and Gromit Cracking Animator CD. My more recent contracts have been more traditionally IT based, working predominately in C++ on MS Windows NT, 2000. XP, Linux and UN*X. These projects have had wide ranging additional skill sets including system analysis and design, databases and SQL in various guises, C#, client server and remoting, cross porting applications between platforms and various client development processes. I have an interest in the development of the C++ core language and libraries and try to keep up with at least some of the papers on the ISO C++ Standard Committee site at http://www.open-std.org/jtc1/sc22/wg21/.

Education/Credentials

©2016 About.com. All rights reserved.