6

I have some homework that I was flying through until I got to this final step and I'm now stumped, I would really appreciate some help.

The premise of the project is to create a file of possible words given a telephone number. The user is meant to input a number with the format '###-####'. The code then pulls the hyphen out and sends the phone number to the method wordGenerator. I know that everything works up until this point. When the time comes to output the different possibilities of words is where I am having my issue. Here's what my method looks like:

// function to form words based on phone number
void wordGenerator( const int * const n )
{
  // set output stream and open output file
  /* Write a declaration for an ofstream object called
     outFile to open the file "phone.dat" */ 
 ofstream outFile("phone.dat");
 // letters corresponding to each number

  /* Write a declaration for an array of 10 const char *'s
  called phoneLetters. Use an initializer list to assign
  each element of the array the corresponding string of
  three letters. Use dummy characters for 0 and 1 */
  const char * phoneLetters[] = {"###", "###", "ABC", "DEF", "GHI",
                     "JKL", "MNO", "PRS", "TUV", "WXY"};
  // terminate if file could not be opened
  /* Write code to check if the file was opened successfully,
     and terminate if not */
   if( !outFile )
   {
    cerr << "The file could not be opened";
    exit(1);
   }

  int count = 0; // number of words found

  // output all possible combinations
  for ( int i1 = 0; i1 <= 2; i1++ )
  {
     for ( int i2 = 0; i2 <= 2; i2++ )
     {
        for ( int i3 = 0; i3 <= 2; i3++ )
        {
           for ( int i4 = 0; i4 <= 2; i4++ )
           {
              for ( int i5 = 0; i5 <= 2; i5++ )
             {
                for ( int i6 = 0; i6 <= 2; i6++ )
                 {
                   for ( int i7 = 0; i7 <= 2; i7++ ) 
                    {
                    /* Write a series of cascaded stream insertion
               operations to output a set of seven letters
           to outFile, followed by a space */

                     outFile << phoneLetters[i7 + 2] << phoneLetters[i6 + 2] <<  phoneLetters[i5 + 2]  << phoneLetters[i4 + 2] << phoneLetters[i3 + 2] << phoneLetters[i2 + 2]
                            << phoneLetters[i1 + 2] << ' ';
                    if ( ++count % 9 == 0 ) // form rows
                       outFile << '\n';
                   } // end for
                 } // end for
              } // end for
           } // end for
         } // end for
      } // end for
    } // end for

  // output phone number
    outFile << "\nPhone number is ";

    for ( int i = 0; i < 7; i++ ) 
    {
      if ( i == 3 )
      outFile << '-';

      outFile << n[ i ];
    } // end for

   /* Write a statement to close the ouput file */
     outFile.close();
     system("pause");
    } // end function wordGenerator

Unfortunately I was given a skeleton of code and told to fill in the blanks to complete the assignment. Everywhere where the comments are blocked (/* */) is where I have to fill in code.

