STL map<String^, String^> thismap; why wont this work? - c++

I am attempting to write a simple login form. I want to store the list of login accounts in a STL map.
when retrieving text values from text boxes on the form. The boxes return "String^"
So what I have is:
map <String^, String^> NamePassList;
typedef pair<String^, String^> StringPair;
string line, usrName, password;
usrName = password = "";
ifstream ifs("login.in");
if (ifs.is_open()){
while (!ifs.eof()){
getline(ifs,line);
bool endofusername = false;
for (int i = 0; i < line.length(); i++){
if (line[i] == ' '){
endofusername = true;
}
if (!endofusername){
usrName += line[i];
}
else{
password += line[i];
}
}
String ^ temp1 = gcnew String(usrName.c_str());
String ^ temp2 = gcnew String(password.c_str());
NamePassList.insert(StringPair(temp1, temp2));
}
ifs.close();
}
String ^ UserName = txtUserName->Text;
String ^ Password = txtPassword->Text;
map<String^, String^>::iterator nameItor;
nameItor = NamePassList.find(UserName);
if (nameItor->first == UserName){
if (nameItor->second == Password){
MessageBox::Show("Sucsess!", "log", MessageBoxButtons::OK);
}
else
MessageBox::Show("Fail!", "log", MessageBoxButtons::OK);
}
else
{
MessageBox::Show("Fail!", "log", MessageBoxButtons::OK);
}
when compiled the error i get of from the "map class" and utility.
This seams like the best way to do it, but everything I try gives me a new error.
Any help would be great!! thanks all.

To possibly reduce some errors, try and simplify your code using std::string.
Given the option not to use the managed String type, I'd opt for std::string. Since you're using std::string already, try that type for NamePassList. Also, typedef the map. Then for inserts, use value_type.
typedef map<string, string> StringMap;
StringMap NamePassList;
to insert:
StringMap::value_type vt(usrName, password);
StringMap::_Pairib pair = NamePassList->insert(vt);
if (pair.second == false)
{
... problems... key already exists ....
}
And also for the search:
StringMap::iterator iter = NamePassList.find(UserName);
if (iter != NamePassList.end())
{
...found...
}
You don't want to "use" the iter until you know it's valid by testing against end().

Related

C++ separate string by selected commas

I was reading the following question Parsing a comma-delimited std::string on how to split a string by a comma (Someone gave me the link from my previous question) and one of the answers was:
stringstream ss( "1,1,1,1, or something else ,1,1,1,0" );
vector<string> result;
while( ss.good() )
{
string substr;
getline( ss, substr, ',' );
result.push_back( substr );
}
But what if my string was like the following, and I wanted to separate values only by the bold commas and ignoring what appears inside <>?
<a,b>,<c,d>,,<d,l>,
I want to get:
<a,b>
<c,d>
"" //Empty string
<d,l>
""
Given:<a,b>,,<c,d> It should return: <a,b> and "" and <c,d>
Given:<a,b>,<c,d> It should return:<a,b> and <c,d>
Given:<a,b>, It should return:<a,b> and ""
Given:<a,b>,,,<c,d> It should return:<a,b> and "" and "" and <c,d>
In other words, my program should behave just like the given solution above separated by , (Supposing there is no other , except the bold ones)
Here are some suggested solution and their problems:
Delete all bold commas: This will result in treating the following 2 inputs the same way while they shouldn't
<a,b>,<c,d>
<a,b>,,<c,d>
Replace all bold commas with some char and use the above algorithm: I can't select some char to replace the commas with since any value could appear in the rest of my string
Adding to #Carlos' answer, apart from regex (take a look at my comment); you can implement the substitution like the following (Here, I actually build a new string):
#include <algorithm>
#include <iostream>
#include <string>
int main() {
std::string str;
getline(std::cin,str);
std::string str_builder;
for (auto it = str.begin(); it != str.end(); it++) {
static bool flag = false;
if (*it == '<') {
flag = true;
}
else if (*it == '>') {
flag = false;
str_builder += *it;
}
if (flag) {
str_builder += *it;
}
}
}
Why not replace one set of commas with some known-to-not-clash character, then split it by the other commas, then reverse the replacement?
So replace the commas that are inside the <> with something, do the string split, replace again.
I think what you want is something like this:
vector<string> result;
string s = "<a,b>,,<c,d>"
int in_string = 0;
int latest_comma = 0;
for (int i = 0; i < s.size(); i++) {
if(s[i] == '<'){
result.push_back(s[i]);
in_string = 1;
latest_comma = 0;
}
else if(s[i] == '>'){
result.push_back(s[i]);
in_string = 0;
}
else if(!in_string && s[i] == ','){
if(latest_comma == 1)
result.push_back('\n');
else
latest_comma = 1;
}
else
result.push_back(s[i]);
}
Here is a possible code that scans a string one char at a time and splits it on commas (',') unless they are masked between brackets ('<' and '>').
Algo:
assume starting outside brackets
loop for each character:
if not a comma, or if inside brackets
store the character in the current item
if a < bracket: note that we are inside brackets
if a > bracket: note that we are outside brackets
else (an unmasked comma)
store the current item as a string into the resulting vector
clear the current item
store the last item into the resulting vector
Only 10 lines and my rubber duck agreed that it should work...
C++ implementation: I will use a vector to handle the current item because it is easier to build it one character at a time
std::vector<std::string> parse(const std::string& str) {
std::vector<std::string> result;
bool masked = false;
std::vector<char> current; // stores chars of the current item
for (const char c : str) {
if (masked || (c != ',')) {
current.push_back(c);
switch (c) {
case '<': masked = true; break;
case '>': masked = false;
}
}
else { // unmasked comma: store item and prepare next
current.push_back('\0'); // a terminating null for the vector data
result.push_back(std::string(&current[0]));
current.clear();
}
}
// do not forget the last item...
current.push_back('\0');
result.push_back(std::string(&current[0]));
return result;
}
I tested it with all your example strings and it gives the expected results.
Seems quite straight forward to me.
vector<string> customSplit(string s)
{
vector<string> results;
int level = 0;
std::stringstream ss;
for (char c : s)
{
switch (c)
{
case ',':
if (level == 0)
{
results.push_back(ss.str());
stringstream temp;
ss.swap(temp); // Clear ss for the new string.
}
else
{
ss << c;
}
break;
case '<':
level += 2;
case '>':
level -= 1;
default:
ss << c;
}
}
results.push_back(ss.str());
return results;
}

