Counter for items in an inventory using iterators - c++

I'm somewhat new to vectors and iterators and I'm trying to figure out how to display an amount of items using an iterator. One example would be you have 5 apples. I would want it to output "5x Apple" or something of that sort. I have no idea how one might accomplish this. Here's a simple code that has the user put in a string to add to the inventory.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
string item;
vector<string> inventory;
vector<string>::iterator iter;
int main()
{
while(true){
cin >> item;
inventory.push_back(item);
cout << "INVENTORY:\n";
for(iter = inventory.begin(); iter != inventory.end(); iter++)
cout << *iter << endl;
}
}
EDIT: I'm trying to make an inventory system for a game. That's why I thought i may need an iterator. If there's a better way to make an inventory system than using an iterator, please let me know. Apologies, i should have clarified.

An iterator lets you iterate through a container, but it does not do any counting for you.
A container's size() tells you how many items are in the container, but if you have different types of items then you have to count them yourself.
For instance, say you have 4 "apple" and 1 "orange".
You have to look at each item entered and count it as needed, eg:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
vector<string> inventory;
int numApples = 0;
int numOranges = 0;
int numOther = 0;
int main()
{
string item;
while (cin >> item)
{
inventory.push_back(item);
if (item == "apples")
++numApples;
else if (item == "orange")
++numOranges;
else
++numOther;
}
cout << "INVENTORY:\n";
for (vector<string>::iterator iter = inventory.begin(); iter != inventory.end(); ++iter)
cout << *iter << endl;
/* or, if you are using C++11 or later:
for (string &s : inventory)
cout << s << endl;
*/
cout << "# apples: " << numApples << endl;
cout << "# oranges: " << numOranges << endl;
cout << "# other: " << numOther << endl;
return 0;
}
Or, you might consider using std::count_if(), eg:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
vector<string> inventory;
bool isApple(const string &s) { return (s == "apple"); }
bool isOrange(const string &s) { return (s == "orange"); }
bool isOther(const string &s) { return !(isApple(s) || isOrange(s)); }
int main()
{
string item;
while (cin >> item)
inventory.push_back(item);
cout << "INVENTORY:\n";
for (vector<string>::iterator iter = inventory.begin(); iter != inventory.end(); ++iter)
cout << *iter << endl;
/* or, if you are using C++11 or later:
for (string &s : inventory)
cout << s << endl;
*/
cout << "# apples: " << count_if(inventory.begin(), inventory.end(), isApple) << endl;
cout << "# oranges: " << count_if(inventory.begin(), inventory.end(), isOrange) << endl;
cout << "# other: " << count_if(inventory.begin(), inventory.end(), isOther) << endl;
/* or, if you are using C++11 or later:
cout << "# apples: " << count_if(inventory.begin(), inventory.end(), [](auto &s){ return (s == "apple"); }) << endl;
cout << "# oranges: " << count_if(inventory.begin(), inventory.end(), [](auto &s){ return (s == "orange"); }) << endl;
cout << "# other: " << count_if(inventory.begin(), inventory.end(), [](auto &s){ return (s != "apple") && (s != "orange"); }) << endl;
*/
return 0;
}
Update: based on another question you posted, try something more like this instead:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
vector<string> other_inventory;
int numApples = 0;
int numOranges = 0;
int main()
{
string item;
while (cin >> item)
{
if (item == "apples")
++numApples;
else if (item == "orange")
++numOranges;
else
other_inventory.push_back(item);
}
cout << "INVENTORY:\n";
if (numApples > 0)
cout << "# apples: " << numApples << endl;
if (numOranges > 0)
cout << "# oranges: " << numOranges << endl;
for (vector<string>::iterator iter = other_inventory.begin(); iter != other_inventory.end(); ++iter)
cout << *iter << endl;
/* or, if you are using C++11 or later:
for (string &s : other_inventory)
cout << s << endl;
*/
return 0;
}

