-3

I am writing a program that will receive a text file, read in a list of names from that file, sort those names in alphabetical order, and then print the sorted list back out.

This originally was a project for my "Intro to Programming" class that was to use arrays, but I'm trying to retool it to work with vectors instead, allowing me to use a file of any length instead of a rigid array length.

But Intellisense is giving me an error:

No suitable conversion function from "std::vector<std::string, std::allocator<std::string>>" to "std::vector<std::string, std::allocator<std::string>>*" exists

Any time that I try to pass the filename to a function (ex at displayArray(names, nameQty), I get the error with names). I'm having a hard time googling how to pass a vector to a function, so I think that's where my problem is. The full code is pasted below:

#include<iostream>
#include<fstream>
#include<string>
#include<vector>
using namespace std;

int readFromFile(string[], string);
void displayArray(vector<string>[], int);
void alphaSort(vector<string>[], int);
void swap(string&, string&);


int main() {
//Declare variables
string fileName;
vector<string>names(1);
int nameQty;

//Prompt for file name
cout << "Please enter the name of the file to read names from: " << endl;
cin >> fileName;

//Call function to open file and read names into a vector array. Function will return the number of names in file
nameQty = readFromFile(names, fileName);

//Display unsorted names
cout << "Unsorted names:" << endl;
displayArray(names, nameQty);

//Sort names into alphabetical order
alphaSort(names, nameQty);

//Display sorted names
cout << "Sorted names:" << endl;
displayArray(names, nameQty);

//More to come after this; program isn't done yet!
}

/*
* Function to read a list from a text file into an array.
* The array starts at size 1, then increments by 1 for each subsequent iteration
* The array then deletes the final element when there is nothing more to read
* (since the last element will be uninitialized)
*/
int readFromFile(vector<string> array, string fileName) {

ifstream inputFile;
inputFile.open(fileName);

if (!inputFile) {
    cout << "Invalid file name. Please restart program and try again."
        << endl;
    system("pause");
    exit(EXIT_FAILURE);
}

else {
    int index = 0;
    while (inputFile) {
        cin >> array[index];
        array.push_back;
        index++;
    }
    array.pop_back;
    inputFile.close();
    return (index + 1);
}
}

//Function to display list of items in array
void displayArray(vector<string> array[], int quantity) {
    for (int i = 0; i < quantity; i++)
        cout << array[i] << endl;
}

//Selection sort function puts array elements in alphabetical order
void alphaSort(vector<string> names[], int qty) {
    for (int j = 0; j < qty - 1; j++) {

        for (int i = j + 1; i < qty; i++) {
            if (names[j] > names[i]) {
                swap(names[j], names[i]);
            }
    }
}

}

//Function to swap elements a and b in array
void swap(string &a, string &b) {
    string temp = a;
    a = b;
    b = temp;
}