How to Find a Substring in a Particular String in a Set

How do you find the substring within a string in a set? For example, if I enter "Ville," then Louisville, Gainesville, and Muellerville are found? I have tried the following code
for(string const& search : cities)
{
if(find(search.begin(), search.end(), str) != std::string::npos)
{
string y = search;
employees.emplace_back(y);
,but I cannot figure out what is wrong with my syntax. This code is used in the following project (Project Code)
EDIT: My problem was simple and was fixed with using .begin() and .end() to iterate over the multimap name_address and finding each name with .substr. I also used a multimap instead of a set. I found the syntax easier and got it to work.
for(auto it = name_address.begin(); it != name_address.end(); ++it)
{
for(int i = 0; i < it->first.length(); ++i)
{
string tmpstr3 = it->first.substr(0 + i, str.length());
if(str == tmpstr3)
{
employees.insert(it->second);
break;
}
}
}
You are likely looking for
if (search.find(str) != std::string::npos)
The std::find call you have shouldn't compile.

How to call toString on iterator c++

hello I am new to coding so sorry for any misunderstandings I might have and how awful it looks. I have spent hours on this problem and cannot fix it. I have a vector of XMLItems and a constant toString method. When I try to call the toString with the iterator, it prints out nothing.
string XMLParser::toStringInput() const
{
string inputret = "";
for(std::vector<XMLItem>::const_iterator iter = theInput.begin(); iter != theInput.end(); ++iter)
{
inputret += (*iter).toString();
}
return inputret;
}
this returns nothing. Am I using the Iterator wrong? have I saved the string wrong when I created my vectors? Here's the toString in the XMLItem class
string XMLItem::toString() const
{
cout << this->theItem; //the item is a private string
return this->theItem;
}
here's where I created the vector just in case.
void XMLParser::readXML(Scanner& inStream)
{
string tmp = "";
string tag = "tag";
string data = "data";
XMLItem localxml = XMLItem();
while (inStream.hasNext())
{
string input = inStream.nextLine();
if(input.find("<") != std::string::npos)
{
XMLItem localxml = XMLItem(tag, input);
}
else
{
XMLItem localxml = XMLItem(data, input);
}
this->theInput.push_back(localxml);
}
}
XMLItem localxml = XMLItem();
while (inStream.hasNext()) {
string input = inStream.nextLine();
if(input.find("<") != std::string::npos) {
XMLItem localxml = XMLItem(tag, input);
} else {
XMLItem localxml = XMLItem(data, input);
}
this->theInput.push_back(localxml);
}
In both the block for the if and the one for the else case you have a new local (to that respective block) variable named localxml. They shadow the variable defined before the while loop, leaving it unchanged. So you basically could run
theInput.push_back(XMLItem());
inside that loop. So later, when you try to convert the elements of the vector to a string these "empty" elements get converted, probably leading to some empty strings being concatenated.
To fix that change the variable declarations to assignments by removing the type in front of the variable name:
localxml = XMLItem(tag, input);

c++ Find string when given only part of it inside an array like structure

It's in the form of a word so let's say I'm given the string "foo", and inside my array there are words like "food", "fool", "foo". All three of them should be printed out.
I haven't made a solid attempt at it yet cause I don't know how to wrap my head around it. Any idea?
Assuming you're using std::string, you could use string::find to see if one string is contained in another.
If you have a vector of strings, you might use that along with (for example) std::remove_copy_if to print out all the words from the vector that contain the chosen word:
#include <vector>
#include <string>
#include <algorithm>
#include <iterator>
#include <iostream>
int main() {
std::vector<std::string> words{"food", "fool", "foo", "tofoo", "lood", "flood"};
std::string word = "foo";
std::remove_copy_if(words.begin(), words.end(),
std::ostream_iterator<std::string>(std::cout, "\n"),
[&](std::string const &s) {
return s.find(word) == std::string::npos;
});
}
Result:
food
fool
foo
tofoo
You could do something simple, like iterating through each character in the string and checking it against the characters in the string you are trying to match using a separate function. If three characters in a row match the string you are searching for, add it to a vector or something and display them.
// Variables
bool charMatched = false;
vector<string> *stringVec = new vector<string>();
int index = 0;
int counter = 0;
string str = "Whatever you are trying to match";
for (char &c : strings[index]) // For each character in string
{
// Check for match
if (checkChar(c))
{
counter++;
charMatched = true;
if(counter == str.length())
stringVec->push_back(strings[index]);
}
else
{
index++;
counter = 0;
break;
}
}
bool checkChar(char c)
{
// Iterator to go through match string
static string::iterator it = str.begin();
if (c == *it)
{
if (it == str.end())
it = str.begin(); // Reset iterator
else
it++; // Increment iterator
return true;
}
else
{
if (it == str.end())
it = str.begin(); // Reset iterator
else
it++; // Increment iterator
return false;
}
}
You will have to tweak it a little to work with an array the way you want it to but something like this should do what you want. I did not run this through a compiler, I wrote it in Notepad so there may be small syntax errors. I hope this helps!

Invalid argument in c++ with Qt integration

I'm trying to write a Qt program in eclipse with C++, but I can't get past an error:
void MyTests::populateFirstList(){
Question* q = new Question;
q = this->ctr->getCurrent();
string s = this->ctr->toString(q);
}
Question is a type defined by me, and the line with toString(q) returns an error saying invalid arguments.
The funcion toString():
string Controller::toString(Question* q){
string s="";
string text = q->getText();
char c;
string::iterator it;
for (it= text.begin(); it != text.end(); it++)
{
if ((*it) == ' ') {
s+="\n";
}
else {
s+=it;
}
}
return s;
}
And just to be safe, the function getCurrent():
Question* Controller::getCurrent(){
return this->question;
}
I don't understand why this happens, because the function toString() should take a pointer to a Question, and q is one. I'm not even sure if the error is caused within these functions or somewhere deeper. Thanks for any help.
The error message is:
invalid arguments ' Candidates are:
std::basic_string < char,std::char_traits < char >, std::allocator < char > >
toString(Question *) '
Perform : Run QMake
then build
:)
Eventually your error comes from line
} else s+=it;
which eventually should be
} else s+=*it;
This will probably not solve the question, but i do not see any QT in here. Why not make use of QT-Objects when writing a Qt-App?
void MyTests::populateFirstList(){
Question* q = this->ctr->getCurrent();
QString s = this->ctr->toString(q);
}
QString Controller::toString(Question* q){
QString s;
QString text = q->getText();
s = text.replace(" ","\\n");
return s;
}
Question* Controller::getCurrent(){
return this->question;
}