A way to simplify this is to sort the items in the inventory. That will bring the identical ones together, which simplifies counting them. Start at the beginning, count the number of consecutive items that match the current one, display it, and continue with the first non-matching one.
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::string item;
std::vector<std::string> inventory;
while (true) {
std::cin >> item;
if (item == "quit") return 0;
inventory.push_back(item);
std::sort(inventory.begin(), inventory.end());
std::cout << "INVENTORY:\n";
auto current = inventory.begin();
while (current != inventory.end()) {
int count = 1;
auto probe = current + 1;
while (probe != inventory.end() && *probe == *current) {
++count;
++probe;
}
std::cout << count << "x " << *current << '\n';
current = probe;
}
std::cout.flush();
}
return 0;
}
In more detail, if your inventory is {"orange", "apple", "orange"}, then the sort will rearrange the order to {"apple", "orange", "orange"}. Note that the identical ones are together.
Now the iterator current starts at the beginning ("apple"). We set count to 1 because we know there's at least 1. We set the iterator probe to point to the next item ("orange"). Since the value at probe doesn't match the value at current, the inner loop does nothing. We print count and the current item ("apple"). We continue by setting current to probe, because, at this point, probe will point to the first item that didn't match the current one.
On the second iteration, current refers to the first "orange". We reset count to 1 and start probe at the next item ("orange"). Since the values at match, we increment count (now 2) and advance probe (now at the end of the inventory). We print count (2) and the current item ("orange"), and set current to probe (end of the list). The outer loop condition sees we're at the end of the inventory, so the loop terminates.

inventory.size()
returns the number of items in your vector.
I don't see how you would need an iterator for that task.

Related

C++ Multimap Printing

I'm trying to make a name, and then give a list of courses this person has taken. Here is my code currently:
#include <iostream>
#include <string>
#include <map>
#include <list>
using namespace std;
int main()
{
multimap<string,string> students;
students.insert(make_pair("john","cs1"));
students.insert(make_pair("john","cs2"));
for (auto itr = students.begin(); itr != students.end(); ++itr)
{
cout << itr->first << '\t' << itr->second << '\n';
}
}
This prints out:
John CS1
John CS2
If I wanted to make it print out the first value and then print out all second values, how would I do this? Do I need to use a list as the second value or something? Or is this doable with just multimaps? For example:
John CS1 CS2
You can use equal_range to achieve what you wanted, see:
std::string current_key = "";
for (auto itr = students.begin(); itr != students.end(); ++itr)
{
if(current_key == itr->first) {
continue;
} else {
current_key = itr->first;
}
const auto result = students.equal_range(itr->first);
cout << itr->first << ": ";
for(auto it = result.first; it != result.second; ++it) {
cout << it->second << " ";
}
cout << endl;
}
See working example here: https://ideone.com/RqCFOk
You'll may eventually end up creating a class to model a student, in the meantime, you could just iterate over the multimap container and check if the current key is the same as the previous:
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <string>
using students_t = std::multimap<std::string, std::string>;
void print_students_list(students_t const& students)
{
// Start printing the name of the first student and the first course (the first key-value
// pair) if the container is not empty.
auto student{ students.cbegin() };
if ( student == students.cend() )
return;
std::cout << std::setw(12) << std::left << student->first
<< std::setw(8) << student->second;
// Then iterate over the rest of the container printing the name (after a newline)
// only if it's different from the previous one.
for ( auto prev{ student++ }; student != students.cend(); prev = student, ++student )
{
if ( student->first != prev->first )
std::cout << '\n' << std::setw(12) << student->first;
std::cout << std::setw(8) << student->second;
}
std::cout << '\n';
}
int main()
{
students_t students {
{"john", "cs1"},
{"john", "cs2"},
{"Karen", "cs2"},
{"Karen", "nc1"},
{"Karen", "nc2"},
{"Bob", "nc1"}
};
print_students_list(students);
}

C++ => No constructor could take the source type, or constructor overload resolution was ambiguous

