0

I want to put first and last names into an array, but I don't want to use a 2d array because the names will always be used together for my project. I have tried something like this:

ifstream in("filename");  
string* names = new string[num];
for (int i = 0; i < num; i++) 
{  
  in >> names[i] >> names[i];  
}

But that obviously just overwrite the first name with the last name. Is there a simple way to put two words into one index?

aons32
  • 25
  • 3
  • 7
    Yes, use a `vector>`. – cigien Sep 09 '20 at 17:22
  • Is there a way to do it without vectors? I haven't learned those yet, but if its the only way I guess I will. – aons32 Sep 09 '20 at 17:25
  • Do you need the person's first and last name in separate variables? Can they have a middle name or initial? Can they have multiple first names like Betty Jane or Mary Jo? I ask this because maybe you want to just read the whole line into a std::string instead of breaking it up. – drescherjm Sep 09 '20 at 17:25
  • 3
    Go ahead and learn `vector`. It's quite easy. – cigien Sep 09 '20 at 17:26
  • 3
    Have you learned struct? You can have a struct `name` with `first` and `last` members in it, that an array of those struct – Vlad Feinstein Sep 09 '20 at 17:27
  • For this project it will always be first and last name, never middle. And I would like the first and last name to be stored together. The problem with reading the whole line is that there is other information about the person on the same line. Is there a way to read the line until you get to a number? Because that could work. – aons32 Sep 09 '20 at 17:28
  • Maybe your class expects something like a `struct Name { std::string first; std::string last;};` and you would have an array or vector of this struct. – drescherjm Sep 09 '20 at 17:29
  • 1
    In that case, you should read all the person info when reading the line. You should have a `vector` that you read into, where `Person` would have members that store the info. – cigien Sep 09 '20 at 17:30
  • 1
    If `vector` has been banned by an assignment restriction, an array will serve. Does "Von Doom" count as a last name? – user4581301 Sep 09 '20 at 17:31
  • if you have a limit of first name size then you can do it using a space between a first and last name. – Hridoy_089 Sep 09 '20 at 17:39
  • Re: `there is other information about the person on the same line` - you should start with describing the format of your data; then declare the appropriate data struct and parse the input line into it. – Vlad Feinstein Sep 09 '20 at 17:43
  • Vector was banned, and fortunately all the last names have hyphens if they are multiple words. – aons32 Sep 09 '20 at 17:44
  • My trick (and I'm sure I share it with others) for dealing with `vector` bans: Write a really simple, lightweight knock-off `vector` and use it There are some good examples of how to do this scattered around Stack Overflow. There are some really good ones on the Code Review sister site. The advantage of writing a simple vector is you can keep using it and save yourself a bunch of time and debugging in other assignments. Plus sooner or later you'll have to write one for the class anyway. – user4581301 Sep 09 '20 at 17:50
  • 1
    On the more than just the name on the line comment: When you get there, you'll probably be able to put [option 2 of this answer to really good use](https://stackoverflow.com/a/7868998/4581301). – user4581301 Sep 09 '20 at 17:52

2 Answers2

3

operator>> assigns to names[i] it does not concatenate strings. You could write an overload for >> that can concatenate strings. Would be fun but not quite appropriate here I think. Simple solution is to first read the strings, then concatenate them (I am scared of pointers, hence no pointers in my example):

std::ifstream in("filename");  
std::vector<std::string> names(num);
for (int i = 0; i < num; i++) 
{  
  in >> name[i];
  std::string last_name;
  in >> last_name;
  name[i] += " " + last_name;
}

PS: I focused on "Is there a simple way to put two words into one index?" with minimum changes on your code. The much cleaner approach would be to define a

struct name {
    std::string first_name;
    std::string last_name;
};

And then in/output operators for that type. Input would be

std::istream& operator>>(std::istream& in, name& n) {
    in >> n.first_name;
    in >> n.second_name;
}

So that reading the two string is as simple as

name n;
std::cin >> n;

Note that all this assumes that both first_name and last_name do not contain whitespaces. If they do you need to use getline or similar.

PPS: And because I think it is fun here is how you can concatenate strings via operator>>:

#include <string>
#include <iostream>

struct concatenate_input {
    std::string& parent;
};

std::istream& operator>>(std::istream& in, concatenate_input ci) {
    std::string temp;
    in >> temp;
    ci.parent += " " + temp;
    return in;
}

int main() {
    std::string name;
    std::cin >> name >> concatenate_input{name};
    std::cout << name;    
}

For input Hello World the output is Hello World. However, please take it with a grain of salt, it is only for illustration and I would definitely prefer the above solution. It has a quirk which is operator>> takes the concatenate_input parameter by value. With a (non-const) reference we could not pass temporaries which would make it much less fun.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
1

You can try this:

    ifstream in("filename");  
    vector< pair < string,string> > name(num);
    for (int i = 0; i < num; i++) 
    {  
      in >> names[i].first >> names[i].second;  
    }
Hridoy_089
  • 318
  • 3
  • 11