I am in desperate need of help! I am having an issue inserting the word into the correct list. Each array index is a letter of the alphabet, and the words need to be put into the correct index according to the first letter of the word. Can I get some help with fixing this issue with my insertWord function?

Here is the text file I am using:

I am excited to be taking this class. Programming isn't
easy but I feel I am getting better. One day when I am
out of the military I hope to work for some IT business.
The job can't be part-time either!
67dd a09dd.

Here is the program file:

# include <iostream>
# include <iomanip>
# include <fstream>
# include <string>
# include <cctype>
# include <cstddef>

using namespace std;

const int MAX_SIZE = 26;

struct wordRec {
   string newWord;
   wordRec *previous;
   wordRec *next;
   };

void programIntro();
wordRec* initializeList ();
void initializeArray (wordRec *[], int& index);
void readTextFile (ifstream& wordIn, wordRec *letters[], int& index, int& wrdIndex);
void checkInputWord (ifstream& wordIn, string& word);
void insertWord (ifstream& wordIn, wordRec* [], int& index, string& word, int& wrdIndex);
void wordListPlacement (ifstream& wordIn, wordRec *letters[], int& index, int& wrdIndex);

int main (int argc, char* argv[]) {

wordRec* letters[MAX_SIZE];
wordRec *head = NULL;

int count;
int indexes;
int wordCount;
string words;
int wordIndex;

ifstream wordIn;

wordIn.open (argv[1]);

if (!wordIn) {
   cout << "Error! Text File did not open!" << endl;
   system ("pause");
return 1;
}
else 
initializeArray (letters, indexes);
readTextFile (wordIn, letters, indexes, wordIndex);
wordIn.close ();

system ("pause");
return 0;
}

void initializeArray (wordRec *letters[], int& index)

{
     for (index = 0; index < MAX_SIZE; index++) {
        letters[index] = NULL;
}

return;
}

void readTextFile (ifstream& wordIn, wordRec *letters[], int& index, int& wrdIndex)

{ 
   wordRec *head = letters[index];
   string word;
   char character;
   char letter;

   while (wordIn) { 
       wordIn >> word; 

  // calculates the specific list each word will go into
  character = word[0];
  letter = toupper(character);
  wrdIndex = letter - 'A'; 

 // checks the word format for errors
 checkInputWord (wordIn, word);

 // uppercases all the words in the file
 for (int indx = 0; indx < word.size(); indx++) {
     word[indx] = static_cast<char>(toupper(word[indx]));
 }

insertWord (wordIn, letters, index, word, wrdIndex);
}
return;
}

void checkInputWord (ifstream& wordIn, string& word)

{

 // strips off any punctuation if there is any
 for (int index = 0; index < word.length(); index++) {
   if ((ispunct(word[index])) && (word[index] != '\'') && (word[index] != '-')) {
      word.erase(index);
   }
}

 // ignores the word if it contains any digits and does not add it to the list!
 for (int index = 0; index < word.size(); index++) {
   if (isdigit (word[index])) {
      wordIn.ignore (word[index], word.length() );
   }
}

return;
} 

void insertWord (ifstream& wordIn, wordRec *letters [], int& index, string& word, int& wrdIndex)

{
wordRec *head = NULL;
wordRec *newNode = NULL;

if (head == NULL) {
   newNode = new (nothrow) wordRec;
   newNode->newWord = word;
   newNode->previous = NULL;
   newNode->next = newNode;

if (head != NULL) 
   head->previous = newNode;

   head = newNode;
   letters[index] = head;
   letters[index]->next = head;
   letters[index]->previous = head;

   }
return;
}

Dani AI

Generated

Diagnosis and concise fixes (why words keep going to the wrong place)

  • The main bug is that insertWord creates a local head initialized to NULL every call, so every word is treated as the first node. The function also stores into letters[index] while your computed bucket is wrdIndex. Several other issues interact: while (wordIn) instead of while (wordIn >> word), uninitialized variables passed by reference from main, incorrect use of string::erase (erase(index) removes the rest of the string), and wordIn.ignore used with wrong parameters. Also cast characters to unsigned char before toupper/classification to avoid undefined behaviour on signed chars.

Corrected insert function (circular doubly linked list per letter)

  • Change the signature to accept the computed bucket and a const word: void insertWord(wordRec* letters[], int wrdIndex, const string& word)
  • Do not reinitialize head to NULL; read it from letters[wrdIndex]. Properly link the first node to itself and for subsequent inserts splice the new node between tail and head. Optionally update the head if inserting before it to keep alphabetical order.
void insertWord(wordRec* letters[], int wrdIndex, const string& word) {
    wordRec* head = letters[wrdIndex];
    wordRec* newNode = new (nothrow) wordRec;
    if (!newNode) return;
    newNode->newWord = word;

    if (!head) {
        newNode->next = newNode;
        newNode->previous = newNode;
        letters[wrdIndex] = newNode;
        return;
    }

    wordRec* tail = head->previous;
    newNode->next = head;
    newNode->previous = tail;
    tail->next = newNode;
    head->previous = newNode;

    if (newNode->newWord < head->newWord) {
        letters[wrdIndex] = newNode; // keep head at lowest word if desired
    }
}

Sanitize input reliably

  • Replace your checkInputWord with a function that removes punctuation except apostrophes/hyphens, rejects words containing digits, and uppercases safely:
bool cleanWord(string& w) {
    string out;
    for (unsigned char ch : w) {
        if (isdigit(ch)) return false;
        if (ispunct(ch) && ch != '\'' && ch != '-') continue;
        out.push_back(static_cast<char>(toupper(ch)));
    }
    if (out.empty()) return false;
    w.swap(out);
    return true;
}

Other practical tips

  • Loop with while (wordIn >> word) and call if (!cleanWord(word)) continue; then compute int wrdIndex = toupper(static_cast<unsigned char>(word[0])) - 'A'; and check 0 <= wrdIndex < 26 before calling insertWord. Initialize variables in main (no uninitialized references). As suggested, if you can use STL, a vector<vector<string>> or map<char, vector<string>> will simplify insertion and memory management dramatically. As noted, keep code properly formatted to spot these logic errors quickly.

Recommended Answers

All 3 Replies

Please format code, and paste in the tags.

Better use maps than double link list.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.