I have a simple student project and I need some help. I have got a message with some kind of an error that i can't fix. Please help me with a solution. The project is in C++. Below is my code:
#include <iostream>
#include <stdlib.h>
#include <list>
#include <set>
using namespace std;
struct V
{
char name;
list <V> to_v;
};
list <V> graph_v;
set <char> PoseteniVarhove;
list <V> ::iterator ukaz(char name)
{
list <V> ::iterator retukaz = (list <V> ::iterator) NULL; // <-- ERROR HERE
for (list <V> ::iterator it = graph_v.begin(); it != graph_v.end(); it++)
if ((*it).name == name)
retukaz = it;
return retukaz;
}
void MakeGraph()
{
int n, br;
V v;
list <V> ::iterator it;
char name;
do
{
cout << "Broy varhove(1..26): "; cin >> n;
} while (n < 1 || n > 26);
graph_v.clear();
for (int c = 0; c < n; c++)
{
v.name = (char)('A' + c);
v.to_v.clear();
graph_v.push_back(v);
}
for (it = graph_v.begin(); it != graph_v.end(); it++)
{
cout << endl;
cout << "Vrah " << (*it).name << endl;
cout << "Kam kolko drugi varha ima nasocheni rebra? ";
cin >> br;
for (int k = 0; k < br; k++)
{
cout << "Rebro kam vrah #" << 1 + k << endl;
cout << "Ime na varha('A'..'Z'): ";
cin >> name;
v.name = name;
v.to_v.clear();
v.to_v.push_back(*ukaz(name));
(*it).to_v.push_back(v);
}
}
}
void PrintGraph()
{
list <V> ::iterator it, it1;
for (it = graph_v.begin(); it != graph_v.end(); it++)
{
cout << endl << "Ot vrah " << (*it).name << " kam varhove ";
for (it1 = (*it).to_v.begin(); it1 != (*it).to_v.end(); it1++)
cout << (*it1).name << " ";
}
cout << endl;
}
bool Path(char beginVrah, char TekVrah, char Target)
{
bool P = false;
list <V> ::iterator uk, it;
if (PoseteniVarhove.count(TekVrah) == 0)
{
uk = ukaz(TekVrah);
PoseteniVarhove.insert(TekVrah);
for (it = (*uk).to_v.begin(); it != (*uk).to_v.end(); it++)
{
if ((*it).name == Target)
return true;
else
if ((*it).name != beginVrah && !P)
P = Path(beginVrah, (*it).name, Target);
}
}
return P;
}
void Paths()
{
int Count = 0;
bool P;
list <V> ::iterator it, it1;
for (it = graph_v.begin(); it != graph_v.end(); it++)
for (it1 = it; it1 != graph_v.end(); it1++)
if (it != it1)
{
P = false;
PoseteniVarhove.clear();
if (Path((*it).name, (*it).name, (*it1).name))
P = true;
PoseteniVarhove.clear();
if (Path((*it1).name, (*it1).name, (*it).name) && P)
{
cout << (*it).name << ' ' << (*it1).name << endl;
Count++;
}
}
cout << "Obshto " << Count << " dvoyki" << endl << endl;
}
int main()
{
char ch[256];
int choice;
cout << "Graph" << endl;
do
{
cout << endl << "1. Vavezhdane na Graph" << endl;
cout << "2. Izvezhdane na Grapha" << endl;
cout << "3. Paths" << endl;
cout << "4. Kray" << endl;
do
{
cout << "(1,2,3,4): ";
cin >> ch;
choice = atoi(ch);
} while (choice < 1 || choice > 4);
switch (choice)
{
case 1:
MakeGraph();
break;
case 2:
PrintGraph();
break;
case 3:
Paths();
break;
case 4:
break;
default:
break;
}
} while (choice < 4);
return 0;
}
The following error appears:
No constructor could take the source type, or constructor overload resolution was ambiguous
MSVC points to NULL in the first line of the function ukaz.
A "NULL" value for an iterator is usually .end(). It's not entirely clear to me what ukaz means, but it looks like you're trying to do something similar to a find.
As such, if nothing is found, I'd return the .end() of your list. Note that this is also what std::find does:
Return value
Iterator to the first element satisfying the condition or last if no such element is found.
If you want the last occurrence of the value, you can loop using reverse iterators and return immediately when you find something. That way you don't even need to temporary iterator at all. That could look like:
list <V> ::iterator ukaz(char name)
{
for (list <V> ::iterator it = graph_v.rbegin(); it != graph_v.rend(); it++)
if ((*it).name == name)
return it;
return graph_v.end(); // <-- default return val if nothing is found
}