Please don't worry about my using system("pause") and using namespace std. I'm aware that's poor practice, but it's what we've been asked to do in class.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
meyers9146
  • 11
  • 3
  • 2
    You're telling the functions to accept **arrays of** `vector`, which then decay to pointers, hence the error. But you only want to pass one `vector`. A `vector` is already a container; that's its purpose; so, you don't need to do anything else to tell the function that it contains multiple elements, and if you do, it breaks everything, just like this. – underscore_d Apr 27 '18 at 14:07
  • I think you're confused about the difference between a vector and an array. Remove the `[]` on the `vector` parameters – AndyG Apr 27 '18 at 14:09
  • 1
    This could/should be a lot shorter as a [mcve]. – Jesper Juhl Apr 27 '18 at 14:11
  • Also: `readFromFile()` takes a copy of the `vector`, so its changes will not be seen outside it. You should pass a reference. And `array.push_back` with no argument list is a syntax error. And you should probably come up with a nicer design than pre-reserving 1 default element, then indexing/assigning to that, then adding another empty one - it would be cleaner and less prone to accidental indexing UB later just emplace back as needed. That's only what I noticed so far; you might well have other errors yet to be found. But it's more interesting for you to do that via an MCVE, than readers here – underscore_d Apr 27 '18 at 14:11
  • @FrançoisAndrieux Huh. That did clear the error. From how the textbook says to create vectors as "vector(quantity)" I would never have thought that was my problem. On to my other compilation errors. Thank you! – meyers9146 Apr 27 '18 at 14:13
  • @meyers9146 I think that fixes the error by accident, but it's not what you really meant and `names(1)` was fine. It's the other parts that are wrong. – BartoszKP Apr 27 '18 at 14:14
  • 1
    @meyers9146 Forget my original comment, it's silly. I had misread the line I was referring to. The problem is `std::vector[]` is an array of vectors where as you are just using a vector. It's the functions that do not have the right argument types. See the answer below. – François Andrieux Apr 27 '18 at 14:17
  • ^ Okay, so changing () to [] did clear the error, but I think in the wrong direction. @underscore_d that makes a ton of sense that it thinks I'm passing an array of vectors, instead of a single vector. And you're right, just changing () to [] did break everything. I didn't realize that vectors were copied, not referenced, since our array chapter makes sure to pay special attention to how arrays are referenced directly, so now everything is referenced that needs it. I'm down to that `push_back` error you mentioned. I think I can get it to work from here. Thanks for your help! – meyers9146 Apr 27 '18 at 14:23
  • Replacing C-style arrays with `vector` is an admirable upgrade to your code, but you need to get an idea of different those are before continuing. ;-) Raw arrays behave like the exception, not the norm. Another problem: your declaration and definition of `readFromFile()` do not agree. Are you compiling with any warnings on? Did that even compile? – underscore_d Apr 27 '18 at 14:27
  • @underscore_d First semester problems, right? I've been wondering just how useful arrays are in the end; they're so inflexible. As for `readFromFile()`, that's not throwing any compilation errors. Right now my only compile error is with `array.push_back(1)` throwing an error "cannot convert argument 1 from 'int' to 'const std::string &'" – meyers9146 Apr 27 '18 at 14:36
  • There is no way that a compiler should let you declare it as taking a `string[]` but let you actually pass a `vector`. And of course you can't put an `int` into a `vector` of `string`s. What are you actually trying to do? Just emplace a default-constructed value so that you can then index to it? Btw, what happens after your last element read? Don't you end up having a useless empty element at the end of the `vector`? This is why you should rather read the value to a temporary `string` and then directly `emplace( std::move(that_string) )` & don't worry about whether you have enough size – underscore_d Apr 27 '18 at 14:40
  • @underscore_d You're absolutely right. The way that I had understood it previously, I thought `push_back(x)` just adds in x uninitialized elements to the end of the existing array. It actually appends x to a new element at the end of the array. I'm going to just get rid of that whole block and have `cin >> input` followed by `push_back(input)` – meyers9146 Apr 27 '18 at 14:44
  • Cool. The stdlib containers don't have a concept of uninitialised elements (yet?), so you either have valid elements or you don't. You may be thinking of the difference between `resize()` and `reserve()`, but the latter only gets you uninitialised *memory* (`capacity()`) for elements so that you can later add them without reallocating: it does not increase the `size()` and hence the range of indices that are valid to access. – underscore_d Apr 27 '18 at 14:49

1 Answers1

1

You want:

void displayArray(vector<string>& array, int quantity)

or in this case even better:

void displayArray(const vector<string>& array, int quantity)

In your code it seems you are trying to pass an array of vectors (which is not that straightforward in C++ and boils down to a pointer to a vector in this case). To avoid copying you should use a reference.

You may also be interested to read about move semantics.

Also, as noted in the comments, you may also want to fix readFromFile:

int readFromFile(vector<string>& array, string fileName)

By changing it to a reference the function will modify caller's vector, instead of creating and modifying a local copy.

BartoszKP
  • 34,786
  • 15
  • 102
  • 130
  • Before it's worth displaying, they need to make `readFromFile()` actually write to it, not just a local copy! – underscore_d Apr 27 '18 at 14:25
  • @underscore_d Yeah, it's not strictly related to the error reported by OP so I didn't want to dig into this one as well. But since you've pointed it out I've included this hint as well, thanks :) – BartoszKP Apr 27 '18 at 14:57
  • 1
    [If he used `span`s](https://stackoverflow.com/questions/45723819/what-is-a-span-and-when-should-i-use-one), those would be an even better choice. – Deduplicator Apr 27 '18 at 14:59
  • Yep. This whole problem began with my treating vectors as arrays. Turns out they're treated more similarly to any other variable, and need to be referenced as such. – meyers9146 Apr 27 '18 at 15:23