How to search a std::string for a specific keyword - c++11

I am attempting to search a std::string for a keyword and return a boolean value, shown below;
std::string select_class()
{
std::string Class; //Defines the string 'Class'
std::string user_input; //Defines the string 'input
//Tells the user available commands
std::cout << "Class selection - Available classes =
\n\nArcher\nRouge\nWarrior\nMage\n\nCommands: \nset_class - selects your
class for this game";
std::cout << "\ninfo (class_name) - provides information regarding the
specific class";
while (true)
{
std::cin >> user_input;//Asks user to input a command
if (std::find(user_input,"set_class") == true)//Tests to see if
//specific keyword has been inputted
{
std::cout << "Please enter your class:";
}
}
}
I am looking to be able make my if statement inside my while loop return a boolean value (or have an equivalent outcome).
Apologies for the poor formatting as this is my first post.

Use string.find, like so:
std::cin >> user_input;//Asks user to input a command
if (user_input.find("set_class") != std::string::npos)//Tests to see if
//specific keyword has been inputted
{
std::cout << "Please enter your class:";
}

Related

C++ empty() and all_of() for checking string is empty or have only digit

I'm creating an IO console application and at the inputs i got an 'while' loop with two condition
empty() and all_of(), the function all_of() seems to work properly but when i press enter the empty() function not working and just let me to input the next thing in the 'struct'. I'm not sure am i doing it correct..There is the part of the code
cout << "Enter age: ";
getline(cin, age_str);
while(!age_str.empty() && !all_of(age_str.begin(), age_str.end(), ::isdigit)){
cout << "--Please Enter an integer-- " << endl;
cin.clear();
getline(cin, age_str);
}
stringstream(age_str) >> person_arr[n].age;
There are a link to the full code : enter link description here
The logic of the conditional of the while is incorrect.
What you need to do is:
If the line is empty, get the next line.
If the line is not empty and the line has anything other than digits, get the next line.
!age_str.empty() && !all_of(age_str.begin(), age_str.end(), ::isdigit) does not do that.
You need to use age_str.empty() || (!all_of(age_str.begin(), age_str.end(), ::isdigit))
I always recommend, when in doubt, simplify.
while ( !is_input_valid(age_str)) )
{
...
}
where
bool is_input_valid(std::string const& input)
{
if ( input.empty() )
{
return false;
}
return std::all_of(input.begin(), input.end(), ::isdigit);
}

C++ Struct attributes can change within function, but remain unchanged outside scope of function