How to iterate through a List function?

I'm running a test program where I make a list of strings and try to find which strings have a certain suffix or prefix.
#include <iostream>
#include <list>
#include <string>
using namespace std;
list<string> beginWith(const string& pre, list <string> test);
list<string> endWith(const string& suf,list <string> test);
int main(){
list <string> testList(5);
string suffix = "able";
string prefix = "M";
testList.push_back("Agreeable");
testList.push_back("Doable");
testList.push_back("Machine");
testList.push_back("Makeable");
testList.push_back("Available");
for(list <string>::const_iterator it = testList.begin(); it != testList.end(); it++){
cout << *it << endl;
}
for(list <string>::const_iterator it = beginWith(prefix, testList).begin(); it != beginWith(prefix, testList).end(); it++){
cout << *it << endl;
}
for(list <string>::const_iterator it = endWith(suffix, testList).begin(); it != endWith(suffix, testList).end(); it++){
cout << *it << endl;
}
return 0;
}
list<string> beginWith(const string& pre, list<string> test){
list <string> answer;
for(list <string>::const_iterator it = test.begin(); it != test.end(); it++){
if(pre == it->substr(0, pre.length())){
answer.push_back(*it);
}
}
return answer;
}
list<string> endWith(const string& suf, list <string> test){
list <string> answer;
for(list <string>::const_iterator it = test.begin(); it != test.end(); it++){
if(suf == it->substr(it->length() - suf.length() , it->back())){
answer.push_back(*it);
}
}
return answer;
}
I declared a list of strings printed them out with the first for-loop. I also have 2 functions which will iterate through that list and then return a list of strings that have a certain prefix or suffix. I'll print those out with the 2nd and 3rd for-loop. The 1st for-loop prints out correctly however, I get a segmentation fault: 11 when I print out the 2nd and 3rd for loops. I'm confused as to how I would get those for-loops to iterate through the list functions and print out the contents.
beginWith and endWith return a list by value. This makes the for-loops call begin() and end() on different copies of the list.
list<string> beginWith(const string& pre, list<string> test) {
list <string> answer;
for (auto word : test) // Use C++ auto to iterate collection
{
cout << "Testing " << word << " against " << pre << " ... ";
if (word.find(pre) == 0) // From http://thispointer.com/c-check-if-a-string-starts-with-an-another-given-string/
{
cout << "match!";
answer.push_back(word);
}
cout << '\n';
}
return answer;
}
list<string> endWith(const string& suf, list <string> test) {
list <string> answer;
for (auto word : test)
{
cout << "Testing " << word << " against " << suf << " ... ";
if (word.size() >= suf.size() &&
word.compare(word.size() - suf.size(), suf.size(), suf) == 0) // From http://thispointer.com/c-how-to-check-if-a-string-ends-with-an-another-given-string/
{
cout << "match!";
answer.push_back(word);
}
cout << '\n';
}
return answer;
}
int main(int argc, wchar_t *argv[])
{
list <string> testList {}; // Create empty list, not list with five elements
string suffix = "able";
string prefix = "M";
testList.push_back("Agreeable");
testList.push_back("Doable");
testList.push_back("Machine");
testList.push_back("Makeable");
testList.push_back("Available");
for (auto word : testList) {
cout << word << '\n';
}
auto prefixedWords = beginWith(prefix, testList);
cout << "Prefixed words: \n";
for (auto prefixed : prefixedWords) {
cout << " " << prefixed << '\n';
}
auto suffixedWords = endWith(suffix, testList);
cout << "Suffixed words: \n";
for (auto suffixed : suffixedWords) {
cout << " " << suffixed << '\n';
}
return 0;
}
Program output:
Agreeable
Doable
Machine
Makeable
Available
Testing Agreeable against M ...
Testing Doable against M ...
Testing Machine against M ... match!
Testing Makeable against M ... match!
Testing Available against M ...
Prefixed words:
Machine
Makeable
Testing Agreeable against able ... match!
Testing Doable against able ... match!
Testing Machine against able ...
Testing Makeable against able ... match!
Testing Available against able ... match!
Suffixed words:
Agreeable
Doable
Makeable
Available