I'm not sure what I need to do to output the proper format of the possible words. I tried searching google, but all the results I found use a much simpler (in my opinion) switch statement to achieve this and I'm constrained to the template :(

All help is appreciated, even a nudge in the right direction.

Edit: I just thought of one other thing. I feel that if someone could even help me figure out how to iterate through the characters of phoneLetters[] individually instead of a block, that would be a significant step forward. Example: when reading in the number '2' of a phone number instead of printing "ABC", print "A" for all possible combinations, then move on to "B".

Edit: Here is my main():

int main()
{
  int phoneNumber[ 7 ] = { 0 }; // holds phone number

   // prompt user to enter phone number
   cout << "Enter a phone number (digits 2 through 9) "
     << "in the form: xxx-xxxx\n";

   // loop 8 times: 7 digits plus hyphen;
   // hyphen is not placed in phoneNumber
   for ( int u = 0, v = 0; u < 8; u++ ) 
  {
     int i = cin.get();

     // test if i is between 0 and 9
     if ( i >= '0' && i <= '9' )  
     phoneNumber[ v++ ] = i - '0';
   } // end for

   wordGenerator( phoneNumber ); // form words from phone number
   return 0;
} // end main
Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
Kyle
  • 366
  • 3
  • 17
  • you could try changing your phoneLetters array to a two dimensional array of char's, then it will be easy for you to loop through each letter – Eamonn McEvoy Apr 17 '12 at 18:22
  • 5
    7 nested for loops is usually a good sign you're doing something silly ... – AJG85 Apr 17 '12 at 18:23
  • @Msonic To simplify the task. – Bartek Banachewicz Apr 17 '12 at 18:34
  • @Eamonn McEvoy - I agree with you, it'd be much easier to do it that way, but that's not what I was instructed to do. – Kyle Apr 17 '12 at 18:38
  • 1
    @Msonic because this is supposed to be a telephone keypad, Q and Z aren't listed on some keypads – Kyle Apr 17 '12 at 18:39
  • @AJG85 - I couldn't agree with you more, it's really, really confusing. Unfortunately, that was already part of the skeleton code that I was given. I guess that doesn't say much for the author's style :/ – Kyle Apr 17 '12 at 18:40
  • @Kyle It's already a bad idea to provide implementations to students but it's even worse to provide really bad implementations and make them use it. If that's the case I wouldn't take anymore of their classes. – AJG85 Apr 17 '12 at 19:28

3 Answers3

6

If you can't get rid of the horrific nested for statements then you can use the following line:

outFile
    << phoneLetters[n[0]][i1]
    << phoneLetters[n[1]][i2]
    << phoneLetters[n[2]][i3]
    << phoneLetters[n[3]][i4]
    << phoneLetters[n[4]][i5]
    << phoneLetters[n[5]][i6]
    << phoneLetters[n[6]][i7]
    << ' ';

Some other notes on the code:

Hope this helps.

Community
  • 1
  • 1
Silas Parker
  • 8,017
  • 1
  • 28
  • 43
  • That's exactly what I needed! Thank you very much for the help, your knowledge is greatly appreciated! – Kyle Apr 17 '12 at 19:09
2

First of all, change these nested for-s. They look terrible, and if I said you are now to generate 15-digit numbers, you would be in really bad position.

What you're looking there is some sort of permutation generator with modulo 3, as i would think of it... Since there are no special cases (like "PQRS" on real phones), just numerate all the possible combinations from 0 to 3^7.

Then, use one for-loop to iterate through them. Writing custom iterator function namely would be probably difficult concept to understand, so think about is just as making all these combinations, like:

// 3^7 = 2187

for (int i = 0; i < 2187; ++i)
{
    int Div = 1;
    // now, 7 digits
    for (int d = 0; d < 7; ++d)
    {
         outFile << (i / Div) % 3;
         Div *= 3;
    } 
}

That code will generate permutations of numbers in tri-nary system ;) Which can then be used to output right letters with

outFile << phoneLetters[ActualReadNumber][ (i/Div)%3 ];

If you really need to use "cascade" writing into a file, replace inner loop with all 7 possibilities, such as:

/*1.*/   i % 3
/*2.*/   (i / 3) % 3
/*3.*/   (i / 9) % 3

And so on... If I should explain something in greater detail, comment for this; If I helped, upvote :) and good luck with homework.

Bartek Banachewicz
  • 38,596
  • 7
  • 91
  • 135
  • It's definitely an elegant solution and I appreciate you writing that out for me. But I'm not supposed to change the template code I was given which included those ridiculous loops – Kyle Apr 17 '12 at 18:42
  • Ah, so these loops will stay there. I know your pain, I'm studying too and teachers have their own "methods". I believe I already wrote you how to iterate through letters, though. (`phoneLetters[num][letter]`). – Bartek Banachewicz Apr 17 '12 at 18:46
  • Ah yes I see that. Could you elaborate on that for me please? I don't see how I can implement it. I'll edit my original post so you can see my main and the rest of the data members. – Kyle Apr 17 '12 at 18:58
  • Disregard Bartek, I have what I was looking for now. Thank you again for your help! – Kyle Apr 17 '12 at 19:09
0

Solution if phone numbers only had two digits while obying you template.

int pN[] = {6,9};

const char * phoneLetters[] = {"###", 
    "###", "ABC", "DEF", "GHI", "JKL", "MNO", "PRS", "TUV", "WXY"}; // 


for (const char *c1 = phoneLetters[pN[0]]; *c1 != '\0'; c1++)
{ 
    for (const char *c2 = phoneLetters[pN[1]]; *c2 != '\0'; c2++)
    { 
        printf( "%c%c\n" , *c1 , *c2); 
    } 
}

OUTPUT: MW MX MY NW NX NY OW OX OY

SirRoot
  • 249
  • 4
  • 17