13 Replies - 4934 Views - Last Post: 07 February 2012 - 05:27 PM Rate Topic: -----

#1 T'Shaunik  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 31
  • Joined: 06-February 12

Error C2664: Trying to add strings to vector of structs

Posted 06 February 2012 - 08:29 PM

I am trying to make a program that will read a file and put information from it into a vector of structures so I can then write that info to a database. It's reading the pipe delimited file correctly, but I am having problems getting string variables into the vector.

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

int main () 
{
string dBTLine;
string split;
stringstream ss;
int n = 1;
struct subscriber
{
	string fName;
	string lName;
	string company;
}
vector<subscriber> sub;
ifstream dBT ("test.txt");
if (dBT.is_open())
	{
		getline (dBT,dBTLine);
		while ( dBT.good() )
	{
		system("PAUSE");  //Just to make sure I'm paying attention when it executes
		for ( int y = 0; y < 20; y++ )
		{
		
		string subscriber;
		for ( int x = 0; x < 50; x++ ) 
		{

			getline(dBT, split, '|');
			cout << split << endl;

			
			switch (x)
			{
				case 0: 
					cout << split << " inside case 0" << endl;
                                        sub[0].fName.push_back(split);
					cout << sub[0].fName<< endl;
					system("PAUSE");
					break;
                case 1: 
					cout << split << " inside case 1" << endl;
                                        sub[0].lName.push_back(split);
					cout << sub[0].lName<< endl;
					system("PAUSE");
					break;
                case 2: 
					cout << split << " inside case 2" << endl;
                                        sub[0].company.push_back(split);
					cout << sub[0].company<< endl;
					system("PAUSE");
					break;
}
dailyBundleTop.close();
	}
	}
}
}
else cout << "Unable to open file"; 

return 0;
}



So I've been trying many different ways to get the info in the file to the vector of structures. The I get is for the 2nd line of the cases:


error C2664: 'std::basic_string<_Elem,_Traits,_Ax>::push_back' : cannot convert parameter 1 from 'std::string' to 'char'
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>,
1> _Ax=std::allocator<char>
1> ]
1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called

I've been teaching myself C++ and am pretty new to it. From what I can understand, using push_back, I need to have a char in the () instead of a string. Should I have the struct use char instead of string for these variables? I tried using char, but haven't been able to find a way to convert the string to char to input. I've seen people directly enter "..." strings, but the only way I am able to is to have it already inside a variable and then try to get it into the vector of structs.

Is This A Good Question/Topic? 0
  • +

Replies To: Error C2664: Trying to add strings to vector of structs

#2 jimblumberg  Icon User is online

  • member icon


Reputation: 4076
  • View blog
  • Posts: 12,588
  • Joined: 25-December 09

Re: Error C2664: Trying to add strings to vector of structs

Posted 06 February 2012 - 09:07 PM

