I’m having trouble with the program. The program is intended to take input from a file in the form of names separated by a comma, and tally them in an output file (which I haven’t gotten to yet). It fails before “good so far 3”. Apparently, what it’s breaking on is defrencing the iterator it. That is to say, what I’m trying to do is use it as a pointer, and ++ that pointer. This should skip ahead to the next struct in the array. Then, I want to use it->inputName to access something inside of the struct. However, when I do it->inputName, it tries to use it as a pointer and it can’t do that. Not sure where to go from here, if I try to make a regular pointer like name * it, it doesn’t work with nameStorage.begin(), as that only takes an iterator. I’m on windows 7 using Microsoft Visual Studio 2010, if that helps.
I’m fairly new to programming, so any other tips would also be great. Thank you!
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
using namespace std;
struct name{
int tally;
string inputName;
};
bool die( const string& message );
int main( void ) {
ifstream infile;
infile.open( "input.txt", ifstream::in );
vector<name> nameStorage; // stores all names and tallies of them
vector<name>::iterator it;
string tempInput; // Stores the most recent input temporarily
char temp;
int counter = 0;
while ( temp = infile.get(), infile.good() ) { // loop while extraction from file is possible
if ( temp != ',' ) {
tolower ( temp ); // makes everything lowercase
tempInput.push_back(temp); }
else {
cout<<"good so far"<<endl;
for ( it = nameStorage.begin(); it <= nameStorage.end(); it++ ) {
cout<<"good so far 2"<<endl;
if ( tempInput == it->inputName ) {
cout<<"good so far 3"<<endl;
it->tally++;
break;
}
else if ( it == nameStorage.end() ) {
name tempStruct;
tempStruct.inputName = tempInput;
tempStruct.tally = 1;
nameStorage.push_back( tempStruct );
}
}
tempInput.clear(); // clears the string after it has stored it
}
counter++;
cout<<"Detected "<<counter<<" characters so far."<<endl;
}
}
bool die( const string& message ) {
cerr<<message;
exit (EXIT_FAILURE);
}
This code has at least 4 problems with it, not least of which is that using vectors for this kind of lookup/tally is extremely inefficient.
1) std::vector::end() returns a special type of iterator that does not support boolean operators such as <= (but does support operator- or operator-=). Well, it supports them, but the behaviour is undefined.
So
should be
2) Now that your for statement is correct, this comparison will never return true
and so your new value will never be stored in the vector. To find tempInput in nameStorage you can either use std::find
3) Using boolean equivalence operator on strings is generally considered bad form i.e.
should be
but you wont need to do that if you use std::find (above).
4) std::getline supports delimiters, and you should be using it instead of reading in 1 char at a time see http://www.cplusplus.com/reference/string/getline/
Last, you should really be doing your lookup/tally with a map. std:map is fine