implement vector of maps in C++ - c++

I am trying to write a code to make a vector of maps to store parts of string by splitting it. This code is giving long compilation errors, i am not able to understand what is the problem. Problem is with initialization way
#include <bits/stdc++.h>
using namespace std;
vector<string> split(string phrase, string delimiter){
vector<string> list;
string s = phrase;
size_t pos = 0;
string token;
while ((pos = s.find(delimiter)) != string::npos) {
token = s.substr(0, pos);
list.push_back(token);
s.erase(0, pos + delimiter.length());
}
list.push_back(s);
return list;
}
int main() {
string line = "tunilib;sebesta;prog lang;14";
vector<string> splitstring = split(line, ";");
vector< map<string,string,string,string> > elements;
map<string,string,string,string> element;
element["library"] = splitstring[0];
element["author"] = splitstring[1];
element["title"] = splitstring[2];
element["reservation"] = splitstring[3];
elements.push_back(element);
for(auto i:splitstring) cout<<i<<" ";
cout<<"success";
return 0;
}

Error was in declaration, simply change,
map<string,string,string,string>
to
map<string,string>
as i wanted to create a list of key value pairs.
#user4581301 thanks for comment

Related

C++ reading string using more delimiters

I'm quite new to c++. My problem is that I have a string that can be any length and ends with \n. For example:
const string s = "Daniel,20;Michael,99\n"
(It's always "name,age;name,age;name,age.............\n")
and I want to separate name and age and put it into two vectors so it can be stored. But I dont know how to manage string with more separators. So the example would be separated like this:
Vector name contains {Daniel,Michael}
Vector age contains {20,99}
You can use stringstream and getline for this purpose, but since you have a very specific format, simple std::string::find is likely to fix your issue. Here is a simple example:
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstddef>
int main() {
std::string const s = "Daniel,20;Michael,99;Terry,42;Jack,34";
std::vector<std::string> names;
std::vector<int> ages;
std::size_t beg = 0;
std::size_t end = 0;
while ((end = s.find(',', end)) != s.npos) {
names.emplace_back(s, beg, end - beg);
char* pend;
ages.push_back(std::strtol(s.c_str() + end + 1, &pend, 10));
end = beg = pend - s.c_str() + 1;
}
for (auto&& n : names) std::puts(n.c_str());
for (auto&& a : ages) std::printf("%d\n", a);
}
Sorry my C++ skills have faded, but this is what I would do :-
vector <string> names;
vector <string> ages;
string inputString = "Daniel,20;Michael,99;Terry,42;Jack,34";
string word = "";
for(int i = 0; i<inputString.length(); i++)
{
if(inputString[i] == ';')
{
ages.push_back(word);
word = "";
}
else if (inputString[i] == ',')
{
names.push_back(word);
word = "";
}
else
{
word = word + inputString[i];
}
}
ages.push_back(word);

Parsing line in a text file into vectors

#include <string>
#include <iostream>
#include <vector>
#include <sstream>
#include <fstream>
using namespace std;
vector <string> tokenizeString(string filename, string delimiter);
int main() {
vector<string> tokens = tokenizeString("cityLocation.txt", "-");
for (int i = 0; i < tokens.size(); i++) {
cout << tokens[i];
}
return 0;
}
vector <string> tokenizeString (string filename, string delimiter) {
size_t pos = 0;
vector<string>tokens;
string token;
ifstream cityText(filename);
string line;
while (getline(cityText, line)) {
while ((pos = line.find(delimiter)) != string::npos) {
token = line.substr(0,pos);
tokens.push_back (token);
line.erase(0, pos + delimiter.length());
}
}
return (tokens);
}
So this is my code, and my text file data are
[1,1]-3-Big_City
[1,2]-3-Big_City
[1,3]-3-Big_City
[2,1]-3-Big_City
[2,2]-3-Big_City
[2,3]-3-Big_City
[2,7]-2-Mid_City
[2,8]-2-Mid_City
[3,1]-3-Big_City
My code is skipping all the Big_city and Mid_city.
It prints out only the first and second column data.
My delimiter is suppose to be '-'.
I haven't tried saving the data into vectors but would like some recommendation on how to do that
That is because you need another run for the last field after the last delimiter. You can accomplish this by using a post-test loop that will excecute one more time when pos==string::npos, therefore adding line.substr(pos,string::npos); as a token which is defined to be the substring from position pos to the end of the string.
vector <string> tokenizeString (string filename, string delimiter) {
vector<string>tokens;
string token;
ifstream cityText(filename);
string line;
while (cityText >> line) {
size_t pos = 0, lastpos=0;
do {
pos = line.find(delimiter, lastpos);
token = line.substr(lastpos,pos-lastpos);
tokens.push_back (token);
lastpos=pos+1;
} while (pos != string::npos);
}
return (tokens);
}

Store .txt file into a char* 2d Vector C++

I know there are lots of questions with similar titles here, but no one seems to work for me.
I have this kind of txt file:
tree pine
color blue
food pizza
and I want to store the items in a char* 2d vector, such as
vector<vector<char*>> data;
..
..
data[0][0] = tree
data[0][1] = pine
data[1][1] = blue
ecc
This is the code:
// parse configuration file
bool Configuration::fileParser(char* filename)
{
vector<vector<char*>> data;
fstream fin("data/setup.txt");
string line;
while (fin && getline(fin, line))
{
vector<char*> confLine;
char* word = NULL;
stringstream ss(line);
while (ss && ss >> word)
{
confLine.push_back(word);
}
data.push_back(confLine);
}
storeData(data);
return 0;
}
But when I run the code an exception is thrown.
Exception thrown: write access violation.
How can I solve this problem?
Thank you
You haven't allocated any memory into which the data can be written. You'd need something like char* word = new char[50];. But just use a std::string it is safer and easier.
Disclaimer: I do not have a compiler on hand to test the following code with files, but it should work.
Here is a reference I used: Parse (split) a string in C++ using string delimiter (standard C++)
Discription: Basically the following code parses the passed in file line by line then assigns the first word and second word into the vector. Notice that I used string(s) in the example because I didn't want to think about memory management.
#pragma once
#include <vector>
#include <fstream>
#include <string>
void Configuration::fileParser(string fileName)
{
vector<vector<string>> data;
ifstream configFile(fileName);
string line, token;
string delimiter = " ";
size_t pos;
if (configFile.is_open())
{
int n = 0;
while (getline(configFile, line))
{
if (!line || line == "")
break; //added as a safety measure
pos = 0;
if ((pos = line.find(delimiter)) != string::npos)
{
token = line.substr(0, pos);
data[n][0] = token; //add first word to vector
line.erase(0, pos + delimiter.length());
}
if ((pos = line.find(delimiter)) != string::npos)
{
token = line.substr(0, pos);
data[n][1] = token; //add second word to vector
line.erase(0, pos + delimiter.length());
}
n++;
}
}
storeData(data);
}

Program gets "Expression: string subscript out of range"

#include <iostream>
#include <string>
using namespace std;
string Latin(string words)
{
string strWord, strSentence = "";
int length = 0, index = 0;
while (words[index] != '\0')
{
if(words.find(' ', index) != -1)
{
length = words.find(' ', index);
length -= index;
strWord = words.substr(index,length);
strWord.insert(length, "ay");
strWord.insert(length, 1, words[index]);
strWord.erase(0,1);
index += length +1;
}
else
{
strWord = words.substr(index);
length = strWord.length();
strWord.insert(length, "ay");
strWord.insert(length,1,words[index]);
strWord.erase(0,1);
index = words.length();
}
strSentence += (strWord + " ");
}
return strSentence;
}
int main()
{
string str;
getline(cin,str);
str = Latin(str);
cout<<str<<endl;
return 0;
}
I get this error that says
I have no clue what to do. As I am new to this, this is a program that is suppose to ask for user input of a length of words and translate them into pig Latin. Any help would be greatly appreciated.
Unless I really wanted to make my own life difficult, I'd do this quite a bit differently. First, I'd use a std::stringstream to break the input string into words to process. Then, I'd use std::rotate to move the first character of the string to the end. Finally, I'd wrap that all in std::transform to manage applying the function to each word in succession.
std::string line;
std::getline(std::cin, line);
std::stringstream buffer(line);
std::stringstream result;
std::transform(std::istream_iterator<std::string>(buffer),
std::istream_iterator<std::string>(),
std::ostream_iterator<std::string>(result, " "),
[](std::string s) {
std::rotate(s.begin(), s.begin() + 1, s.end());
s += "ay";
return s;
});
Of course, this doesn't know the special rules for things like words that start with vowels or letter pairs like sh or ch, but it looks like that's outside the scope of the task at hand.
For more on std::rotate, I recommend watching some of Sean Parent's videos.

finding substring c++ [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
How to split a string?
Hi,
I have a string say "1,0,1", how can i get the substring separated by comma operator.
C++ doesn't have a built in function for doing exactly this. However, it can be implemented using either the std::string::find_first_of member function, or the non-member std::find.
Here's an example using the latter:
#include <string>
#include <vector>
#include <algorithm>
// given a string str, split it on every occurrence of the character delim
std::vector<std::string> tokenize(std::string str, char delim) {
// store the results in a vector of strings
std::vector<std::string> tokens;
std::string::iterator end = str.end();
std::string::iterator left = str.begin();
for (;;) {
// find the next occurrence of the delimiter
std::string::iterator right = std::find(left, end, delim);
// create a string from the end of last one up until the one we just foun
tokens.push_back(std::string(left, right));
// if we reached the end of the string, exit the loop
if (right == end) { break; }
// otherwise, start the next iteration just past the delimiter we just found
left = right + 1;
}
return tokens;
}
// test program
int main() {
std::string str = "foo, bar, baz";
std::string str2 = "foo, bar, baz,";
std::string str3 = "foo";
std::string str4 = "";
std::string str5 = ",";
std::vector<std::string> tokens = tokenize(str, ',');
std::vector<std::string> tokens2 = tokenize(str2, ',');
std::vector<std::string> tokens3 = tokenize(str3, ',');
std::vector<std::string> tokens4 = tokenize(str4, ',');
std::vector<std::string> tokens5 = tokenize(str5, ',');
}
Of course there are a lot of border cases to handle, and this implementation might not do exactly what you want, but it should give you a starting point.
another way of doing this is by using strtok. This is a old c way but it still applies to the problem.
using <vector>
using <string>
char* token, line[512];
std::string tokenStr;
std::string lineStr = "0, 1, 2";
std::vector<std::string> commaSplit;
strcpy ( line, lineStr.c_str());
//Remove spaces and find the first instance of ','
token = strtok( line, " ," );
while(token != NULL)
{
//Copy the token to a string
tokenStr = token;
//Add the token to the vector
commaSplit.push_back(token);
//Find next instance of the ,
token = strtok(NULL, " ,");
}
Search google for an algorithm to explode or tokenize your string. It's trivial.
You can also check out the documentation and use available tools : http://www.cplusplus.com/reference/string/string/
A simple implementation could be :
void tokenize(const string & text, vector<string> & tokens, char delim)
{
size_t length = text.size();
string token = "";
for(size_t i=0;i<length;i++)
{
if(text[i] != delim)
{
token += text[i];
}
else
{
if(token.size() > 0)
{
tokens.push_back(token);
}
token = "";
}
}
tokens.push_back(token);
}