In the following snippet:
struct subscriber
{
	string fName;
	string lName;
	string company;
}
   vector<subscriber> sub;
   ifstream dBT ("test.txt");
   if (dBT.is_open())
   {
      getline (dBT,dBTLine);
      while ( dBT.good() )
      {
         system("PAUSE");  //Just to make sure I'm paying attention when it executes
         for ( int y = 0; y < 20; y++ )
         {

            string subscriber;
......
                                       sub[0].fName.push_back(split);



You have a structure named subscriber, then you name a string variable subscriber. You should not name a variable the same name as your structure.

Also your vector is a vector of subscriber, so you must push_back a subscriber.
sub.push_back(subscriber()); // Push back an empty structure.


Jim
Was This Post Helpful? 1
  • +
  • -

#3 r.stiltskin  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1833
  • View blog
  • Posts: 4,927
  • Joined: 27-December 05

Re: Error C2664: Trying to add strings to vector of structs

Posted 06 February 2012 - 09:36 PM

You don't seem to be using that string named subscriber (declared on line 31) anyway, so you should probably just eliminate that line.

To elaborate a bit on the push_back issue:

You have a vector<subscriber> -- in other words a vector that can contain elements of type subscriber -- but initially it doesn't contain any elements at all, not even any "empty" subscribers, just the "mechanisms" that will enable it to deal with them when they are provided. You can't push data fields into your vector; you can only push subscriber objects into it. To add anything to that vector, you have to create an object of type subscriber. You can either push the "empty" subscriber into the vector as jimblumberg suggested, and then assign data to it's data members, or alternatively you can declare a subscriber object, then assign data to the subscriber's fields and subsequently push that subscriber into the vector.

This illustrates the assignment both ways:
vector<subscriber> sub;
sub.push_back(subscriber());
sub[0].fName = someString;
sub[0].lName = someOtherString;
//...
subscriber tempSub;
tempSub.fName = someString;
tempSub.lName = someOtherString;
sub.push_back(tempSub);



You should be able to work out the rest.

One more thing:
Your method of parsing the input lines from the file is very awkward. You should investigate using an istringstream, which is perfect for that purpose. The gist of it is that you load one line from the file into the istringstream, and then read the individual fields, one at a time, from the istringstream just as if were itself a file. Then, you empty the istringstream and clear its 'eof' flag, and that's the end of the first iteration. On the next iteration of your loop, you load the next line from the file into the istringstream, and so on ...

Give it a try & post again if you get stuck.
Was This Post Helpful? 1
  • +
  • -

#4 T'Shaunik  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 31
  • Joined: 06-February 12

Re: Error C2664: Trying to add strings to vector of structs

Posted 07 February 2012 - 07:41 AM

View Postr.stiltskin, on 06 February 2012 - 09:36 PM, said:

You don't seem to be using that string named subscriber (declared on line 31) anyway, so you should probably just eliminate that line.

To elaborate a bit on the push_back issue:

You have a vector<subscriber> -- in other words a vector that can contain elements of type subscriber -- but initially it doesn't contain any elements at all, not even any "empty" subscribers, just the "mechanisms" that will enable it to deal with them when they are provided. You can't push data fields into your vector; you can only push subscriber objects into it. To add anything to that vector, you have to create an object of type subscriber. You can either push the "empty" subscriber into the vector as jimblumberg suggested, and then assign data to it's data members, or alternatively you can declare a subscriber object, then assign data to the subscriber's fields and subsequently push that subscriber into the vector.

This illustrates the assignment both ways:
vector<subscriber> sub;
sub.push_back(subscriber());
sub[0].fName = someString;
sub[0].lName = someOtherString;




Thanks so much, both of you! I decided to use this part of what you guys recommended and it worked right away! About that string subscriber, that is a good point that I need more unique variable names. In looking at that, it must have been there from before in trying stuff, that I hadn't eliminated after getting rid of unusable code.

I've been working on the program a section at a time and realized I hadn't put in for having a phone number yet. How can I pull int out of a string to put it into the structure? From what I've been reading, it looks like atoi is what I want to do that, but I haven't figured out how to do that.

struct subscriber
{
string fName;
string lName;
string company;
int phone[10];
}

//inside the switch statement
sub[x].accountNum = atoi(split); //is this the right syntax/is there a better method to use to get int from a string?



Quote

Your method of parsing the input lines from the file is very awkward. You should investigate using an istringstream, which is perfect for that purpose. The gist of it is that you load one line from the file into the istringstream, and then read the individual fields, one at a time, from the istringstream just as if were itself a file. Then, you empty the istringstream and clear its 'eof' flag, and that's the end of the first iteration. On the next iteration of your loop, you load the next line from the file into the istringstream, and so on ...


For this, would that work for taking everything between the pipe delimiters? Before I had tried using a method like that (at least I think it was a stream like that), but it was ending whenever it saw a whitespace, so I tried different things and this method works. Some of the fields have spaces in them, so I need to make sure all the info between the pipes is read.

Thanks again!
Was This Post Helpful? 0
  • +
  • -

#5 jimblumberg  Icon User is online

  • member icon


Reputation: 4076
  • View blog
  • Posts: 12,588
  • Joined: 25-December 09

Re: Error C2664: Trying to add strings to vector of structs

Posted 07 February 2012 - 08:05 AM

Quote

I've been working on the program a section at a time and realized I hadn't put in for having a phone number yet. How can I pull int out of a string to put it into the structure? From what I've been reading, it looks like atoi is what I want to do that, but I haven't figured out how to do that.

Why is phone an int? Usually a phone number is considered a string "555-555-5555".

Please show a few lines of your input file.

Jim
Was This Post Helpful? 0
  • +
  • -

#6 T'Shaunik  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 31
  • Joined: 06-February 12

Re: Error C2664: Trying to add strings to vector of structs

Posted 07 February 2012 - 08:34 AM

View Postjimblumberg, on 07 February 2012 - 08:05 AM, said:

Quote

I've been working on the program a section at a time and realized I hadn't put in for having a phone number yet. How can I pull int out of a string to put it into the structure? From what I've been reading, it looks like atoi is what I want to do that, but I haven't figured out how to do that.

Why is phone an int? Usually a phone number is considered a string "555-555-5555".

Please show a few lines of your input file.

Jim


I'm writing a program to help my mom track info for her work since the way it's done now is atrocious. (And I've figured out the best way for me to learn something is to set my sights on a tangible goal to work towards, so this is something I know what I have and what I need to do.) The file of this info she can get from work is specifically stripped of the extra characters in the phone number so that only the 10-digit number is left. I am also curious how it is done to change a number from a string into an int to store it.

John|Smith|Acme Company|5555555555
Jane|Doe|McDonalds|5555555555

I'm working on getting Case 1 set up and am getting the error "vector subscript is out of range".

for ( int x = 0; x < 50; x++ ) 
		{
			getline(dailyBundleTop, split, '|');
			cout << split << "x is at: " << x << endl;

			switch (x)
			{
case 0: 
					cout << split << " CASE 0" << endl;
					sub[x].fName= split;
					cout << sub[x].fName << " this is using x " << endl;
					system("PAUSE");
					break;
				case 1: 
					cout << split << " CASE 1" << endl;
					sub[x].lName= split;
					cout << sub[x].lName<< " this is using x " << endl;
					system("PAUSE");
					break;



It gets into case 1, but it doesn't grab the second field, which is lName. Before the switch, it shows "x is at: 1", but it doesn't have split displaying, even though it is working before and for case 0. It displays "CASE 1" from case 1, but then it stops and pops up the error.
Was This Post Helpful? 0
  • +
  • -

#7 T'Shaunik  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 31
  • Joined: 06-February 12

Re: Error C2664: Trying to add strings to vector of structs

Posted 07 February 2012 - 08:47 AM

Thanks for the quick response, Jim.

Quote

This illustrates the assignment both ways:
vector<subscriber> sub;
sub.push_back(subscriber());
sub[0].fName = someString;
sub[0].lName = someOtherString;
//...
subscriber tempSub;
tempSub.fName = someString;
tempSub.lName = someOtherString;
sub.push_back(tempSub);



I used the first way, but only put in
vector<subscriber> sub;
sub.push_back(subscriber());



I just got to thinking, does it work for fName but not lName because I didn't put in the last 2 lines of the first way r.stiltskin posted? Did stopping at the push_back line and not doing the assignment make it so that I can only put in the one element and not follow-up ones, thus explaining the vector out of subscript error?
Was This Post Helpful? 0
  • +
  • -

#8 jimblumberg  Icon User is online

  • member icon


Reputation: 4076
  • View blog
  • Posts: 12,588
  • Joined: 25-December 09

Re: Error C2664: Trying to add strings to vector of structs

Posted 07 February 2012 - 08:58 AM

Please show the complete program, plus the complete error message exactly as it appears in your development environment. These error messages have important information embedded within them to aid in locating and fixing the error.

Jim
Was This Post Helpful? 0
  • +
  • -

#9 r.stiltskin  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1833
  • View blog
  • Posts: 4,927
  • Joined: 27-December 05

Re: Error C2664: Trying to add strings to vector of structs

Posted 07 February 2012 - 10:20 AM

You're getting that "out of range" error because the overall structure of your loop
for ( int x = 0; x < 50; x++ ) 

is inappropriate.

So far you've only created one subscription object, which is located in the vector as sub[0]. So far, so good. You only want one subscription object for one subscriber.

The error is that your program is trying to store that subscriber's firstname in sub[0], the lastname in sub[1], and the company in sub[2], and so on, but sub[1] and sub[2] don't exist yet (and they shouldn't).

That's not what you want to do. You want to store the firstname in sub[0].fName, the lastname in sub[0].lName, the company in sub[0].company, etc.

As far as the phone number is concerned, even though it's all digits you should still store it as a string. Don't worry about the fact that it's composed of numerical digits -- those digits '0', '1' and so forth are still ASCII characters. Just assign the "5555555555" that you read in from the file to a string variable, the same as you do with the names. You're not doing arithmetic with the phone numbers so there's no reason to try to save them as numerical values.

This post has been edited by r.stiltskin: 07 February 2012 - 10:23 AM

Was This Post Helpful? 1
  • +
  • -

#10 T'Shaunik  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 31
  • Joined: 06-February 12

Re: Error C2664: Trying to add strings to vector of structs

Posted 07 February 2012 - 02:05 PM

View Postr.stiltskin, on 07 February 2012 - 10:20 AM, said:

So far you've only created one subscription object, which is located in the vector as sub[0]. So far, so good. You only want one subscription object for one subscriber.

The error is that your program is trying to store that subscriber's firstname in sub[0], the lastname in sub[1], and the company in sub[2], and so on, but sub[1] and sub[2] don't exist yet (and they shouldn't).

That's not what you want to do. You want to store the firstname in sub[0].fName, the lastname in sub[0].lName, the company in sub[0].company, etc.

As far as the phone number is concerned, even though it's all digits you should still store it as a string. Don't worry about the fact that it's composed of numerical digits -- those digits '0', '1' and so forth are still ASCII characters. Just assign the "5555555555" that you read in from the file to a string variable, the same as you do with the names. You're not doing arithmetic with the phone numbers so there's no reason to try to save them as numerical values.

*facepalm* I didn't realize that I was trying to have it move to another struct instead of the next element. And good point that I don't need it to be int, since it's all the same to the computer - it just needs to print it out, not add up phone numbers. I cleaned up my code (I prefer commenting stuff out that I was trying so I don't lose something that I may want later) so here it is:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
using namespace std;

int main () 
{
string dBTLine;
string split;

struct subscriber
{
	string fName;
	string lName;
	string company;
	string phone;
};
vector<subscriber> sub;
sub.push_back(subscriber());
system("PAUSE");

ifstream myFile ("test.txt");
if (myFile.is_open())
	{
		system("PAUSE");
		while ( myFile.good() )
	{
		system("PAUSE");
		for ( int y = 0; y < 3; y++ ) //temp loop to repeat and read 3 lines - to be replaced with eof test***
		{
		for ( int x = 0; x < 4; x++ ) 
		{
			switch (x)
			{
				case 0: 
					getline(myFile, split, '|');
					cout << split << " CASE 0" << endl;
					sub[y].fName = split;
					system("PAUSE"); 
					break;
				case 1: 
					getline(myFile, split, '|');
					cout << split << " CASE 1" << endl;
					sub[y].lName = split;
					system("PAUSE");
					break;
				case 2: 
					getline(myFile, split, '|');
					cout << split << " CASE 2" << endl;
					sub[y].company = split;
					system("PAUSE");
					break;
				case 3: 
					getline(myFile, split, '|');
					cout << split << " CASE 3" << endl;
					sub[y].phone = split;
					system("PAUSE");
					break;
		}
		system("PAUSE");		
	myFile.close();
	}
	}
	}
	}
else cout << "Unable to open file"<<endl; 
system("PAUSE");
return 0;
}



What it's doing right now is it will read the first entry (John) and correctly process that case, but on the 3 follow-up cases, it will not read in the file, but only output "CASE 1/2/3" and then when it tries to go to the next line, it will give that "vector subscript out of range" error, at the bottom of the debug output (I have no idea how to read this area talking about cannot find or open the PDB files - should I be posting what it says there?), it says: "The program '[2396] Xanni.exe: Native' has exited with code 3 (0x3)."
Here's the file with sample text file: Attached File  test.TXT (101bytes)
Number of downloads: 29

Do I need to initialize follow-up structs before I can add info, like I did the first struct?

What I can't figure out is why it won't do the
 getline(myFile, split, '|'); 
in the different cases after the first, even though it IS looping through them. Is there something with the "split" variable that's not working with the way I have the code? I thought I had the getline code working earlier in testing and it read right through the file and spit it out without problems.

Thanks both of you for helping me out. You're explaining it so I can understand the why, not just the what.
Was This Post Helpful? 0
  • +
  • -

#11 r.stiltskin  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1833
  • View blog
  • Posts: 4,927
  • Joined: 27-December 05

Re: Error C2664: Trying to add strings to vector of structs

Posted 07 February 2012 - 02:37 PM

The immediate problem is ... well there are a few. I'm surprised that you can compile that code at all, because the definition of the subscriber class should not be in your main function; it should be defined before the beginning of main.

The reason that your subsequent attempts to read from the file fail is because you are closing the file at the end of the switch statement.

But really, this is a terrible way to go about this. You can make it work, after a fashion, but it's absolutely not what a switch statement is intended for.

I suggest that you look again at my earlier post where I described how to do this using a stringstream, read the istringstream documentation and that way you will be exerting your efforts in a much more productive direction.
Was This Post Helpful? 1
  • +
  • -

#12 jimblumberg  Icon User is online

  • member icon


Reputation: 4076
  • View blog
  • Posts: 12,588
  • Joined: 25-December 09

Re: Error C2664: Trying to add strings to vector of structs

Posted 07 February 2012 - 02:38 PM

What is the purpose of the switch statement? The two for statements?

In your input file you have multiple lines of text in the following format: First|Last|Company|phone
I would first read an entire line into a string. I would then use stringstreams to process that string, inserting the items into a temporary structure to make adding to the vector easier.

Something like:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>

using namespace std;

struct subscriber
{
   string fName;
   string lName;
   string company;
   string phone;
};

int main ()
{
   vector<subscriber> sub;

   ifstream myFile ("test.txt");
   if (myFile.is_open())
   {
      std::string line;
      /* The following will read an entire line of text into line.
         If the read fails for any reason it will end the processing.*/
      while ( getline(myFile, line))
      {
         // Temporary structure to insert the line information into.
         subscriber temp;
         istringstream ins(line); // Use a stringstream to process the line.
         getline(ins, temp.fName, '|'); // Extract the first item, place it into the temporary structure.
         getline(ins, temp.lName, '|');
         getline(ins, temp.company, '|');
         getline(ins, temp.phone);
         // Now add this subscriber to the vector.
         sub.push_back(temp);
      }
      /* Print the vector so you can see that the reading worked */
      cout << sub.size() << endl;
      for(size_t i = 0; i < sub.size();++i)
         cout << sub[i].fName << " " << sub[i].lName << " "
              << sub[i].company << " " << sub[i].phone << endl;
   }
   else
   {
      cout << "Unable to open file"<<endl;
   }

   // Pause the program so you can see the output.
   cin.get();

   return 0;
}




Also I would move your structure definition to outside of main(). To allow using this structure in other functions as you build your program.

Jim
Was This Post Helpful? 1
  • +
  • -

#13 T'Shaunik  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 31
  • Joined: 06-February 12

Re: Error C2664: Trying to add strings to vector of structs

Posted 07 February 2012 - 03:43 PM

Quote

The reason that your subsequent attempts to read from the file fail is because you are closing the file at the end of the switch statement.

*facepalm* number 2. I put the close there thinking "oh, well it's OUTSIDE of the switch, so that's where I should put it, because the switch is what needs to get done." Not realizing it's INSIDE the for loop that is necessary to make the switch happen. *facepalm*

Quote

I suggest that you look again at my earlier post where I described how to do this using a stringstream, read the istringstream documentation and that way you will be exerting your efforts in a much more productive direction.


Thanks for pointing that out again. I had used some implementation of a stream before, but that stopped at the whitespaces, but looking at istringstream, I see that it will go until the delimiter is found, so I won't be cut off at a space.

Quote

The immediate problem is ... well there are a few. I'm surprised that you can compile that code at all

I excel at the impossible. :)

Quote

But really, this is a terrible way to go about this. You can make it work, after a fashion, but it's absolutely not what a switch statement is intended for.


I didn't realize I could use istreamstring to read the fields correctly, so what I came up with when my attempt failed to use a form of stream (can't remember which it was, just that it stopped at whitespaces), was to use what I did get to work
getline(myFile, split, '|');
and put it into a switch using a counter to tell it the correct element of the structure to go into. I didn't really realize that I could push a fully filled in structure onto the end of a vector of structures. (Was having a hard time finding documentation on vectors of structures - I ran across arrays of structures, but I don't want a built-in Y2K type bug by imposing artificial limitations.)

Quote

What is the purpose of the switch statement? The two for statements?


The outside for loop was to make it loop each line, one at a time until the number specified was reached - that was intended to be temporary until I got around to fixing that so it would be a test to go until the end of file. The inside for loop was to have it loop the necessary number of times and keep count of what field I am in so that it could insert the necessary fields into the struct.

I sort of try to focus on one area at a time to really try and figure out how to do something and then move onto the next area. So my code is sort of like a ramshackle hut - I just sort of build off what I got to work for a goal, so it just sort of goes together. I guess that's like a house of cards - that could cause it to collapse, but it's all a process for me to learn this stuff. I'm really getting into writing this program and thinking about what other ones I could work on to continue learning. I didn't use to like programming much, but it's getting to be more fun as I'm getting into it.

When this is finished, I'm thinking I might move onto inserting this info into a PostgreSQL database. Last year I did some programming MySQL using php, so I want to try a different system (and see how much I remember about querying databases and such).

Do you have any recommendations for learning about classes? I keep hearing about c++ being object oriented, but I guess I still don't fully grasp what that means. When would I use one and how would I make it? So if I were to want this to pull this info out of a file and write to a database, would pulling the info out of a file be one class and then putting to the database be another? And can vectors of structures even be passed from a class to the main program and vice versa?

Thank you so much! I really like learning where I went wrong so I can keep improving.
Was This Post Helpful? 0
  • +
  • -

#14 r.stiltskin  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1833
  • View blog
  • Posts: 4,927
  • Joined: 27-December 05

Re: Error C2664: Trying to add strings to vector of structs

Posted 07 February 2012 - 05:27 PM

View PostT, on 07 February 2012 - 05:43 PM, said:

I didn't realize I could use istreamstring to read the fields correctly, so what I came up with when my attempt failed to use a form of stream (can't remember which it was, just that it stopped at whitespaces) ...


There are two getline functions. The one you've been using here is part of the <string> library. The other is a member of <istream>, and therefore inherited by <fstream> and <stringstream>. The key difference is that the first one saves the input in a C++ string and the second one saves the input in a "C string" (a char array terminated by a '\0' null character). Both of these functions stop at a newline by default, and both also let you specify any other delimiter as you've been doing. The common input operator that stops at any whitespace is the >> "extraction operator" so that's probably what you're thinking of. It's part of the <istream> library so it can be used with fstreams and stringstreams, but not the best choice for what you're doing in this program.


Regarding learning about classes, you can read the Wikipedia article about object-oriented programming for an overview, and there are lots of tutorials online (just search for c++ object-oriented programming) but I think you would be much better off getting a textbook. I like C++ Primer by Lippman, but there are plenty of others. If you're on a tight budget Bruce Eckel's Thinking in C++ is available free online. I personally don't think it's the best book available, but it's pretty good and ... it's free.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1