Hangman w/ Functions - Compile Error - No Match for Call To

I've been trying to get this Hangman using functions (from Michael Dawson's book) program to work, but I have this one error that I don't really understand. I realize my code code could have a variety of bad practices, but please go easy on me as I am a newb. I feel like I am almost there but I'm having trouble figuring out this one error. I am using CodeBlocks. The error is:
32|error: no match for call to '(std::__cxx11::string {aka std::__cxx11::basic_string}) (std::__cxx11::basic_string::size_type, char)'|
//Hangman from Michael Dawson's code
//Uses functions to create the program
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <ctime>
#include <cctype>
using namespace std;
//FUNCTION DECLARATION
string pickword();
char playerGuess();
void isitinthere();
char guess = 0;
string soFar = "word";
string used = "";
int wrong = 0;
int main()
{
const int MAX_WRONG = 8;
string WORD = pickword();
soFar = WORD;
soFar(WORD.size(), '-');
used = "";
cout << "Welcome to Hangman! Godspeed!" << endl;
while ((wrong < MAX_WRONG) && (soFar != WORD))
{
cout << "\n\nYou have " << (MAX_WRONG - wrong);
cout << " incorrect guesses left.\n";
cout << "\nYou've used the following letters:\n" << used << endl;
cout << "\nSo far, the word is:\n" << soFar << endl;
}
playerGuess();
while (used.find(guess) != string::npos)
{
cout << "\nYou've already guessed " << guess << endl;
cout << "Enter your guess: ";
cin >> guess;
guess = toupper(guess);
}
used += guess;
isitinthere();
if (wrong == MAX_WRONG)
{
cout << "\nYou've been hanged!";
}
else
{
cout << "\nYou guessed it!";
}
cout << "\nThe word was " << WORD << endl;
return 0;
}
//FUNCTION DEFINITION
string pickword()
{
srand(static_cast<unsigned int>(time(0)));
vector<string> words;
words.push_back("INDUBITABLY");
words.push_back("UNDENIABLY");
words.push_back("CRUSTACEAN");
words.push_back("RESPONSIBILITY");
words.push_back("MISDEMEANOR");
words.push_back("FORENSIC");
words.push_back("BALLISTIC");
words.push_back("PARADIGM");
words.push_back("TROUBARDOR");
words.push_back("SUPERCALIFRAGILISTICEXPIALLADOCIOUS")
random_shuffle(words.begin(), words.end());
theword = words[0];
return theword;
}
char playerGuess()
{
cout << "\n\nEnter your guess: ";
cin >> guess;
guess = toupper(guess);
return guess;
}
void isitinthere()
{
if (WORD.find(guess) != string::npos)
{
cout << "That's right! " << guess << " is in the word.\n";
for (int i = 0; i < WORD.length(); ++i)
{
if (WORD[i] == guess)
{
soFar[i] = guess;
}
}
}
else
{
cout << "Sorry, " << guess << "isn't in the word. \n";
++wrong;
}
}
Thanks in advance for your help!
Here is a simple program that should solve your question.
#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <cctype>
// since you must have function here are some
bool removeGuessFromWord(std::string& word, const char guess);
bool isGuessInWord(const std::string& word, const char guess);
bool hasAlreadyGuessed(const std::vector<char>& gussList, const char guess);
// this is a simple program that should solve your question. It is not optimized for speed or efficency.
int main()
{
std::vector<std::string> wordList = {"dog","cat","rat"}; // vector of words to select from and use as the word in hangman
std::vector<char> guessList; // empty vector of gusses
// Note that I assume a MAX_GUESS_COUNT of 0 means no guesses are allowed
const unsigned int MAX_GUESS_COUNT = 4U; // number of guesses your allowed
std::srand(time(0)); // use current time as seed for random generator
std::string word = wordList.at(std::rand()%wordList.size()); // get a random word in the list
std::string letersLeft = word; // keep track of what letters will still need to remove
std::cout << "Welcome to Hangman! Godspeed!" << std::endl;
char guess = 0;
for(unsigned int numBadGusses=0U; numBadGusses<MAX_GUESS_COUNT && letersLeft.size()>0U; guess = 0)
{
std::cin>>guess;
if(std::isprint(guess) == 0)
{
// may want more error checking
std::cout << "You ented a non-printable charecter" << std::endl;
}
else if(isGuessInWord(word, guess))
{
// this was a good guess because the charecter is still in the word
// so remove all the remaining chars of this type from the word
if( removeGuessFromWord(letersLeft,guess) )
{
std::cout << guess << " was a good guess" << std::endl;
}
else
{
std::cout << guess << " was a good guess, but you already guessed it once" << std::endl;
}
}
else if(hasAlreadyGuessed(guessList, guess))
{
std::cout << "You've already guessed " << guess << std::endl;
}
else
{
// this was a new bad guess
guessList.push_back(guess);
numBadGusses++; // Note that this isn't technicly needed and could use size of vector
std::cout << guess << " was a bad guess" << std::endl;
}
}
if(letersLeft.size() == 0U)
{
std::cout<<"You Win"<<std::endl;
}
else
{
std::cout<<"You Lose"<<std::endl;
}
std::cout << "The word was "<< word << std::endl;
return 0;
}
bool removeGuessFromWord(std::string& word, const char guess)
{
return word.erase(std::remove(word.begin(), word.end(), guess), word.end()) != word.end() ? true : false;
}
bool isGuessInWord(const std::string& word, const char guess)
{
return word.find(guess) != std::string::npos ? true: false;
}
bool hasAlreadyGuessed(const std::vector<char>& gussList, const char guess)
{
return std::find(gussList.begin(), gussList.end(), guess) != gussList.end() ? true: false;
}

