How to put characters from file into two-dimensional vector? - c++

I've been trying to read in characters from an external file to be put into a two-dimensional vector with type char. The elements must be able to be compared to certain values in order to navigate a maze given in "MazeSample.txt".
While I haven't been able to get characters be put into the vector, I was able to read and output the characters with the get and cout functions.
The following code is an attempt to read the vectors in the correct format, but provides an error in the end:
//MazeSample.txt
SWWOW
OOOOW
WWWOW
WEOOW
//source.cpp
vector<vector<char>> maze;
ifstream mazeFile;
char token;
mazeFile.open("MazeSample.txt");
while (!mazeFile.eof()) {
mazeFile.get(token); //reads a single character, goes to next char after loop
for (int row = 0; row < maze.size(); row++) {
for (int column = 0; column < maze.at(row).size(); row++) {
maze.push_back(token);
}
}
//cout << token;
}
mazeFile.close();
For the maze provided in "MazeSample.txt", I'd expect the maze vector to read each character row by row, mimicking the format of the maze sample.
In the above code, am provided with an error at maze.push_back(token):
"no instance of overloaded function "std::vector<_Ty, _Alloc>::push_back..." matches the argument list"
"argument types are: (char)"
"object type is: std::vector>, std::allocator>>>"

You are inserting char to vector<vector<char>>. You should create a vector<char>, insert the values of type char into that and then insert the vector<char> to vector<vector<char>> maze;. Here is the corrected version of your program. It can be written in simple ways but for your understanding, I have made made corrections on top of your program.
vector<vector<char>> maze;
ifstream mazeFile;
string token;
mazeFile.open("MazeSample.txt");
while (!mazeFile.eof()) {
std::getline(mazeFile, token); //reads an entire line
//Copy characters in entire row to vector of char
vector<char> vecRow;
vecRow.assign(token.begin(), token.end());
//Push entire row of characters in a vector
maze.push_back(vecRow);
}
mazeFile.close();

