I'm trying to iterate through a map to read out a string and then all of the numbers in a vector to a file. I copied and pasted the typedef line, then adjusted it to my code, so I'm not positive it's correct. Anyways, Visual Studio is giving me errors on the use of iterator_variable in my loops. It says type name is not allowed. How can I fix this?
ofstream output("output.txt");
typedef map<string, vector<int>>::iterator iterator_variable;
for (iterator_variable iterator = misspelled_words.begin(); iterator != misspelled_words.end(); iterator++)
{
output << iterator_variable->first;
for (int i = 0; i < misspelled_words.size(); i++)
{
output << " " << iterator_variable->second[i];
}
output << endl;
}
You should access the iterator like iterator->first instead of iterator_variable->first.
And for the inner loop, you probably want to iterate through 0 to iterator->second.size() instead of misspelled_words.size().
ofstream output("output.txt");
typedef map<string, vector<int>>::iterator iterator_variable;
for (iterator_variable iterator = misspelled_words.begin(); iterator != misspelled_words.end(); iterator++)
{
output << iterator->first;
for (int i = 0; i < iterator->second.size(); i++)
{
output << " " << iterator->second[i];
}
output << endl;
}
You can use the the new range based for loop and auto for more concise and readable code too.
ofstream output("output.txt");
for ( auto const & ref: misspelled_words ) {
output << ref.first;
for (auto const & ref2 : ref.second ) {
output << " " << ref2;
}
output << "\n"; // endl force a stream flush and slow down things.
}
Related
I have the following simple code. I declare a vector and initialize it with one value 21 in this case. And then i am trying to find that value in the vector using find. I can see that the element "21" in this case is in the vector since i print it in the for loop. However why the iterator of find does not resolve to true?
vector<uint8_t> v = { 21 };
uint8_t valueToSearch = 21;
for (vector<uint8_t>::const_iterator i = v.begin(); i != v.end(); ++i){
cout << unsigned(*i) << ' ' << endl;
}
auto it = find(v.begin(), v.end(), valueToSearch);
if ( it != v.end() )
{
string m = "valueToSearch was found in the vector " + valueToSearch;
cout << m << endl;
}
are you sure it doesn't work?
I just tried it:
#include<iostream> // std::cout
#include<vector>
#include <algorithm>
using namespace std;
int main()
{
vector<uint8_t> v = { 21 };
uint8_t valueToSearch = 21;
for (vector<uint8_t>::const_iterator i = v.begin(); i != v.end(); ++i){
cout << unsigned(*i) << ' ' << endl;
}
auto it = find(v.begin(), v.end(), valueToSearch);
if ( it != v.end() )
{// if we hit this condition, we found the element
string error = "valueToSearch was found in the vector ";
cout << error << int(valueToSearch) << endl;
}
return 0;
}
There are two small modifications:
in the last lines inside the "if", because you cannot add directly a
number to a string:
string m = "valueToSearch was found in the vector " + valueToSearch;
and it prints:
21
valueToSearch was found in the vector 21
while it's true that you cannot add a number to a string, cout
support the insertion operator (<<) for int types, but not uint8_t,
so you need to convert it to it.
cout << error << int(valueToSearch) << endl;
This to say that the find is working correctly, and it is telling you that it found the number in the first position, and for this, it != end (end is not a valid element, but is a valid iterator that marks the end of your container.)
Try it here
I've started a little toy project as a way to teach myself C++ and have hit a wall. In the code below the highlighted line is causing a build error saying:
welcome.cc:65:26: error: cannot convert
'std::_Rb_tree_iterator >' to 'char' in
assignment
current = result.first;
and I'm not sure why. The goal is to create a Markov chain for English placenames, the intent of the line in question is meant to update the current letter in the generated placename with a randomly selected value of the previous one, my random selection method is taken from this question. As I say, new to C++ and no idea what I've done wrong.
int main(int argc, char**argv) {
string line;
ifstream myfile;
std::multimap<char, char> m;
myfile.open ("C:\\Users\\james\\Desktop\\placenames.txt");
if (myfile.is_open()){
while ( getline (myfile,line) )
{
for(std::string::size_type i = 0; i < line.size(); ++i) {
std::cout<<line[i]<<std::endl;
m.insert(std::pair<char, char>(line[i], line[i+1]));
}
}
for (std::multimap<char, char>::iterator it = m.begin();it != m.end(); ++it)
cout << " [" << (*it).first << ", " << (*it).second << "]" << endl;
myfile.close();
// for( auto it = m.begin(), end = m.end();it != end; it = m.upper_bound(it->first))
// cout << (*it).first << ' ' << m.count( (*it).first) << endl;
auto current = 'A';
std::string name = "A";
typedef std::multimap<const char, char>::iterator MMAPIterator;
for (int j=0; j<8; ++j){
std::pair<MMAPIterator, MMAPIterator> result = m.equal_range(current);
std::size_t sz = std::distance(result.first, result.second);
std::size_t idx = std::rand() % sz;
std::advance(result.first, idx);
current = result.first; <------THIS LINE
//name+=current;
}
cout << name;
}
else cout << "Unable to open file";
return 0;
}
I'm aware its a pretty naive implementation of a markov chain, btw. As I say, intent was to play around with c++ rather than anything else.
You have a dual layer of pairs here, firstly the equal_range function returns a range, so your
std::size_t sz = std::distance(result.first, result.second);
Tells you how many items are in the range, to get an element of that range (your pair of chars) you need to
auto random_element = result.first;
auto the_const_char = random_element.first;
auto the_non_const_char = random_element.second;
Hello Everyone,
This is the following code of a package:
for (int iter = 0; iter < flags.total_iterations_; ++iter) {
std::cout << "Iteration " << iter << " ...\n";
if (flags.compute_likelihood_ == "true") {
double loglikelihood = 0;
for (list<LDADocument*>::const_iterator iterator = corpus.begin();
iterator != corpus.end();
++iterator) {
loglikelihood += sampler.LogLikelihood(*iterator);
}
std::cout << "Loglikelihood: " << loglikelihood << std::endl;
}
sampler.DoIteration(&corpus, true, iter < flags.burn_in_iterations_);
}
accum_model.AverageModel(
flags.total_iterations_ - flags.burn_in_iterations_);
FreeCorpus(&corpus);
std::ofstream fout(flags.model_file_.c_str());
accum_model.AppendAsString(word_index_map, fout);
return 0;
I would like to tweak this in such a way that for every 20 iterations, I would like to write a file that stores the result of fout. I am actually beginner in code coding in python. Since the package has the codes in c++, I have no idea what to input where.
I understand the logic like:
There must be a counter which counts the iteration and for every 20th iteration, a file must be created and the result of fout must be saved in that file. And for every 20th iteration I need new files to be created as I do not want the contents to be overwritten for analysis purpose.
Please help me as am a newbie and totally clueless about c++. Thanks in advance!
Try this:
for (int iter = 0; iter < flags.total_iterations_; ++iter) {
double loglikelihood = 0;
std::cout << "Iteration " << iter << " ...\n";
if(iter%20==0) {
const char *path1 = "Your path to the files"
std::ofstream llh_file;
std::ofstream myfile;
std::string result;
char numstr[30];
sprintf(numstr, "%d", iter);
result = path1 + std::string (numstr) + ".txt";
myfile.open(result.c_str());
model.AppendAsString(myfile);
myfile.close();
Complete program here for clarification: compilr.com/rayd360/test-songs
struct Album {
string title;
string year;
string track;
vector<string> tracks;
vector<string>::iterator trk;
}MyAlbums[40];
cout << "\n list of songs: \n";
for(int i = 0; i < 5; i++){
cout << *MyAlbums[i].trk << "\n";
}
gives me: "bash: line 1: 232 Segmentation fault "
I am needing to pass the list of tracks to a function that sorts them alphabetically then prints them out.
Any help is very much appreciated!
The line in the for loop dereferences the iterator returned by MyAlbums[i].trk. Since the iterator isn't assigned to anything (its internal pointer isn't pointing to anything) dereferencing it is Undefined Behavior. This can also cause a segmentation fault since your looking into memory that isn't owned by you.
To fix this I think you should remove the iterator from your class. Instead, use one inside your loop:
auto begin = MyAlbums.tracks.begin(),
end = MyAlbums.tracks.end();
for (auto it = begin; it != end; ++it)
{
std::cout << *it;
}
struct Album {
string title;
string year;
string track;
}MyAlbums[40];
vector<Album> tracks;
vector<Album>::iterator trk=tracks.begin();
cout << "\n list of songs: \n";
for(trk;trk!=tracks.end();++trk){
cout << *trk.title << "\n";
Assuming that you have already populated the MyAlbums.
There are two problems:
1) MyAlbums[i].trk is not initialized
2) While iterating through containers, ensure not to access container with invalid index.
(Ex: for(int i = 0; i < 5; i++) is not safe in this context).
// C++11
for ( auto track : MyAlbums.tracks )
{
cout << track << "\n";
}
// If not C++11
for (vector<string>::Iterator trackItr = MyAlbums.begin();
trackItr != MyAlbums.end(); ++trackItr)
{
cout << *trackItr << "\n";
}
Im having trouble accessing the following vector. Im new to vectors so this is probably a small syntactical thing i've done wrong. here is the code....
void spellCheck(vector<string> * fileRead)
{
string fileName = "/usr/dict/words";
vector<string> dict; // Stores file
// Open the words text file
cout << "Opening: "<< fileName << " for read" << endl;
ifstream fin;
fin.open(fileName.c_str());
if(!fin.good())
{
cerr << "Error: File could not be opened" << endl;
exit(1);
}
// Reads all words into a vector
while(!fin.eof())
{
string temp;
fin >> temp;
dict.push_back(temp);
}
cout << "Making comparisons…" << endl;
// Go through each word in vector
for(int i=0; i < fileRead->size(); i++)
{
bool found = false;
// Go through and match it with a dictionary word
for(int j= 0; j < dict.size(); j++)
{
if(WordCmp(fileRead[i]->c_str(), dict[j].c_str()) != 0)
{
found = true;
}
}
if(found == false)
{
cout << fileRead[i] << "Not found" << endl;
}
}
}
int WordCmp(char* Word1, char* Word2)
{
if(!strcmp(Word1,Word2))
return 0;
if(Word1[0] != Word2[0])
return 100;
float AveWordLen = ((strlen(Word1) + strlen(Word2)) / 2.0);
return int(NumUniqueChars(Word1,Word2)/ AveWordLen * 100);
}
The error is in the lines
if(WordCmp(fileRead[i]->c_str(), dict[j].c_str()) != 0)
and
cout << fileRead[i] << "Not found" << endl;
the problem seems to be, because its in the form of a pointer the current syntax im using to access it is made invalid.
Using [] on a pointer to a vector will not call std::vector::operator[]. To call std::vector::operator[] as you want, you must have a vector, not a vector pointer.
The syntax to access the n-th element of a vector with a pointer to the vector would be: (*fileRead)[n].c_str().
However, you should just pass a reference to the vector:
void spellCheck(vector<string>& fileRead)
Then it's just:
fileRead[n].c_str()
You can use the unary * to get a vector& from a vector*:
cout << (*fileRead)[i] << "Not found" << endl;
Two options to access:
(*fileRead)[i]
fileRead->operator[](i)
One option to improve the method
pass by reference
You can either pass fileRead by reference like this:
void spellCheck(vector<string> & fileRead)
Or add a dereferece when you use it like this:
if(WordCmp( (*fileRead)[i]->c_str(), dict[j].c_str()) != 0)