I'm working on a self imposed challenge which involves implementing a linked list and an append function for it, which is giving me issues seemingly related to variable scope.
The append function loops through each link element until it reads a NULL value and then changes the data value associated with that link to the function input. The test outputs within the function seem to show it is working as intended, but when performing the same test outside the function, even after it is called gives a different output.
template <class T>
struct atom{
T data;
atom<T>* link = NULL;
};
template <class T>
void append_LL(atom<T> first, T input_data){
atom<T>* current_node = &first;
atom<T>* next_node = current_node->link;
int i = 0;
while (i < 4 && next_node != NULL) {
current_node = next_node;
next_node = next_node->link;
i ++;
}
current_node->data = input_data;
current_node->link = (atom<T>*)malloc(sizeof(atom<T>));
cout << "leaving node as: " << current_node->data << endl; //outputs 5
cout << "input nodes data: " << first.data << endl; //outputs 5
}
int main() {
int dd = 5;
atom<int> linked_list;
linked_list.data = 999;
append_LL(linked_list, dd);
cout << linked_list.data << endl; //outputs 999
}
Because you are not sending the same atom. You see the program is making a copy of the linked_list in the main function and sending that copy to the function.
If you want to modify the same linked_list then change
void append_LL(atom<T> first, T input_data){
to
void append_LL(atom<T> &first, T input_data){
That way you are sending the really atom not a copy of it.

Isalpha() function with while loop c++

I want to create a while loop that will allow me to input a mix of string numbers until I input string that contains all characters.
Also, I have a problem with output
int main() {
string name;
string temp;
cout << "Enter your name:";
cin >> name;
cout << endl;
for(auto a:name) {
if(isalpha(a)) {
temp=name;
} else {
while(!isalpha(a)) {
cout << "Enter your name without digit:";
cin >> name;
cout << endl;
}
}
}
cout << temp << endl;
}
for(auto a:name) {
This is a loop over the characters in name, as entered after the prompt "Enter your name:". The current character is assigned to a.
if(isalpha(a)) {
temp=name;
}
If the letter is alphabetic, assign temp = name (every time the current letter is alphabetic... this is not what you want!).
else {
...if the current character (a) is not alphabetic...
while(!isalpha(a)) {
...enter a second loop, which will loop until a is alphabetic...
cout << "Enter your name without digit:";
cin >> name;
cout << endl;
}
...but a is never again assigned to. Your loop does not terminate.
You should re-work your logic. As this looks like a self-study project, I will not write the reworked loop for you, as I think you will learn much more from trying to do it on your own.

Constructing an object as part of ostream output

For a class declaration as below:
class A{
public:
A(int);
~A()
private:
int a;
};
And a constructor definition as follows:
A::A(int i){
a = i;
cout << a << endl;
}
I would like to do something like this from main():
int main(){
int i;
//user input for value
//stored inside i
cout << "The value is " << A obj(i);
return 0;
}
I now get the following error for the above code in main():
error: 'A' does not refer to a value
What is the cause of this error?
You cannot declare obj and output it on the same line. If you want obj to remain available after printing, do this:
A obj(i);
cout << "The value is " << obj;
Otherwise, skip obj in favor of a temporary object:
cout << "The value is " << A(i);
You cannot have a declaration in the middle of another line.
What you can do is create an A on the fly with casting (A) i, or simply A(i), this will cast the int i into an A, and then send it to cout. The temporary A object is then directly discarded.
If you want to keep it, you have to declare a name for it, in its own statement.
You need to first output the message "The value is " on first code line. On the second code line you create the object obj of type A which will output the i.
int main()
{
int i;
cout << "The value is ";
A obj(i);
return 0;
}

Boost Spirit - Parser Capturing Unwanted Text

I have a simple struct
// in namespace client
struct UnaryExpression
{
std::string key;
SomeEnums::CompareType op;
};
SomeEnums::CompareType is an enum where I define a symbol table as such:
struct UnaryOps : bsq::symbols<char, SomeEnums::CompareType>
{
UnaryOps() : bsq::symbols<char, SomeEnums::CompareType>(std::string("UnaryOps"))
{
add("exists", SomeEnums::Exists)
("nexists", SomeEnums::NotExists);
}
};
I have two different ways I want to parse the struct, which I asked about in another thread and got to work (mostly).
My grammar looks as follows:
template<typename Iterator>
struct test_parser : bsq::grammar<Iterator, client::UnaryExpression(), bsq::ascii::space_type>
{
test_parser()
: test_parser::base_type(unaryExp, std::string("Test"))
{
using bsq::no_case;
key %= bsq::lexeme[bsq::alnum >> +(bsq::alnum | bsq::char_('.'))];
unaryExp %= unaryE | unaryF;
unaryE %= key >> no_case[unaryOps];
unaryF %= no_case[unaryOps] >> '(' >> key >> ')';
};
UnaryOps unaryOps;
bsq::rule<Iterator, std::string(), bsq::ascii::space_type> key;
bsq::rule<Iterator, client::UnaryExpression(), bsq::ascii::space_type> unaryExp;
bsq::rule<Iterator, client::UnaryExpression(), bsq::ascii::space_type> unaryE;
bsq::rule<Iterator, client::UnaryFunction(), bsq::ascii::space_type> unaryF;
};
And I'm parsing the code using the following logic:
bool r = phrase_parse(iter, end, parser, bsq::ascii::space, exp);
if (r && iter == end)
{
std::cout << "-------------------------\n";
std::cout << "Parsing succeeded\n";
std::cout << "key: " << exp.key << "\n";
std::cout << "op : " << exp.op << "\n";
std::cout << "-------------------------\n";
}
This all works fine if I do the input like foo exists and exp.key equals "foo" and exp.op equals the corresponding enum value (in this case 0). Something like foo1 nexists also works.
However, that second rule doesn't work like I expect. If I give it input of nexists(foo) then I get the following output:
-------------------------
Parsing succeeded
key: nexistsfoo
op : 1
-------------------------
It seems that the enum value is getting set appropriately but I can't figure out why the "nexsts" is getting prepended to the key string. Can someone please tell me how I can fix my rule so that the key would equal just 'foo' with the second rule?
I have posted a copy of the stripped down code that illustrates my problem here: http://pastebin.com/402M9iTS

Resources