The problem with this code is that there are no errors showing, but when i compile the program, the if else statements do not carry out as they should do. Both if statements show the same answer, for example the second if statement. If I type Y or N then I get the same thing, 'You will now choose an event'. How do i get rid of this problem? Is char supposed to be used or string?
#include <iostream>
#include <iomanip>
#include<stdlib.h>
class start
{
public :
void getusertype ();
void registeruser ();
start();
protected :
char consumer_name[20],
consumer_address[30],
consumer_email[30];
char user[8];
};
start::start()
{
char terminator;
cout <<"Are you the venue manager, consumer or ticket agent?";
cin.get(user,8);
cin.get(terminator);
}
void start::getusertype ()
{
char terminator;
if(user[8])
{
cout <<"You have now entered the system." <<endl <<endl;
cin.get(terminator);
}
else
{
cout <<"You can only enter this part of the system if you are a consumer.";
}
}
void start::registeruser()
{
char option[1];
cout <<"Are you registered? (Enter Y/N)";
cin.get(option,1);
if (option=="N")
{ char terminator;
cout <<"Please enter your registration details" <<endl <<endl;
cout << " Enter your full name: " <<endl;
cin.get (consumer_name,20);
cin.get(terminator);
cout <<"Enter your address: " <<endl;
cin.get(consumer_address,30);
cin.get(terminator);
cout <<"Enter your email address: " <<endl;
cin.get(consumer_email,30);
cin.get(terminator);
}
else
{
cout <<"You will now choose an event.";
}
}
If you really want to use char [] rather than std::string (which has an operator== and clearly acts more like what you expect) you'll need to edit your if statement to use the old C-way of doing string comparisons. Something like:
if ( strcmp(option, "N") == 0)
{
// ...
}
Or since you are comparing only one character you could just do:
if ( *option == 'N' )
{
// ...
}
This dereferences the pointer to the first character in that char [] which is a primitive type and so can be compared directly with ==.
char option[1]; ... if (option=="N")
The 'if' statement compares the address of the option array with address of a constant string; they will never be equal.
Writing in C style, you could write something like if (strcmp(option, "N") == 0) or several other things. But it would be better to get used to using std::string in C++ code; and it's more direct. If option was a std::string, your 'if' statement would have been correct.
Take, for example
if (option=="N")
This compares option, decayed to a pointer, to the address of the literal "N". That will always return false. To compare the contents of C strings you need to use strcmp.
Do yourself an enormous favour and use std::string instead of C strings.
You are using 'C' strings - that end of the day are just pointers. So you need to use the function strcmp - but std::strings will save the hassle.
To understand why this doesn't work, you need to know a few things about how pointers work.
What is a pointer?
A pointer is a type that points to a value. So when you declare a variable with a type char:
char foo;
char* bar = &foo;
You are reserving a chunk of memory to store a character. The variable bar points to the variable foo. You can get the value stored in foo by using it directly or dereferencing the variable bar (*bar).
When you declare a variable with a char pointer type:
char* foo
You are reserving a chunk of memory to store a chunk of memory to store a character.
But I never made pointer!
In C/C++, an array can be implicitly converted into a pointer. This is not what actually happens with the code you wrote, but you can think of it like this:
char optionValue;
char* option = &optionValue;
Why does my if statement not work?
When you compare pointers, you compare the chunk of memory you are pointing to with the other pointer's chunk of memory. So == will only return true if the two pointers point to the same chunk of memory. In your code, this is impossible: the constant "N" will never be the same as the pointer that points to the chunk of memory the compiler created for you.
What you need to do is compare the content of the chunks of memory (by using strlen as suggested by other people) or changing the type of the variable (strings are very common, so there is a std::string type to deal with them).
How do i get rid of this problem?
Stop using character arrays.
where do i call std::string ?
Like this:
#include <iostream>
#include <iomanip>
#include <string>
#include <limits>
class start
{
public :
void getusertype ();
void registeruser ();
start();
protected :
std::string consumer_name;
std::string consumer_address;
std::string consumer_email;
std::string user;
};
start::start()
{
std::cout <<"Are you the venue manager, consumer or ticket agent?";
std::getline(std::cin, user);
}
void start::getusertype ()
{
if(user == "consumer")
{
std::cout <<"You have now entered the system.\n\n";
}
else
{
std::cout <<"You can only enter this part of the system if you are a consumer.\n";
}
}
void start::registeruser()
{
std::string option;
std::cout <<"Are you registered? (Enter Y/N)";
std::cin >> option;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
if (option=="N")
{
std::cout <<"Please enter your registration details\n\n";
std::cout << " Enter your full name: \n";
std::getline(std::cin, consumer_name);
std::cout <<"Enter your address: \n";
std::getline(std::cin, consumer_address);
std::cout <<"Enter your email address: \n";
std::getline(std::cin, consumer_email);
}
else
{
std::cout <<"You will now choose an event.\n";
}
}
Related
I'm working on an assignment right now and when run my code returns this error:
main.cpp:60:20: error: ‘dataArr’ was not declared in this scope
if(tolower(dataArr[i].last) == tolower(lastName))
I'm not quite sure what I'm missing here. If I could at least get it to run I'd appreciate it. Thanks.
I thought arrays were declared globally so i thought it wouldn't be an issue in my functions
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
struct Database
{
string first;
string last;
string ID;
string phoneNum;
};
void lastSearch(string);
void idSearch(string);
int main()
{
Database dataArr[100];
ifstream myFile("library_database.txt");
int count = 0;
while(!myFile.eof() && count < 100)
{
myFile >> dataArr[count].first >> dataArr[count].last >> dataArr[count].ID >> dataArr[count].phoneNum;
cout << dataArr[count].first << " " << dataArr[count].last << " " << dataArr[count].ID << " " << dataArr[count].phoneNum << endl;
count++;
}
int input;
string search;
cout << "Would you like to search by last name or member ID?\n1. Last Name\n2. ID\n> ";
cin >> input;
while(input != 1 || input != 2)
{
cout << "Enter a valid answer.\n> ";
cin >> input;
}
if(input == 1)
{
cout << "Enter last name: ";
cin >> search;
lastSearch(search);
}
if(input == 2)
{
cout << "Enter ID: ";
cin >> search;
idSearch(search);
}
return 0;
}
void lastSearch(string lastName)
{
int num = 0;
for(int i = 0; i < 100; i++)
{
if(tolower(dataArr[i].last) == tolower(lastName))
{
cout << dataArr[i].first << " " << dataArr[i].last << " " << dataArr[i].ID << " " << dataArr[i].phoneNum << endl
num++;
}
}
if(num == 0)
{
cout << "No match was found in the file.";
}
}
voidSearch was removed to allow this to be posted
To answer the title of your post: because it isn't.
You declare dataArr in main, but you are trying to use it in lastSearch, so lastSearch can't see it. But you can pass it in as a parameter, that's probably the easiest fix:
void lastSearch(const string lastName, const Database *dataArr) { ... }
and call it like this:
lastSearch (search, dataArr);
Note the use of const (get into the habit of doing that whenever you can) and that your array 'decays' to a pointer when you pass it as a parameter like this, so don't be tempted to use sizeof in lastSearch. If you need to know the number of elements in the array, pass that as a parameter too.
Or, better, use std::array instead of a C-style array and then the size of the array is available in lastSearch without the need to pass it in separately. If you do that, you probably want to pass it by const reference to avoid copying it every time you call the function.
Finally, it might be time to learn about std::vector. At the expense of a little more complexity (but not much), this would avoid the need to allocate a fixed size array. Again, for the same reason, pass it around by reference.
Some bedtime reading: The Definitive C++ Book Guide and List
Arrays are not declared globally, they are declared where you declare them :-)
In your case, you declare it at the top of main() so that is its scope, from point of declaration to end of main(). Trying to use it in lastSearch() is therefore invalid.
The easiest fix is probably just to move the declaration immediately before main() so that it is global. But the easiest things is often not the right thing.
You would be better off embracing C++ fully(1) and using something like std::vector, whose size isn't arbitrarily limited to 100 (for example) and which you could pass around quite easily, something like:
#include <iostream>
#include <vector>
void function(const std::vector<int> &vec) {
std::cout << vec.size() << ' ' << vec[0] << '\n'; // Output: 2 42
}
int main() {
std::vector<int> x;
x.push_back(42);
x.push_back(99);
function(x);
}
The main advantages with vectors are that:
you're not limited to a maximum of 100 items;
you don't have to pass around the actual count of items read separately as with a raw array or even a std::array (you don't do that in your code but I assure you, that's a problem).
the size of the vector is an integral property of the vector, available anywhere the vector is in scope.
(1) There's a variety of developers I like to call C+ developers. These are the people that, though they claim to be C++ developers, have never really embraced the C++ way of doing things, sticking to C style programming practices like non-smart pointers or normal arrays :-)
Some of those things may still have a place in modern C++ code but you should be circumspect in their use.
For my homework assignment I'm supposed to make a create-your-own-adventure story. There are certain words in the text that are in all caps to represent boolean values that I need to display at the end if the player got them, like a status effect or something. I'm having trouble figuring out how to pass the booleans to the functions so that it makes it to the end of the program where I can display it. My program has functions within functions.
I've tried making the function that sets the boolean to true a boolean itself, then returning the boolean but that just ends the program it seems. I've also tried passing it through the first function call to see if it reaches the second but it doesn't seem like it wants to.
void A1();
bool A100(bool INTIM);
void A167();
void A232();
void A290();
void A13();
void A212();
void A173();
void A159();
void A161();
int main() {
bool INTIM;
A1();
cout << INTIM << endl;
return 0;
}
void A1()
{
int choice;
cout << "Well, Mr Artanon, ...\n 1. ’It’s you who’ll get a rare cut
across that corpulent neck of yours if you don’t speed things along, you
feckless blob of festering lard.’\n 2. ’Surely in such an industrious
kitchen, there must be a starter or two ready to send along and sate His
Abhorentness’s appetite?’\n (enter a menu option): ";
cin >> choice;
while (choice != 1 && choice != 2)
{
cout << "Enter in a valid choice (1 or 2)";
cin >> choice;
}
if (choice == 1)
{
A100();
}
if (choice == 2)
{
A167();
}
}
bool A100(bool INTIM)
{
int choice;
INTIM = true;
cout << " Repugnis turns a paler...\n 1. Onwards, Mr Artanon.\n (enter
in a menu option): ";
cin >> choice;
while (choice != 1)
{
cout << "Enter in a valid option (1)";
}
return INTIM;
A232();
}
What I'm wanting to happen is, the bool INTIM to be passed along so i can display it back in main with the cout statement. I know it will just be a 1 or 0 at the end but I'm just trying to get it to show up at least in the end when I display it. Again there are functions within functions in this program and that might be my problem but I wouldn't think so. There is also functions that come after this, this is not the end of the program and if I need to post the whole thing I will
Calling A100 as written, you need to pass in INTIM and accept the return value
INTIM = A100(INTIM);
But... The initiqal state of INTIM is never used, so you could
INTIM = A100();
and change A100 to look more like
bool A100()
{
int choice;
cout << " Repugnis turns a paler...\n 1. Onwards, Mr Artanon.\n (enter in a menu option): ";
cin >> choice;
while (choice != 1)
{
cout << "Enter in a valid option (1)";
cin >> choice; // added here because otherwise choice never changes
// and this loop will go on for a long, long time.
}
A232(); // moved ahead of return. Code after a return is not run
return true;
}
But since A232 is called and may set additional flags you cannot return, you have a design flaw: What if A232 also modifies a boolean? You can only return one thing from a function. You could pass A232's boolean in by reference, but what it A232 then calls B484 and it also has a boolean?
You don't want to have to pass around every possible boolean, that would be a confusing mess, so consider making a data structure that stores all of your booleans to pass around.
And that leads to an even better idea: encapsulating the booleans and the functions in the same data structure so that you don't have to pass anything around; it's all in the same place.
Do I need to pass them [the boolean results] to the functions?
Often, but not always, it is my preference to pass them by reference, and yes, it can get to be a big chain thru many functions. sigh.
But your question is "Do you need to pass them ...".
The answer is No.
Because
a) you have tagged this post as C++, and
b) the key feature of C++ is the user-defined-class.
Consider declaring every 'adventurous function' of your story within a class scope.
Each 'adventurous function', as an attribute of the class, is implemented with one 'hidden' parameter, the 'this' pointer to the class instance.
So .. if you place all your 'result' booleans as data attributes of the class, invoking any 'adventurous function' will also 'pass' all the class instance data attributes (all your bools!) as part of the invocation. No data is actually moving, just a pointer, the 'this' pointer.
It might look something like this:
#include <iostream>
using std::cout, std::cerr, std::flush, std::endl;
// using std::cin;
#include <iomanip>
using std::setw, std::setfill;
#include <sstream>
using std::stringstream;
#include <string>
using std::string;
namespace AS // Adventure Story
{
class CreateYourOwnAdventureStory_t
{
private:
// diagnostic purposes
stringstream ssUI;
// command line arguments concatenated into one string
// contents: strings convertable to ints to mimic cin
bool INTIM;
// other results go here
public:
int operator()(int argc, char* argv[]) {return exec(argc, argv);}
private:
int exec(int argc, char* argv[])
{
int retVal = 0;
// capture all command line arguments into a string
for (int i=1; i<argc; ++i)
ssUI << argv[i] << " ";
cout << "\n ssUI: " << ssUI.str() << "\n\n\n";
A1();
cout << "\n INTIM : " << INTIM << endl;
// ?more here?
return retVal;
}
void A1()
{
int choice = 0;
cout << "Well, Mr Artanon, ...\n "
"\n 1. ’It’s you who’ll get a rare cut across that corpulent neck of yours "
"if you don’t speed things along, you feckless blob of festering lard. "
"\n 2. ’Surely in such an industrious kitchen, there must be a starter or two "
"ready to send along and sate His Abhorentness’s appetite?’"
"\n (enter a menu option): ";
ssUI >> choice; // cin >> choice;
if (choice == 1) { A100(); }
if (choice == 2) { A167(); }
}
void A100()
{
int choice = 0;
INTIM = true;
ssUI >> choice; // cin >> choice;
cout << "\n\n A100() choice:" << choice
<< " INTIM: " << INTIM << endl;
}
void A167()
{
int choice = 0;
INTIM = false;
ssUI >> choice; // cin >> choice;
cout << "\n\n A167() choice:" << choice
<< " INTIM: " << INTIM << endl;
}
// other action-functions go here
}; // class CreateYourOwnAdventureStory_t
typedef CreateYourOwnAdventureStory_t CreateYOAS_t;
} // namespace AS
int main(int argc, char* argv[]){return AS::CreateYOAS_t()(argc,argv);}
Notes:
This example grabs the command line parameters and appends them to a string stream. The result is use-able in a fashion much like your cin statements.
Did you notice you (probably) will not need forward declarations for your functions? The compiler has to scan a lot of the class declaration to decide various issues, and thus can figure out that A100 (and A167) are actually with-in the scope of AS::CreateYOAS_t::. The functions can still be moved into a cpp file, so you can still take advantage of separate compilation. (and maybe save some effort compiling smaller files, and only the changed files.)
Did you notice that the functions accessing INTIM simply use the bool, without needing any 'this->' to de-reference?
Main invokes a simple Functor. Nothing else. Main invokes operator(). Simple, minimal. The ctor and dtor are currently default. If you need to use the ctor to initialize results or other intermediate info, I would simply add it near the operator() implementation.
PS: You mentioned using bools to return results. You might as, an alternative, consider using a stringstream ... a single stream with text ... use like a log for capturing the ongoing game, or for a single simple overall report to the user.
Good luck.
I've looked everywhere, but I cannot find a solution to exactly why this happens in my situation.
I'm making a simple string function that asks for a string, and prints out the length.
However, I get an "Invalid Null Pointer" assertion error when I run the compiled version. I have had no errors when compiling, but the error comes up when I run it.
This is the function causing the problem:
string getString()
{
string wordInput;
cout << "Enter a word that has AT LEAST four (4) letters! ";
getline(cin, wordInput);
while (wordInput.length() <= 3)
{
cout << "Enter a word that has AT LEAST four (4) letters! ";
getline(cin, wordInput);
}
return 0;
}
The while loop isn't a problem. I commented it out and I still got the same error. How is initializing word input, cout, and getline giving me the error?
Here is my whole code so far (not finished). I tried running the string by itself too, the getKeyLetter function isn't a problem.
#include <iostream>
#include <string>
#include <cassert>
using namespace std;
char getKeyLetter()
{
char keyLetter;
string convertFromString;
cout << "Enter a SINGLE character! ";
getline(cin, convertFromString);
while (convertFromString.length() > 1)
{
cout << "Enter a SINGLE character! ";
getline(cin, convertFromString);
}
assert(convertFromString.size() == 1);
keyLetter = convertFromString[0];
return 0;
}
string getString()
{
string wordInput;
cout << "Enter a word that has AT LEAST four (4) letters! ";
getline(cin, wordInput);
while (wordInput.length() <= 3)
{
cout << "Enter a word that has AT LEAST four (4) letters! ";
getline(cin, wordInput);
}
return 0;
}
int main()
{
getKeyLetter();
getString();
return 0;
}
First, in your GetKeyChar() function, writing:
char ch;
cout << "Enter a single character: ";
cin >> ch;
will give you the first character the person types into the command prompt. So, typing "check" will have ch = c.
Second, as eran said, at the end of your functions, you have
return 0;
Unless you want both functions to return a char and string respectively, make them void GetKeyLetter() and void GetString(). Or, if you do want to return something, have them return ch (from my example) and return wordInput.
Only int main(), per standard, needs return 0, to show you that it exited correctly. the variable type you put in front of your functions is what variable you plan on returning. 0 is an int, so that's what it returns based on convention. As was pointed out, a return is not necessary in main. If you want your functions to return values, do this in your main.
string str;
char ch;
ch = GetKeyLetter();
str = GetString();
return 0;
And have your functions return the char and string value you want them to.
I already searched, and couldn't find anything exactly like this one. Although there do seem to be similarities. If a mod or admin thinks this is a duplicate topic, please let me know which one and ask me how I think it might be different before you delete it.
If I'm returning an int value in a function, how do I return a second one indirectly with a pointer or reference parameter? I have a practice problem I need to do that is asking for this:
Write a function that takes two input arguments and provides two
separate results to the caller, one that is the result of multiplying
the two arguments, the other the result of adding them. Since you can
directly return only one value from a function, you'll need the second
value to be returned through a pointer or reference parameter.
And I also need to return a string pointer through a function.
Write a function that prompts the user to enter his or her first name and last name, as two separate values. This function should
return both values to the caller via additional pointer (or reference)
parameters that are passed to the function. Try doing this first with
pointers and then with references.
I already did this one with a reference to a pointer, but I'm having trouble doing it with pointers.
#include <iostream>
using namespace std;
string userName(string user_first_name, string user_last_name);
int main()
{
string user_first_name;
string user_last_name;
cout << "Program for taking in user's full name\n";
cout << userName(user_first_name, user_last_name);
}
string userName(string user_first_name, string user_last_name)
{
cout << "Please provide your first name: ";
cin >> user_first_name;
cout << "Please provide your last name: ";
cin >> user_last_name;
string full_name = user_first_name + " " + user_last_name;
return full_name;
}
Whenever I try to use those string variables as pointers, I get an error saying I can't convert a string to a string*, or I get an error saying I can't convert a string* to a string**.
As for the other one, this is the code I have:
#include <iostream>
using namespace std;
int* pointerMath();
int main()
{
cout << "Let's do some math!\n";
pointerMath();
}
int* pointerMath()
{
int value1;
int value2;
cout << "Provide the first number: ";
cin >> value1;
cout << "Provide the second number: ";
cin >> value2;
int *multiplication_result = value1 * value2;
int *addition_result = value1 + value2;
cout << "The numbers added together are: " << *addition_result << '\n';
cout << "The numbers multiplied by each other are: " << *multiplication_result << '\n';
return multiplication_result;
}
Whenever I run this, it always crashes right after getting both input values, and I get an error code 255.
Edit:
I also have to further modify the string name program, per this question's specification:
Modify the program you wrote for exercise 1 so that instead of always prompting the user for a last name, it does so only if the
caller passes in a NULL pointer for the last name.
How do I do this?
To do it with pointers, you have to introduce pointers, i.e.
Change this:
string userName(string user_first_name, string user_last_name);
to that (note string* for pointer parameters):
string userName(string* user_first_name, string* user_last_name);
Moreover, when you sue cin you have to dereference the pointer, using the (*pointer) syntax, e.g.:
string userName(string* user_first_name, string* user_last_name)
{
cout << "Please provide your first name: ";
cin >> (*user_first_name); // <-- dereference pointer
cout << "Please provide your last name: ";
cin >> (*user_last_name); // <-- dereference pointer
string full_name = (*user_first_name) + " " + (*user_last_name);
return full_name;
}
And in main(), you should pass the address of the variables using the address-of & operator:
int main()
{
string user_first_name;
string user_last_name;
cout << "Program for taking in user's full name\n";
// Use & to get address of (pointers) to first and last name
cout << userName(&user_first_name, &user_last_name);
}
Now that I showed you some sample code, you should be able to use a similar coding pattern for the other case.
Since you can directly return only one value from a function, you'll
need the second value to be returned through a pointer or reference
parameter.
This is extremely misleading. It's true that you can technically only return one value, but nothing stops you from returning a custom type that internally holds two values. This approach is usually superior to references or out pointers and should be the default choice:
struct Value
{
int x;
int y;
};
Value GetValue()
{
return { 1, 2 };
}
I already did this one with a reference to a pointer, but I'm having
trouble doing it with pointers.
You should not do it with a pointer in the first place. Not with a pointer directly and not with a reference to a pointer. A reference would suffice.
string userName(string user_first_name, string user_last_name);
These string parameters are copies. The function will operate on copies of the arguments, and the original strings on the outside will be left untouched.
Whenever I try to use those string variables as pointers, I get an
error saying I can't convert a string to a string*, or I get an error
saying I can't convert a string* to a string**.
Because a pointer to something is not implicitly convertible to something, and vice versa (this is also true if "something" is itself a pointer).
Just use references:
string userName(string& user_first_name, string& user_last_name);
int *multiplication_result = value1 * value2;
The result of value1 * value2 is an int. You cannot just take an int and use it as if it was a pointer. Your code should not even compile but fail with an error message like error C2440: 'initializing' : cannot convert from 'int' to 'int *', unless you are using an ancient compiler or invoke it with the wrong settings.
For the first problem, you need use & to pass your string value. I think it's better to understand than using passing pointer.
also you can pass the pointer like this:
#include
using namespace std;
string *userName(string user_first_name, string user_last_name);
int main()
{
string user_first_name;
string user_last_name;
cout << "Program for taking in user's full name\n";
cout << *(userName(user_first_name, user_last_name));
}
string* userName(string user_first_name, string user_last_name)
{
cout << "Please provide your first name: ";
cin >> user_first_name;
cout << "Please provide your last name: ";
cin >> user_last_name;
string *full_name = new string;
*full_name = user_first_name + " " + user_last_name;
return full_name;
}
int *multiplication_result is a pointer, it need to be bind with a value. after that you can make it point to a int value.
you can pass the value by this way:
#include <iostream>
using namespace std;
int* pointerMath();
int main()
{
cout << "Let's do some math!\n";
cout<<*(pointerMath()) <<endl;
}
int* pointerMath()
{
int value1;
int value2;
cout << "Provide the first number: ";
cin >> value1;
cout << "Provide the second number: ";
cin >> value2;
int *multiplication_result = new int;
*multiplication_result = value1 * value2;
int addition_result = value1 + value2;
cout << "The numbers added together are: " << addition_result << '\n';
cout << "The numbers multiplied by each other are: " << *multiplication_result << '\n';
return multiplication_result;
}
Write a function that takes two input arguments and provides two
separate results to the caller, one that is the result of multiplying
the two arguments, the other the result of adding them. Since you can
directly return only one value from a function, you'll need the second
value to be returned through a pointer or reference parameter.
int multiplyAndAdd(int a, int b, int& sum){
sum = a+b;
return a*b;
}
calling this is like this :
int sum=0;
int multiply = multiplyAndAdd(2,3,sum);
I am in favor of using a reference instead of a pointer. In the latter case it would be like this :
int multiplyAndAdd(int a, int b, int* sum){
*sum = a+b; //--> probably a null check is needed
return a*b;
}
and then calling like this :
int sum=0;
int multiply = multiplyAndAdd(2,3,&sum);
the string exercise is almost the same:
with references:
void returnstrings(string& s1, string& s2){
//whatever here you just assign s1 and s2
}
calling it :
string firstName;
string lastName;
returnstrings(firstName,lastName);
with pointers :
void returnstrings(string* s1, string* s2){
//whatever here you just assign *s1 and *s2
}
calling it :
string firstName;
string lastName;
returnstrings(&firstName,&lastName);
I have an object that works with arrays of smaller objects. I am now creating a larger interface object that needs to collect input data and send it into a parameter of const* char. What code would I use to capture keyboard input of something like a 20 character title and be able to pass it into this parameter?
In Short:
How do you get keyboard input of a name and pass it into this:
void Insert(const char* t)
I am restricted to using the iostream, iomanip, cstring, cctype libraries
EDIT: You asked for the whole code, so here it is. All my input is having problems...
#include <iostream>
#include "store.h"
using namespace std;
void ShowMenu()
// Display the main program menu.
{
cout << "\n\t\t*** BOOKSTORE MENU ***";
cout << "\n\tA \tAdd a Book to Inventory";
cout << "\n\tF \tFind a book from Inventory";
cout << "\n\tS \tSell a book";
cout << "\n\tD \tDisplay the inventory list";
cout << "\n\tG \tGenre summary";
cout << "\n\tO \tSort inventory list";
cout << "\n\tM \tShow this Menu";
cout << "\n\tX \teXit Program";
}
char GetAChar(const char* promptString)
// Prompt the user and get a single character,
// discarding the Return character.
// Used in GetCommand.
{
char response;// the char to be returned
cout << promptString;// Prompt the user
cin >> response;// Get a char,
response = toupper(response);// and convert it to uppercase
cin.get();// Discard newline char from input.
return response;
}
char Legal(char c)
// Determine if a particular character, c, corresponds
// to a legal menu command. Returns 1 if legal, 0 if not.
// Used in GetCommand.
{
return((c == 'A') || (c == 'F') || (c == 'S') ||
(c == 'D') || (c == 'G') || (c == 'O') ||
(c == 'M') || (c == 'X'));
}
char GetCommand()
// Prompts the user for a menu command until a legal
// command character is entered. Return the command character.
// Calls GetAChar, Legal, ShowMenu.
{
char cmd = GetAChar("\n\n>");// Get a command character.
while (!Legal(cmd))// As long as it's not a legal command,
{// display menu and try again.
cout << "\nIllegal command, please try again . . .";
ShowMenu();
cmd = GetAChar("\n\n>");
}
return cmd;
}
void Add(Store s)
{
char* aTitle;
char aAuthor[21];
Genre aGenre = FICTION;
double aPrice = 10.00;
cout << "Enter title: ";
cin >> aTitle;
cout << "Enter author: ";
cin.getline(aAuthor, 20);
cout << aTitle << " " << "aAuthor\n";
s.Insert(aTitle, aAuthor, aGenre, aPrice);
}
void Find()
{
}
void Sell()
{
}
void Genre()
{
}
void Sort()
{
}
void Intro(Store s)
{
double amount;
cout << "*** Welcome to Bookstore Inventory Manager ***\n"
<< "Please input the starting money in the cash register: ";
cin >> amount;
s.SetCashRegister(amount);
}
int main()
{
Store mainStore;// Create and initialize a Store.
Intro(mainStore);//Display intro & set Cash Regsiter
ShowMenu();// Display the menu.
mainStore.Insert("A Clockwork Orange", "Anthony Burgess", SCIFI, 30.25);
mainStore.Insert("X-Factor", "Anthony Burgess", SCIFI, 30.25);
char command;// menu command entered by user
do
{
command = GetCommand();// Retrieve a command.
switch (command)
{
case 'A': Add(mainStore); break;
case 'F': Find(); break;
case 'S': Sell(); break;
case 'D': mainStore.DisplayStore(); break;
case 'G': Genre(); break;
case 'O': Sort(); break;
case 'M': ShowMenu(); break;
case 'X': break;
}
} while ((command != 'X'));
return 0;
}
Consider std::istream::getline(char *, std::streamsize).
But, be sure that you pass it a valid pointer to allocated memory! That is, use it like this:
char buffer[80];
std::cin.getline(buffer, sizeof buffer);
and not like this:
char *p;
std::cin.getline(p, 80); // Undefined behavior: using uninitialized variable
EDIT. You have this code:
char* aTitle;
...
cout << "Enter title: ";
cin >> aTitle;
This is a bug. You create a pointer called aTitle, and do not initialize it. That pointer now points at memory you do not own.
The >> operator writes data to the location pointed to by your pointer. Since your pointer does not point at anything you control, the >> will invoke undefined behavior when its writes through your pointer.
Lesson: make sure that you provide valid values for all of your pointers. (Broader lesson: never use pointers. (Okay, almost never.))
Immediately following, you have this code:
cout << "Enter author: ";
cin.getline(aAuthor, 20);
But, consider the input state. Your user just typed "Jaws", followed by ENTER. Your cin>>aTitle read "Jaws", and left "\n" in the input stream.
This istream::getline call reads up to the first newline, which is the newline that follows "Jaws"(!) and not the newline that follows "Peter Benchley"! So now, you have "Jaws" in aTitle (assuming you fix your previous bug), nothing in aAuthor, and "Peter Benchley\n" still in the input stream.
Lesson: Don't mix formatted input with getline. Use either one or the other consistently throughout your program.
Use getline to take a std::string input. And pass it to the function converting to a c-style string using member function c_str()
Use std::string and pass by reference.
You need a pointer to mutable data:
char * t; // Pointer to mutable data
OR
char* const t; // Constant pointer to mutable character.
Because of the weird restrictions (iostream is allowed, but not std::string), you might have a hard time finding your answer in a C++ text book. So here's some help:
char buffer[81];
std::cin >> buffer; // input some text (80 characters or less)
// A mutable character array can be implicitly converted
// to a const char* without casting.
Insert(buffer);