Reducing process time of two map using c++

I have two maps: Pkt_creatingmap and Pkt_arrivalmap. The number of elements in (Pkt_creatingmap) map is much more than the number of elements in (Pkt_arrivalmap) map [i.e.: total number of elements in Pkt_creatingmap about 650000 elements and total number of element in Pkt_arrivalmap about 72000 elements].
I want to compare the key IDs (firsts) in (Pkt_creatingmap) map and (Pkt_arrivalmap) map. If it is equal then subtract the values of key IDs (seconds) and store the result in list (TotalTrafficETED).
I write below code to do this task, However it takes a long time to accomplish (i.e.: it is time consuming). Not all elements in (Pkt_creatingmap) map are needed in this process. The process of subtraction depends only on the elements of (Pkt_arrivalmap) map.
Is there method to reduce the running time? (i.e.: can the iterator of (Pkt_creatingmap) map end at the end location of (Pkt_arrivalmap) map iterator?
Hope my question is clear.
Anyone can help me please or give me another ideal to do this task ..
#include <iostream>
#include <fstream>
#include <string>
#include <stdint.h>
#include <sstream>
#include <cmath>
#include <map>
#include <iterator>
#include <list>
using namespace std;
int main()
{
map<double_t, double_t> Pkt_arrivalmap;
map<double_t, double_t> Pkt_creatingmap;
list<double_t> TotalTrafficETED;
int pos, pos2, pos3;
double_t ArrivingID, CreatingID, ArrivingTime, CreatingTime, Pkt_ETED, TTETED;
string line, search, word1 = "ns", word2 = "Pkt_create", word3 = "Pkt_recv";
ifstream inf;
inf.open("123.txt");
if (inf.is_open()) {
while (getline(inf, line)) {
if (line.find("Pkt_recv") != string::npos) {
pos = line.find(word1);
pos3 = line.find(word3);
line.replace(pos, word1.length(), " "); // to remove "ns"
line.replace(pos3, word3.length(), " "); // to remove "Pkt_recv"
istringstream iss(line);
double_t column1;
//double_t column3;
double_t column2;
iss >> column1 >> column2;
//cout << column1 <<" "<< column2 <<" "<< " "<< endl;
Pkt_arrivalmap[column1] = column2;
}
}
inf.close();
}
else
cout << "Unable to open file inf \n";
for (std::map<double_t, double_t>::iterator it = Pkt_arrivalmap.begin(); it != Pkt_arrivalmap.end(); it++) {
cout << "Arrival info."
<< " " << it->first << " " << it->second << " " << Pkt_arrivalmap.size() << endl;
}
inf.open("123.txt");
if (inf.is_open()) {
while (getline(inf, line)) {
if (line.find("Pkt_create") != string::npos) {
pos = line.find(word1);
pos2 = line.find(word2);
line.replace(pos, word1.length(), " "); // to remove "ns"
line.replace(pos2, word2.length(), " "); // to remove "Pkt_create"
istringstream iss(line);
double_t column1;
//double_t column3;
double_t column2;
iss >> column1 >> column2;
//cout << column1 <<" "<< column2 <<" "<< " "<< endl;
Pkt_creatingmap[column1] = column2;
}
}
inf.close();
}
else
cout << "Unable to open file inf \n";
for (std::map<double_t, double_t>::iterator it = Pkt_creatingmap.begin(); it != Pkt_creatingmap.end(); it++) {
cout << "Creating info."
<< " " << it->first << " " << it->second << " " << Pkt_creatingmap.size() << endl;
}
for (std::map<double_t, double_t>::iterator it = Pkt_arrivalmap.begin(); it != Pkt_arrivalmap.end(); it++) {
ArrivingID = it->first;
ArrivingTime = it->second;
//cout << "Ahmed" <<" "<< ArrivingID <<endl;
for (std::map<double_t, double_t>::iterator it = Pkt_creatingmap.begin(); it != Pkt_creatingmap.end(); it++) {
CreatingID = it->first;
CreatingTime = it->second;
if (ArrivingID == CreatingID) {
Pkt_ETED = (ArrivingTime - CreatingTime) / 1000000000;
TotalTrafficETED.push_back(Pkt_ETED);
Pkt_creatingmap.erase(it->first);
Pkt_arrivalmap.erase(it->first);
cout << "Pkt_ID:" << CreatingID << ","
<< "Pkt_ETED:" << Pkt_ETED << endl;
}
}
}
for (std::list<double_t>::iterator it = TotalTrafficETED.begin(); it != TotalTrafficETED.end(); it++) {
TTETED += *it / TotalTrafficETED.size();
}
cout << "Total Traffic ETED"
<< " " << TTETED << endl;
return 0;
}
If you want to find an element with a given ID in a map, the method map::find is very efficient and proceeds logarithmic in size of the map, because it is a sorted container. In your code, you do two for loop and the complexity is quadratic. Thus, you have to write something like that :
for (std::map<double_t,double_t>::iterator it = Pkt_arrivalmap.begin(); it != Pkt_arrivalmap.end(); it++)
{
ArrivingID =it->first;
ArrivingTime=it->second;
//cout << "Ahmed" <<" "<< ArrivingID <<endl;
map<double_t,double_t>::iterator it2 = Pkt_creatingmap.find(ArrivingID);
if (it2!=Pkt_creatingmap.end()){ // Found equivalent key
CreatingTime=it2->second;
Pkt_ETED=(ArrivingTime-CreatingTime)/1000000000;
TotalTrafficETED.push_back(Pkt_ETED);
Pkt_creatingmap.erase(it->first);
Pkt_arrivalmap.erase(it2->first);
cout <<"Pkt_ID:"<<CreatingID<<","<<"Pkt_ETED:"<<Pkt_ETED<<endl;
}
}