-
string input problem
I am trying to create an inventory-esque program. I want to be able to enter in some data about a product and then save it into another struct and then enter another if so desired. The problem is i enter in one item and all of it's properties and then when it loops around to enter another one, it skips the forst entry. I think it has to do with my string instruction.
Here is the code:
Code:
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
#include <conio.h>
#include <iomanip>
using namespace std;
struct co {
string name; //Product Name
string model; //Model Number
string descrip; //Description
double Rprice; //Retail price
double priceP; //Price Paid
};
int main()
{
//After data is entered, save it into another struct to be searched later.
//Create counter
int proceed=1;
string decision;
co inven; //Declare struct for inventory
while(proceed)
{
cout<<"Enter the Product name: "; //Product Name
getline ( cin, inven.name );
cout<<"Enter the Model number: "; //Model Number
getline(cin,inven.model);
cout<<"Enter Description of Item: "; //Description
getline(cin,inven.descrip);
cout<<"Retail Price Paid: "; //Retail Price
cin>>inven.Rprice;
cout<<"Actual Price Paid: "; //Price Paid
cin>>inven.priceP;
cout<<"Would you like to add another item? (Yes/No) ";
cin >> decision;
if (decision!="yes")
proceed=0;
else
proceed=1;
}
//Display
cout <<"\n-----------------------------------------------\n" << endl;
cout << "Product Name: " << inven.name << endl;
cout << "Model Number: " << inven.model << endl;
cout << "Product Description: " << inven.descrip << endl;
cout << "Retail Price: $" << inven.Rprice << endl;
cout << "Actual Price: $" << inven.priceP << endl;
return 0;
}
Output Problem after first item & description was entered.
Code:
Enter the Product name: Enter the Model number:
Any help would be much appreciated.
Gracias.
-
This is a common problem. In fact, everyone re-discovers it when they start working with C or C++. The problem is that formatted input functions don't mix well with unformatted input functions because the formatted input functions (ie. >> and scanf) treat newlines differently than common unformatted input functions (ie. getline and fgets). A quick fix is to just discard any leftover characters in the stream:
Code:
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
#include <conio.h>
#include <iomanip>
#include <limits>
using namespace std;
struct co {
string name; //Product Name
string model; //Model Number
string descrip; //Description
double Rprice; //Retail price
double priceP; //Price Paid
};
int main()
{
//After data is entered, save it into another struct to be searched later.
//Create counter
int proceed=1;
string decision;
co inven; //Declare struct for inventory
while(proceed)
{
cout<<"Enter the Product name: "; //Product Name
getline ( cin, inven.name );
cout<<"Enter the Model number: "; //Model Number
getline(cin,inven.model);
cout<<"Enter Description of Item: "; //Description
getline(cin,inven.descrip);
cout<<"Retail Price Paid: "; //Retail Price
cin>>inven.Rprice;
cout<<"Actual Price Paid: "; //Price Paid
cin>>inven.priceP;
cout<<"Would you like to add another item? (Yes/No) ";
cin >> decision;
if (decision!="yes")
proceed=0;
else
proceed=1;
cin.ignore ( numeric_limits<streamsize>::max(), '\n' );
}
//Display
cout <<"\n-----------------------------------------------\n" << endl;
cout << "Product Name: " << inven.name << endl;
cout << "Model Number: " << inven.model << endl;
cout << "Product Description: " << inven.descrip << endl;
cout << "Retail Price: $" << inven.Rprice << endl;
cout << "Actual Price: $" << inven.priceP << endl;
return 0;
}
-
Thanks, that helped a lot. I may have some more questions concerning structs. Would it be easier to use classes? I haven't gone over this stuff in about a year. Just brushing up.
-
>Would it be easier to use classes?
It depends on the use. If you're using something very simple like a point then a struct is easier because you don't have to worry about access specifiers. public is the default:
Code:
struct point {
int x, y;
};
If you used a class then you would have to explicitly say that the data is public:
Code:
class point {
public:
int x, y;
};
On the other extreme, if you're creating an object with private data then a class would more clearly show your intentions. In the end, there's no difference at all between classes and structs aside from the name and the default access level.
-
Is there anyway to create a counter to be incrimented and added to a struct name like:
Code:
int elem=0;
elem++;
//create struct to hold copied data
struct DataCopy;
//add incrimented variable to struct name
DataCopy+elem;
This might be an easy thing to do and maybe I'm looking somthing over, but any help will be great.
-
If I understand your question correctly, it wouldn't be too difficult. Check the faq on how to convert an int to a string and then it should be easy since you are using the std::string object.
-
>Is there anyway to create a counter to be incrimented and added to a struct name
Can you rephrase your question? I don't understand what you're trying to do, so suggesting a solution would likely be counter-productive.
-
Prelude: What the question means is, "Can I create a struct name dynamically based on an interger counter."
Unfortunately, I don't know what the answer to that would be, but I suspect you can't. Last I knew, variable names had to be declared at compile-time.
Edit: Something like -
Struct0
Struct1
Struct2
Struct3
...
StructN
-
Lithorien re-phrased my question perfectly. However, I will try JaWiB's idea.. I just took a class in Python and it seemed to be more user friendly than C++ is.. I guess I'm just spoiled. I'll let you know the outcome. If you have anymore ideas, please post away.
Thanks
-
>Can I create a struct name dynamically based on an interger counter.
That's what I though, but it never hurts to ask for clarification. The answer is no; and yes, but it's not advisable; and yes, but it's not what you're thinking.
Being less cryptic, no, you can't do it normally. However, you can fake it by using the preprocessor, but the preprocessor causes too many problems for that solution to be a good one. You can also simulate similar behavior by using a map keyed on the integer. That's usually the best solution, but people coming from high level scripting languages find it overly verbose:
Code:
#include <iostream>
#include <map>
#include <string>
using namespace std;
struct data {
string s;
data() {}
data ( const string& init ): s ( init ) {}
};
int main()
{
map<int, data> data_map;
int counter = 0;
data_map[++counter] = data ( "test" );
data_map[++counter] = data ( "another test" );
map<int, data>::iterator it = data_map.begin();
while ( it != data_map.end() ) {
cout<<"data"<< it->first <<": "<< it->second.s <<'\n';
++it;
}
}
-
Instead of doing anything too complicated, it came down to something as simple as using the string conversion in the FAQ and this code:
Code:
int number=5;
string test="data";
string final;
cout << "int: " << number << " string: " << result << endl;
final=test+result;
cout << final << endl;
Thanks for all the help.
If (i have anymore questions)
{
I'll post.
}
-
Well, I guess I got so caught up in trying to add two strings together I forgot why I was trying to do it in the first place. I tried creating a new struct from the combined string and that obviously did not work. I guess I will try another method of cataloging.
-
>I tried creating a new struct from the combined string and that obviously did not work.
Right, you can't declare an object using the value of a string as the type. But I figured I would let you give it a shot first. There's no knowledge like knowledge born of experience. :)
>I guess I will try another method of cataloging.
As I said before, std::map is your easiest option. Everything else would involve you basically implementing your own associative array or using a non-portable library.