简体   繁体   中英

Accessing a vector of pointers

this is for a CS assignment. I've looked at similar problems/questions, but can't seem to find an answer for this.

A little background info: We need to sort c-strings in a list and count how many times each word occurs. Needed for the problem: Write a program Problem2_A.cpp that inputs several lines of text from the keyboard as C-strings and prints an alphabetical listing of each word in the text and how many times it occurred. To do this, keep a pointer to each word in an array of pointers. Use the qsort() function to sort the array of pointers and then count the number of occurrences of each word. Terminate input by signaling end-of-file from the keyboard. Ignore any case differences (eg, “Cat” and “cat” are the same word). As a minimum requirement, you may assume there will be no punctuation marks and that exactly one space will separate words in the input lines. You may remove this limitation as an extension.

Edit- I understand I will need to have user input one line with a bunch of words. For now, I will just input each word manually as I am more concerned about accessing the vector and retrieving what I want to retrieve.

Here is what I have so far

Word.H

#pragma once
#ifndef __WORD_H__
#define __WORD_H__
#define _CRT_SECURE_NO_WARNINGS

class Word {
public:
    Word(char * word);

    ~Word();

    /* Returns the inputted word */
    const char* getWord();

private:
    char word[51];
};

#endif

Word.cpp

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include "Word.h"

Word::Word(char * word) {
    strcpy(this->word, word);
}

Word::~Word() {

}

const char* Word::getWord() {
    char* clone = new char[50];
    strcpy(clone, word);
    return clone;
}

Problem2.cpp

#include <iostream>
#include <vector>
#include "Word.h"

using namespace std;

const int MAX_WORDS = 2;
const int MAX_WORD_LENGTH = 15;

char* promptWord();


int main() {
    char inputWord[MAX_WORD_LENGTH];
    vector<Word*> pWordList;
    pWordList.reserve(MAX_WORDS);

    cout << "Please type each word and press enter: ";

    for (int i = 0; i < MAX_WORDS; i++) {
        Word* newWord = new Word(promptWord());
        pWordList.push_back(newWord);
    }

    cout << "Printing &pWordList[i]" << endl;
    for (size_t i = 0; i < pWordList.size(); i++) {
        cout << &pWordList[i] << endl;
    }

    cout << "Printing (void*)pWordList[i]->getWord()" << endl;
    for (size_t i = 0; i < pWordList.size(); i++) {
        cout << (void*)pWordList[i]->getWord() << endl;
    }

    cout << "Printing pWordList[i]->getWord()" << endl;
    for (size_t i = 0; i < pWordList.size(); i++) {
        cout << pWordList[i]->getWord() << endl;
    }

    cout << "Printing (*pWordList[i]).getWord()" << endl;
    for (size_t i = 0; i < pWordList.size(); i++) {
        cout << (*pWordList[i]).getWord() << endl;
    }

    /* Delete our dynamic objects */
    while (!pWordList.empty()) {
        delete pWordList.back();
        pWordList.pop_back();
    }




    system("pause");
    return 0;
}

/*
Ask the user to enter their desired word
@params inputWord[MAX_WORD_LENGTH] -> Desired word to be inputted
@return Returns the user's inputted word
*/
char* promptWord() {
    char inputWord[MAX_WORD_LENGTH];
    cin.getline(inputWord, MAX_WORD_LENGTH);
    return inputWord;
}

I was never too good with pointers, but if I'm understanding this right, what I currently have is a vector of pointers pointing to the locations of my Word objects, which I have dynamically assigned.

Part of my confusion possibly comes from the question -- Do I need to put objects into the vector of pointers? Or do I make pointers to the objects and put those pointers in the vector of pointers?

Anyways, as you can see i'm trying to figure out the correct way to output the word. When I call it as

cout << &pWordList[i] << endl;

this outputs a location address for each word (pointer of word?). Using

cout << (void*)pWordList[i]->getWord() << endl;

will output a different location (pointer to the index of the vector?)

and using

cout << pWordList[i]->getWord() << endl;

and

cout << (*pWordList[i]).getWord() << endl;

will print out the same junk.

I am most likely doing this wrong because

pWordList[i]->getWord()

should print out the c-string in question, but I think it is somewhere getting lost in transit and the pointer location becomes invalid. Really any advice or input would be offered.

Edit2-- As noted by Colin Basnett and T33C, I have changed the function to

/*
Ask the user to enter their desired word
@return Returns new dynamic char containing inputted word
*/
char* promptWord() {
    char* inputWord = new char[MAX_WORD_LENGTH];
    cin.getline(inputWord, MAX_WORD_LENGTH);
    return inputWord;
}

and I am now able to output the right thing. Still wondering about the two different locations coming from &pWordList[i] and (void*)pWordList[i]->getWord()

Edit3-- Here is my method containing my non-working map. It should sort the vector and create a map with the word (which is actually the pointer to the word) and the amount of times it occurrs. However, it just sorts it. It prints out each word with an occurrence of 1, even if the same word was entered multiple times. This is because it's actually inserting the pointer to the word, not the word itself, into the key section.

void measureVector(vector<Word*> ourVector, int numOfElements) {
    int count = 0;
    bool isDone = false;
    qsort(&ourVector[0], ourVector.size(), sizeof(Word*), wordCompare);

    map<Word*, int> wordCount;
    for (int i = 0; i < ourVector.size(); i++) {
        wordCount[ourVector[i]]++;
    }

    for (auto const& wc : wordCount) {
        cout << wc.first->getWord() << " appears " << wc.second << " times." << endl;
    }

}

I have tried changing

for (int i = 0; i < ourVector.size(); i++) {
    wordCount[ourVector[i]]++;
}

to

for (int i = 0; i < ourVector.size(); i++) {
    wordCount[ourVector[i]->getWord()]++;
}

However, that gives an error stating

'[': no operator found which takes a right-hand operand of type 'const char *' (or there is no acceptable conversion)

Edit4-- I emailed my professor again seeing if creating a map of strings and converting the char* to a string and he said that I could, so here is the updated measureVector method incase anyone else was following this.

/*
    Sorts our vector of pointers and puts all words into a map and
    keeps track of each word's occurrence.
    @params inputVector -> The vector of pointers to utilize.

*/
void measureVector(vector<Word*> inputVector) {
    /* Sort our vector of pointers */
    qsort(&inputVector[0], inputVector.size(), sizeof(Word*), wordCompare);
    map<string, int> wordCount;
    string ourString;

    /* For each word in our vector, insert it into our map. */
    for (auto word : inputVector) {
        ourString = word->getWord();
        wordCount[ourString]++;
    }

    /* For each unique word in our map, print out the word and how many times it occurred.*/
    for (const auto &p : wordCount) {
        cout << p.first << " appears " << p.second << " time" << (p.second > 1 ? "s." : ".") << endl;
    }
}

Thanks for the guidance, all!

There are many issues in this code but key to your question is that you are returning a pointer to a buffer on the stack which no longer exists after the function returns. Function returns unwind their stack frame.

char* promptWord() {
    char inputWord[MAX_WORD_LENGTH];
    cin.getline(inputWord, MAX_WORD_LENGTH);
    return inputWord;
}

I hesitate to say declare the buffer on the heap and return a pointer to that because the whole code is quite far from where it should be for modern C++.

I recommend using:

  1. std::string and returning that instead of a char*
  2. never use new outside of a smart pointer (or something that will guarantee to call delete) see std::unique_ptr but std::string will be a better option in your case.

All the best with your studies.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM