How to call toString on iterator c++ - 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);

Related

Problem in my C++ function with vector size not increasing

In the following code, I am attempting to add elements to a vector of strings, ints, and doubles but when I output the vector's size, it never moves past 1. This leads me to believe it's not adding elements, but instead changing the first element?
// Need to show this for the code I'm having issues with
struct Store_Info{ // Stores all info for a given item
string store_name;
string location;
// vector<string> = item | vector<int> = stock || vector<double> = price
pair<pair<vector<string>, vector<int>>, vector<double>> item_stock_price;
Store_Info() = default;
Store_Info(string, string);
string how_many(int);
};
void stock_info(vector<Store_Info> &stores, int n_stores){ // This is the code I need help with
for (int i(0); i<n_stores; i++){
string name; string loc;
int counter(0);
bool active(true);
while(active){
string line;
std::getline (cin,line);
if (line == "")
active = false;
else if (counter == 0){
name = line;
counter++;
}
else if (counter == 1){
loc = line;
stores[i] = Store_Info(name, loc);
counter ++;
}
else{
regex reg{R"((\w+),(\d+),\W(\d+.\d+))"}; // From professor's piazza post
std::smatch m;
std::regex_match(line, m, reg);
Store_Info current_store = stores[i];
pair itemStock = std::get<0>(current_store.item_stock_price);
std::get<0>(itemStock).push_back(m[1].str()); // Defines item name
std::get<1>(itemStock).push_back(std::stoi(m[2].str())); // Defines amount in stock
std::get<1>(current_store.item_stock_price).push_back(std::stod(m[3].str())); // Defines price
//cout << std::get<1>(current_store.item_stock_price).capacity();
}
}
}
}
Sorry if this is formatted poorly, this is my first post.
Any help is appreciated, thank you!
edit: Might be helpful to know what's being inputted..
Using standard input, the function reads in this:
(int) Stores:
(Name of a store)
(A location)
(item name),(quantity),$(price)
Ex.)
2 Stores:
Local Grocery
California
Apples,2,$1.20
Mall
Michigan
Pizza,3,$4.00
Cake,1,$10.45
Please consider to change you code to something like this.
Using nested pair's is way too confusing. Then at least use std::tuple.
Also you need to use reference to the struct and not its copy !
struct Item {
string name; // Defines item name
int amount; // Defines amount in stock
double price; // Defines price
}
struct Store_Info { // Stores all info for a given item
string store_name;
string location;
// vector<string> = item | vector<int> = stock | vector<double> = price
vector<Item> items;
Store_Info() = default;
Store_Info(string, string);
string how_many(int);
};
void stock_info(vector<Store_Info> &stores, int n_stores){ // This is the code I need help with
for (int i(0); i<n_stores; i++){
string name; string loc;
int counter(0);
bool active(true);
while(active){
string line;
std::getline (cin,line);
if (line == "")
active = false;
else if (counter == 0){
name = line;
counter++;
}
else if (counter == 1){
loc = line;
stores[i] = Store_Info(name, loc);
counter ++;
}
else{
regex reg{R"((\w+),(\d+),\W(\d+.\d+))"}; // From professor's piazza post
std::smatch m;
std::regex_match(line, m, reg);
Store_Info &current_store = stores[i]; // need to be reference and not the copy !
// item name | amount | price
current_store.items.emplace_back(m[1].str(), std::stoi(m[2].str()), std::stod(m[3].str()));
}
}
}
}
Not sure about other bugs or problems because this code is not run-able.

reverse words in a sentence using istringstream and istream_iterator

Trying to solve the problem using C++ constructs. Reference to each word in the sentence is taken and reversed. But the changes are not seen in the original sentence.
class Solution {
public:
string reverseWords(string s) {
istringstream ss(s);
for(auto w = istream_iterator<string>(ss); w != istream_iterator<string>(); w++)
{
/* changes of the below 2 lines are not reflected in the main sentence*/
string &str = const_cast<string&>(*w);
reverse(str.begin(),str.end());
}
reverse(s.begin(),s.end());
return s;
}
};
I don't think it is possible to use streams without copying the word as the stream would always extract the word into a separate string. In your attempt, you are also modifying such a copy, that's why you get the original string returned. I would just use iterators (this is to be taken as pseudo-code, may not compile):
auto last = s.begin();
auto cur = s.begin();
while (cur != s.end()) {
if (!isalpha(*(cur++))) {
reverse(last, cur);
last = cur;
}
}
reverse(last, cur);
return s;

String pointer manipulation

I have this assignment at school. A string pointer is passed to the function and returns 2 const strings to a different functions.
The 2 new strings divide the original string into 2 parts based on a space.
Example:
Input
str = 05/12 Hello
Desired output
key = 05/12
satData = Hello
This is the code I wrote but its giving me errors. Please help
void RBapp::processInsert(string &str)
{
string *key = new string();
string *satData = new string();
int i = 0, j =0;
while(str[i]!=" ")
{
key[j] = str[i];
i++;
j++;
}
j = 0;
while(str[i]!='\0')
{
satData[j] = str[i];
i++;
j++;
}
myRBT.rbInsert(key, satData);
}
Using stringstream
void RBapp::processInsert(const std::string &str)
{
std::stringstream ss(str);
std::string key;
std::string satData;
ss >> key;
ss >> satData;
myRBT.rbInsert(key, satData);
}
Your program is subject to undefined behavior since you are accessing memory that is not valid.
When you use:
string *key = new string();
string *satData = new string();
You have two pointers that point to empty strings.
key[j] = str[i];
is wrong if j > 0 since that points to invalid memory.
Based on the description of what you are trying to do, what you need is something along the lines of:
void RBapp::processInsert(string &str)
{
// There is no need to use new string.
// Just use two string objects.
string key;
string satData;
int i = 0;
while(str[i]!=" ")
{
// Add the character to key
key.push_back(str[i]);
i++;
}
// Increment i here if you want the space to be excluded from
// satData. If you want to include the space character in satData,
// then, there is no need to increment i
++i;
while(str[i]!='\0')
{
// Add the character to satData
satData.push_back(str[i]);
i++;
}
myRBT.rbInsert(key, satData);
}
You say you receive a string pointer - what I see is you receive a string. In C++ you would try to avoid hand-written loops as much as possible - std::string has a lot of stuff you need.
void process(const string &str) {
auto firstSpace = str.find_first_of(' ');
auto key = str.substr(0, firstSpace);
auto value = str.substr(firstSpace, string::npos);
myRBT.rbInsert(key, value);
}

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!

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

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().