help with C++

bed_head7

Deity
Joined
Jun 16, 2004
Messages
2,494
I am writing, or trying to start writing, a program that would allow the user to input any number of lines. Using arrays, the program should count each letter of input up until a '.' is reached, and then reorganize the list in order of frequency of each letter. I think that I should be able to do most of this, with a bit of a struggle I am sure, but I can figure it out. However, I do not understand one sentence of the assignment:

Use an array with a struct type as its base type so that each array element can hold both a letter and an integer.

This is probably intended to be a hint, though it seems obvious that I would need to hold both the letter and an integer. How else could I keep track of the frequency of use by each letter? So, what is the problem? Well, my book has very little on structs, and the online lessons (it is an online class through the nearby junior college) have nothing on structs. I generally learn best by seeing examples, but in this case I have none from which to learn. Can someone give/show me an example and an explanation? I would appreciate it, as I put this assignment off a bit longer than intended, and at this point only have 24 hours in which to complete it.

[Forgot to mention that I am not to use classes, and this is a single-dimensional array. I don't know if the last detail is relevant, but two-dimensional arrays happen to be the next lesson, so I wouldn't know at this point]
 
You don't really have to use structs or 2d-array. you can just assign a number to every letter, so Array[0] holds the frequency of a, Array[1] the freq of be, and so on. You can make it easier for yourself if you use the standard ASCII-Codes so that 'a' is stored in Array[97]. That way you can easily determine which field to store it in, by converting the char into an int (which then represents the ASCII-Code).
 
you can use something like this:

for (i=0; i<number_of_lines ; ++i)
for (j=0; user_array[j]!='.' ; ++j)
for (k=32; k<255; ++k)
if (user_array[j]==k)
{ ++ascii_table[k]; break; }

Where user_array is the inputed table and ascii_table a special table that stores all character frequencies (you will have to initialise it).

You must know by now that characters and numbers are treated the same (i.e. 'A' is the same as 65).

If you check the ASCII table (http://www.italysoft.com/utility/converters/ascii-table.html ) you will see that printable characters range from 32 to 255. If you don't plan to use any special characters you can only increment k from 32 to 127. A further optimisation would be to make the ascii_table shorter (holding only the stuff you need) and adjusting the last line of the code line this:

++ascii-table[k-32];

Finally, you can allocate the user_table dynamically so that if someone inputs many lines of diferent lengths you don't waste memory. Another thing you can do is to let the user input whatever text he wants (including points) then add an extra sign at the end of the line (you can add a NULL). This way the user only has to press the ENTER key to move to the next line (which is an intuitive thing). Or you can let the user input text and store the length of the line in the first location of each line.


I hope this helps ;)

Edit: added a "break" after the last loop. Not essential, but more efficient.
 
That's not what the instructor wants. He/she wants something like

struct {
char my_character;
int my_integer;
} my_structure[num_elements];

That way, you can refer to the stuff inside as e.g. my_structure.my_integer. You can also allocate the memory dynamically, or whatever else your instructor wants.
 
Ok, so you build your own character set, right? What's so difficult about that? Do you have problems sorting it?

you can define something like:
my_structure alphabet = { {'A', 0}, {'B', 0}, {'C', 0}, ... }
of if you're smart you can use the ASCII and a for loop to do it
alphabet[0...x] contains the character and it's frequency (initialised with zero).
You simply compare each character of the entry with this alphabet[x].my_character.
 
Thanks IbnSina. Eventually I found an example of that last night, and got started on that. It was just frustrating to be asked to do that without knowing anything about structs other than

struct StructName {
MemberList
} VariableList;

and the fact that structs can use other structs and access members through dot notation, or whatever it is called. Of course, since this was just mentioned as a "by the way" sort of thing in the chapter on classes, I probably should have been able to figure out on my own that that was what I needed to do.

I appreciate your last suggestion, Aphex_Twin, but I think that doing that might sort of be getting around part of the assignment.
 
Thanks again for the help. I realize it was not all that complicated a program, and still I probably managed to overcomplicate certain parts, but I was frustrated last night with not knowing much about structs. Anyway, here is the final product.

Code:
#include <iostream> // provides cout and cin
#include <iomanip> // provides setw()
#include <cctype> // provides tolower()
using namespace std;

const int NUM_LETTERS = 26;

struct letterFrequency {
    int frequency;
    char letter;
};


int indexOfLargest(letterFrequency frequencyArray[], 
                   int startingPoint);
void sortFrequencyArray(letterFrequency frequencyArray[]);
void countLetters(letterFrequency frequencyArray[]);
void initFrequencyArray(letterFrequency frequencyArray[]);
void printFrequencyTable(letterFrequency frequencyArray[]);




int main()
{
    letterFrequency frequencyArray[NUM_LETTERS];

    initFrequencyArray(frequencyArray);
    countLetters(frequencyArray);
    sortFrequencyArray(frequencyArray);
    printFrequencyTable(frequencyArray);
}


int indexOfLargest(letterFrequency frequencyArray[], 
                   int startingPoint)
{
    int targetIndex = startingPoint;
   
    for (int count = startingPoint + 1; 
         count < NUM_LETTERS; count++){
        if (frequencyArray[count].frequency > 
            frequencyArray[targetIndex].frequency){
            targetIndex = count;
        }
    }
   
        return targetIndex;
}

void sortFrequencyArray(letterFrequency frequencyArray[])
{
    for (int count = 0; count < NUM_LETTERS - 1; count++){
        swap(frequencyArray[indexOfLargest(frequencyArray, 
             count)], frequencyArray[count]);
    }
}


void countLetters(letterFrequency frequencyArray[])
{
    char ch1;
    int count;
    
    cout << "Enter a sequence of characters (end with '.'): ";
    cin >> ch1;
    
    while (ch1 != '.')
    {
        
        count = 0;
        bool searching = true;
        
        while ((count < NUM_LETTERS) && searching)
        {
            if (frequencyArray[count].letter == tolower(ch1))
            {
                frequencyArray[count].frequency++;
                searching = false;  
            }
            else
                count++; 
        }
        
        cin >> ch1;
    }    

    count = 0;
    
}


void initFrequencyArray(letterFrequency frequencyArray[])
{
    int count = 0;
    int charCount = 'a';
    
    while (count < NUM_LETTERS)
    {
        frequencyArray[count].frequency = 0;
        frequencyArray[count].letter = charCount;
        count++;
        charCount++;
    }

}


void printFrequencyTable(letterFrequency frequencyArray[])
{
    cout << endl;    
    cout << "Letter:    Number of Occurrences" << endl;
    
    for (int count = 0; count < NUM_LETTERS; count++)
    {
        if (frequencyArray[count].frequency > 0)
        {    
            cout << setw(6) << frequencyArray[count].letter;
            cout << setw(6) << frequencyArray[count].frequency;
            cout << endl;
        } 
    }
}
 
Back
Top Bottom