The reason for your problem is that you try to put a char into a std::vector of std vector. So you put a wrong type.
maze.at(row).push_back(token); would do it, but then no row exists. You also need to push_back and empty row, before you can write data to it.
That is your syntax error.
Then, your code could be drastically shortened by using C++ algorithms. See:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <sstream>
std::istringstream testDataFile(
R"#(00000
11111
22222
33333
44444
)#");
// This is a proxy to read a complete line with the extractor operator
struct CompleteLineAsVectorOfChar {
// Overloaded Extractor Operator
friend std::istream& operator>>(std::istream& is, CompleteLineAsVectorOfChar& cl) {
std::string s{}; cl.completeLine.clear(); std::getline(is, s);
std::copy(s.begin(), s.end(), std::back_inserter(cl.completeLine));
return is; }
operator std::vector<char>() const { return completeLine; } // Type cast operator for expected value
std::vector<char> completeLine{};
};
int main()
{
// Read complete source file into maze, by simply defining the variable and using the range constructor
std::vector<std::vector<char>> maze { std::istream_iterator<CompleteLineAsVectorOfChar>(testDataFile), std::istream_iterator<CompleteLineAsVectorOfChar>() };
// Debug output: Copy all data to std::cout
std::for_each(maze.begin(), maze.end(), [](const std::vector<char> & l) {std::copy(l.begin(), l.end(), std::ostream_iterator<char>(std::cout, " ")); std::cout << '\n'; });
return 0;
}
But this is not the end. A std::vector<char>has no advantage over a string. You can work nearly have all the same functionality as a std::vector<char>. That is an improvement in design. The code would then look more like this:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <sstream>
std::istringstream testDataFile(
R"#(00000
11111
22222
33333
44444
)#");
int main()
{
// Read complete source file into maze, by simply defining the variable and using the range constructor
std::vector<std::string> maze{ std::istream_iterator<std::string>(testDataFile), std::istream_iterator<std::string>() };
// Debug output: Copy all data to std::cout
std::copy(maze.begin(), maze.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
return 0;
}
This is the by far more simpler solution. And it will serve your needs as well.
Please note: I used a istringstream for reading data, becuase I do not have a file on SO. But it is of cause the same as using any other stream (like an ifstream).
EDIT
The first solution read the source and put it directly into a std::vector<std::vector<char>>:
The 2nd solution put everything in the a std::vector<std::vector<std::string>> which is the most efficient solution. Also a std::string is nearly a std::vector<std::vector<char>>.
The OP requested a 3rd solution where we use the 2nd solution and then copy the std::vector<std::vector<std::string>> into a std::vector<std::vector<char>>.
Please see below
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <sstream>
std::istringstream testDataFile(
R"#(00000
11111
22222
33333
44444
)#");
int main()
{
// Read complete source file into maze, by simply defining the variable and using the range constructor
std::vector<std::string> maze{ std::istream_iterator<std::string>(testDataFile), std::istream_iterator<std::string>() };
// Debug output: Copy all data to std::cout
std::copy(maze.begin(), maze.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
// Edit: Copy into a std::vector<std::vector<char> -------------------------------------------------------
std::cout << "\n\n\nSolution 3:\n\n";
// Define the new variable with number of lines from the first maze
std::vector<std::vector<char>> mazeChar(maze.size());
// Copy the data from the original maze
std::transform(
maze.begin(), // Source
maze.end(),
mazeChar.begin(), // Destination
[](const std::string & s) {
std::vector<char>vc; // Copy columns
std::copy(s.begin(), s.end(), std::back_inserter(vc));
return vc;
}
);
// Debug Output
std::for_each(
mazeChar.begin(),
mazeChar.end(),
[](const std::vector<char> & vc) {
std::copy(vc.begin(), vc.end(), std::ostream_iterator<char>(std::cout));
std::cout << '\n';
}
);
return 0;
}
Hope this helps . . .

Related

How to get a word vector from a string?

I want to store words separated by spaces into single string elements in a vector.
The input is a string that may end or may not end in a symbol( comma, period, etc.)
All symbols will be separated by spaces too.
I created this function but it doesn't return me a vector of words.
vector<string> single_words(string sentence)
{
vector<string> word_vector;
string result_word;
for (size_t character = 0; character < sentence.size(); ++character)
{
if (sentence[character] == ' ' && result_word.size() != 0)
{
word_vector.push_back(result_word);
result_word = "";
}
else
result_word += character;
}
return word_vector;
}
What did I do wrong?
Your problem has already been resolved by answers and comments.
I would like to give you the additional information that such functionality is already existing in C++.
You could take advantage of the fact that the extractor operator extracts space separated tokens from a stream. Because a std::string is not a stream, we can put the string first into an std::istringstream and then extract from this stream vie the std:::istream_iterator.
We could life make even more easier.
Since roundabout 10 years we have a dedicated, special C++ functionality for splitting strings into tokens, explicitely designed for this purpose. The std::sregex_token_iterator. And because we have such a dedicated function, we should simply use it.
The idea behind it is the iterator concept. In C++ we have many containers and always iterators, to iterate over the similar elements in these containers. And a string, with similar elements (tokens), separated by a delimiter, can also be seen as such a container. And with the std::sregex:token_iterator, we can iterate over the elements/tokens/substrings of the string, splitting it up effectively.
This iterator is very powerfull and you can do really much much more fancy stuff with it. But that is too much for here. Important is that splitting up a string into tokens is a one-liner. For example a variable definition using a range constructor for iterating over the tokens.
See some examples below:
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
#include <regex>
const std::regex delimiter{ " " };
const std::regex reWord{ "(\\w+)" };
int main() {
// Some debug print function
auto print = [](const std::vector<std::string>& sv) -> void {
std::copy(sv.begin(), sv.end(), std::ostream_iterator<std::string>(std::cout, "\n")); std::cout << "\n"; };
// The test string
std::string test{ "word1 word2 word3 word4." };
//-----------------------------------------------------------------------------------------
// Solution 1: use istringstream and then extract from there
std::istringstream iss1(test);
// Define a vector (CTAD), use its range constructor and, the std::istream_iterator as iterator
std::vector words1(std::istream_iterator<std::string>(iss1), {});
print(words1); // Show debug output
//-----------------------------------------------------------------------------------------
// Solution 2: directly use dedicated function sregex_token iterator
std::vector<std::string> words2(std::sregex_token_iterator(test.begin(), test.end(), delimiter, -1), {});
print(words2); // Show debug output
//-----------------------------------------------------------------------------------------
// Solution 3: directly use dedicated function sregex_token iterator and look for words only
std::vector<std::string> words3(std::sregex_token_iterator(test.begin(), test.end(), reWord, 1), {});
print(words3); // Show debug output
//-----------------------------------------------------------------------------------------
// Solution 4: Use such iterator in an algorithm, to copy data to a vector
std::vector<std::string> words4{};
std::copy(std::sregex_token_iterator(test.begin(), test.end(), reWord, 1), {}, std::back_inserter(words4));
print(words4); // Show debug output
//-----------------------------------------------------------------------------------------
// Solution 5: Use such iterator in an algorithm for direct output
std::copy(std::sregex_token_iterator(test.begin(), test.end(), reWord, 1), {}, std::ostream_iterator<std::string>(std::cout,"\n"));
return 0;
}
You added the index instead of the character:
vector<string> single_words(string sentence)
{
vector<string> word_vector;
string result_word;
for (size_t i = 0; i < sentence.size(); ++i)
{
char character = sentence[i];
if (character == ' ' && result_word.size() != 0)
{
word_vector.push_back(result_word);
result_word = "";
}
else
result_word += character;
}
return word_vector;
}
Since your mistake was only due to the reason, that you named your iterator variable character even though it is actually not a character, but rather an iterator or index, I would like to suggest to use a ranged-base loop here, since it avoids this kind of confusion. The clean solution is obviously to do what #ArminMontigny said, but I assume you are prohibited to use stringstreams. The code would look like this:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
vector<string> single_words(string sentence)
{
vector<string> word_vector;
string result_word;
for (char& character: sentence) // Now `character` is actually a character.
{
if (character==' ' && result_word.size() != 0)
{
word_vector.push_back(result_word);
result_word = "";
}
else
result_word += character;
}
word_vector.push_back(result_word); // In your solution, you forgot to push the last word into the vector.
return word_vector;
}
int main() {
string sentence="Maybe try range based loops";
vector<string> result= single_words(sentence);
for(string& word: result)
cout<<word<<" ";
return 0;
}

C++ Writing a column of a CSV file into a vector

I have a CSV file with a bunch of columns, but I only need the information for the 11th column. How do I read through each line and skip to the 11th column in each line? I'm struggling to find clear information on how to read files in c++. This is what I have so far:
#include<iostream>
#include<fstream>
#include<vector>
#include <sstream>
#include <string>
std::string readStock(std::string fileName){
std::vector<std::string> ticker; //create vector
std::ifstream f(fileName, std::ios::in|std::ios:: binary|std::ios::ate);
std::string finalString = "";
if(f.is_open()){
std::string str;
std::getline(f,str); //skip the first row
while(std::getline(f,str)){ //read each line
std::istringstream s(str); //stringstream to parse csv
std::string val; //string to hold value
for(int i=1;i<=10;++i){ //skips everything until we get to the
column that we want
while(std::getline(s,val, ',')){
}
std::getline(s,val,',');
ticker.push_back(val);
}
f.close();
finalString = ticker.front();
}
}
else{
finalString="Could not open the file properly.";
}
return finalString;
}
int main(){
std::string st;
st=readStock("pr.csv");
std::cout<<st<<std::endl;
return 0;
}
There is a very simple solution for your problem.
You define a proxy class that reads one complete line, splits it into ALL tokens, using the dedicated functionality of the std::regex_token_iterator and then extracts the 11th element.
Using this proxy mechanism, you can use the std::istream_iterator to read the complete file, column 11, into a std::vector. For that we use the range constructor of the std::vector.
The result is a simple and short one-liner.
Please see:
#include <string>
#include <iostream>
#include <vector>
#include <fstream>
#include <regex>
#include <iterator>
#include <algorithm>
std::regex delimiter{ "," };
constexpr size_t targetColumn = 10U; // Target column is eleven
struct String11 { // Proxy for the input Iterator
// Overload extractor. Read a complete line
friend std::istream& operator>>(std::istream& is, String11& s11) {
// Read a complete line
if (std::string line{}; std::getline(is, line)) {
// Split it into tokens
std::vector token(std::sregex_token_iterator(line.begin(), line.end(), delimiter, -1), {});
// We only need one column
if (targetColumn < token.size()) {
// Get column 11
s11.result = token[targetColumn];
}
}
return is;
}
// Cast the type 'String11' to std::string
operator std::string() const { return result; }
// Temporary to hold the resulting string
std::string result{};
};
int main() {
// Open CSV fíle
if (std::ifstream csvFile{ "pr.csv" }; csvFile) {
// Read complete CSV file and get column 11 of each line
std::vector col11(std::istream_iterator<String11>(csvFile), {});
// Show output. Show all columns 11
std::copy(col11.begin(), col11.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
}
return 0;
}
EDIT:
For having output with doubles.
We just change one line in the cast operator in the proxy. That's all.
Even in main, there is no change in the read operatrion necessary. Through CTAD, the vector will be of type double.
Please see:
#include <string>
#include <iostream>
#include <vector>
#include <fstream>
#include <regex>
#include <iterator>
#include <algorithm>
std::regex delimiter{ "," };
constexpr size_t targetColumn = 10U; // Target column is eleven
struct String11 { // Proxy for the input Iterator
// Overload extractor. Read a complete line
friend std::istream& operator>>(std::istream& is, String11& s11) {
// Read a complete line
if (std::string line{}; std::getline(is, line)) {
// Split it into tokens
std::vector token(std::sregex_token_iterator(line.begin(), line.end(), delimiter, -1), {});
// We only need one column
if (targetColumn < token.size()) {
// Get column 11
s11.result = token[targetColumn];
}
}
return is;
}
// Cast the type 'String11' to double
operator double() const { return std::stod(result); }
// Temporary to hold the resulting string
std::string result{};
};
int main() {
// Open CSV fíle
if (std::ifstream csvFile{ "r:\\pr.csv" }; csvFile) {
// Read complete CSV file and get column 11 of each line
std::vector col11(std::istream_iterator<String11>(csvFile), {});
// Show output. Show all columns 11
std::copy(col11.begin(), col11.end(), std::ostream_iterator<double>(std::cout, "\n"));
}
return 0;
}
Output needs to adapted as well.

reading selected lines of file using mmap

I posted one question, which was related to faster reading of a file, by skipping specific lines but that does not seem to go well with standard c++ api's.
I researched more and got to know what memory mapped files could come handy for these kinds of cases. Details about memory mapped files are here.
All in all,
Suppose, the file(file.txt) is like this:
A quick brown fox
// Blah blah
// Blah blah
jumps over the little lazy dog
And then in code, opened file, Read that as memory mapped file and then iterate over the contents of the char* pointer, skipping the file pointers itself. Wanted to give it a try before reaching to an conclusion on it. Skeleton of my code looks like this:
struct stat filestat;
FILE *file = fopen("file.txt", "r");
if (-1 == fstat(fileno(file), &filestat)) {
std::cout << "FAILED with fstat" << std::endl;
return FALSE;
} else {
char* data = (char*)mmap(0, filestat.st_size, PROT_READ, MAP_PRIVATE, fileno(file), 0);
if (data == 0) {
std::cout << "FAILED " << std::endl;
return FALSE;
}
// Filter out 'data'
// for (unsigned int i = 0; i < filestat.st_size; ++i) {
// Do something here..
// }
munmap(data, filestat.st_size);
return TRUE;
}
In this case, I would want to capture lines which does not start with //. Since this file(file.txt) is already memory mapped, I could go over the data pointer and filter out the lines. Am I correct in doing so?
If so, what is the efficient way to parse the lines?
Reading selected lines from wherever and copy them to whatever can be done with the C++ algorithms.
You can use std::copy_if. This will copy data from any source to any destination, if the predicate is true.
I show you a simple example that copies data from a file and skips all lines starting with "//". The result will be put in a vector.
This is one statement with calling one function. So, a classical one liner.
For debugging purposes, I print the result to the console.
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <string>
#include <fstream>
using LineBasedTextFile = std::vector<std::string>;
class CompleteLine { // Proxy for the input Iterator
public:
// Overload extractor. Read a complete line
friend std::istream& operator>>(std::istream& is, CompleteLine& cl) { std::getline(is, cl.completeLine); return is; }
// Cast the type 'CompleteLine' to std::string
operator std::string() const { return completeLine; }
protected:
// Temporary to hold the read string
std::string completeLine{};
};
int main()
{
// Open the input file
std::ifstream inputFile("r:\\input.txt");
if (inputFile)
{
// This vector will hold all lines of the file
LineBasedTextFile lineBasedTextFile{};
// Read the file and copy all lines that fullfill the required condition, into the vector of lines
std::copy_if(std::istream_iterator<CompleteLine>(inputFile), std::istream_iterator<CompleteLine>(), std::back_inserter(lineBasedTextFile), [](const std::string & s) {return s.find("//") != 0; });
// Print vector of lines
std::copy(lineBasedTextFile.begin(), lineBasedTextFile.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
}
return 0;
}
I hope this helps

Creating 2D String Vector from text file

I'm having slight trouble creating a 2D Vector of String that's created by reading values from a text file. I initially thought I needed to use an array. however I've come to realise that a vector would be much more suited to what I'm trying to achieve.
Here's my code so far:
I've initialised the vector globally, but haven't given it the number of rows or columns because I want that to be determined when we read the file:
vector<vector<string>> data;
Test data in the file called "test" currently looks like this:
test1 test2 test3
blue1 blue2 blue3
frog1 frog2 frog3
I then have a function that opens the file and attempts to copy over the strings from text.txt to the vector.
void createVector()
{
ifstream myReadFile;
myReadFile.open("text.txt");
while (!myReadFile.eof()) {
for (int i = 0; i < 5; i++){
vector<string> tmpVec;
string tmpString;
for (int j = 0; j < 3; j++){
myReadFile >> tmpString;
tmpVec.push_back(tmpString);
}
data.push_back(tmpVec);
}
}
}
However, when I attempt to check the size of my vector in my main function, it returns the value '0'.
int main()
{
cout << data.size();
}
I think I just need a pair of fresh eyes to tell me where I'm going wrong. I feel like the issues lies within the createVector function, although I'm not 100% sure.
Thank you!
You should use std::getline to get the line of data first, then extract each string from the line and add to your vector. This avoids the while -- eof() issue that was pointed out in the comments.
Here is an example:
#include <string>
#include <iostream>
#include <vector>
#include <sstream>
typedef std::vector<std::string> StringArray;
std::vector<StringArray> data;
void createVector()
{
//...
std::string line, tempStr;
while (std::getline(myReadFile, line))
{
// add empty vector
data.push_back(StringArray());
// now parse the line
std::istringstream strm(line);
while (strm >> tempStr)
// add string to the last added vector
data.back().push_back(tempStr);
}
}
int main()
{
createVector();
std::cout << data.size();
}
Live Example

C/C++ reading and writing long strings to files

I have a list of cities that I'm formatting like this:
{town, ...},
{...},
...
Reading and building each town and creating town1, town2,.... works
The problem is when I output it, 1st line works {town, ...}, but the second line crashes.
Any idea why?
I have [region] [town] (excel table).
So each region repeats by how many towns are in it.
Each file has 1 region/town per line.
judete contains each region repeated 1 time.
AB
SD
PC
....
orase contains the towns list.
town1
town2
....
orase-index contains the region of each town
AB
AB
AB
AB
SD
SD
SD
PC
PC
...
I want an output like this {"town1", "town2", ...} and each row (row 5) contains the town that belong to the region from judete at the same row (row 5).
Here's my code:
#include<stdio.h>
#include<string.h>
char judet[100][100];
char orase[50][900000];
char oras[100], ceva[100];
void main ()
{
int i=0, nr;
FILE *judete, *index, *ORASE, *output;
judete = fopen("judete.txt", "rt");
index = fopen("orase-index.txt", "rt");
ORASE = fopen("orase.txt", "rt");
output = fopen("output.txt", "wt");
while( !feof(judete) )
{
fgets(judet[i], 100, judete);
i++;
}
nr = i;
char tmp[100];
int where=0;
for(i=0;i<nr;i++)
strcpy(orase[i],"");
while( !feof(index) )
{
fgets(tmp, 100, index);
for(i=0;i<nr;i++)
{
if( strstr(judet[i], tmp) )
{
fgets(oras, 100, ORASE);
strcat(ceva, "\"");
oras[strlen(oras)-1]='\0';
strcat(ceva, oras);
strcat(ceva, "\", ");
strcat(orase[i], ceva);
break;
}
}
}
char out[900000];
for(i=0;i<nr;i++)
{
strcpy(out, "");
strcat(out, "{");
strcat(out, orase[i]); //fails here
fprintf(output, "%s},\n", out);
}
}
The result I get from running the code is:
Unhandled exception at 0x00D4F7A9 (msvcr110d.dll) in orase-judete.exe: 0xC0000005: Access violation writing location 0x00A90000.
You don't clear orase array, beacause your loop
for(i-0;i<nr;i++)
strcpy(orase[i],"");
by mistake ('-' instead of '=') executes 0 times.
I think you need to start by making up your mind whether you're writing C or C++. You've tagged this with both, but the code looks like it's pure C. While a C++ compiler will accept most C, the result isn't what most would think of as ideal C++.
Since you have tagged it as C++, I'm going to assume you actually want (or all right with) C++ code. Well written C++ code is going to be enough different from your current C code that it's probably easier to start over than try to rewrite the code line by line or anything like that.
The immediate problem I see with doing that, however, is that you haven't really specified what you want as your output. For the moment I'm going to assume you want each line of output to be something like this: "{" <town> "," <town> "}".
If that's the case, I'd start by noting that the output doesn't seem to depend on your judete file at all. The orase and orase-index seem to be entirely adequate. For that, our code can look something like this:
#include <iostream>
#include <string>
#include <iterator>
#include <fstream>
#include <vector>
// a class that overloads `operator>>` to read a line at a time:
class line {
std::string data;
public:
friend std::istream &operator>>(std::istream &is, line &l) {
return std::getline(is, l.data);
}
operator std::string() const { return data; }
};
int main() {
// open the input files:
std::ifstream town_input("orase.txt");
std::ifstream region_input("orase-index.txt");
// create istream_iterator's to read from the input files. Note
// that these iterate over `line`s, (i.e., objects of the type
// above, so they use its `operator>>` to read each data item).
//
std::istream_iterator<line> regions(region_input),
towns(town_input),
end;
// read in the lists of towns and regions:
std::vector<std::string> town_list {towns, end};
std::vector<std::string> region_list {regions, end};
// write out the file of town-name, region-name:
std::ofstream result("output.txt");
for (int i=0; i<town_list.size(); i++)
result << "{" << town_list[i] << "," << region_list[i] << "}\n";
}
Noe that since this is C++, you'll typically need to save the source as something.cpp instead of something.c for the compiler to recognize it correctly.
Edit: Based on the new requirements you've given in the comments, you apparently want something closer to this:
#include <iostream>
#include <string>
#include <iterator>
#include <fstream>
#include <vector>
#include <map>
// a class that overloads `operator>>` to read a line at a time:
class line {
std::string data;
public:
friend std::istream &operator>>(std::istream &is, line &l) {
return std::getline(is, l.data);
}
operator std::string() const { return data; }
};
int main() {
// open the input files:
std::ifstream town_input("orase.txt");
std::ifstream region_input("orase-index.txt");
// create istream_iterator's to read from the input files. Note
// that these iterate over `line`s, (i.e., objects of the type
// above, so they use its `operator>>` to read each data item).
//
std::istream_iterator<line> regions(region_input),
towns(town_input),
end;
// read in the lists of towns and regions:
std::vector<std::string> town_list (towns, end);
std::vector<std::string> region_list (regions, end);
// consolidate towns per region:
std::map<std::string, std::vector<std::string> > consolidated;
for (int i = 0; i < town_list.size(); i++)
consolidated[region_list[i]].push_back(town_list[i]);
// write out towns by region
std::ofstream output("output.txt");
for (auto pos = consolidated.begin(); pos != consolidated.end(); ++pos) {
std::cout << pos->first << ": ";
std::copy(pos->second.begin(), pos->second.end(),
std::ostream_iterator<std::string>(output, "\t"));
std::cout << "\n";
}
}
Notice that ceva is never initialized.
Instead of using strcpy to initialize strings, I would recommend using static initialization:
char ceva[100]="";