Re: STL::MAP: Printing values only once ..
On 18.01.2014 03:39, Rahul Mathur wrote:
Hi,
Oh, hi!
I have a input.txt file separator by pipe '|' as -
40147|181|ORANGE|MIKE|XX||1000397900|3500
40148|373|ORANGE|BOB|XX||1078889400|4500
40149|673|ORANGE|TREY|XX||1095159900|5500
I only wish to have all the FIRST(ID=40147) and LAST FIELD(PRICE=3500) to
be printed for three lines as given above.
I think this would be a task for "awk", or its modern replacement if
there is one. But as I recall from old days, "awk" was good at splitting
lines into fields. If working in Windows, then there are lots of "Unix
utilities" around, including just installing Cygwin (one practical idea
is to map drive U: to such utilities, write "u::awk").
I am reading as -
--
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <boost/algorithm/string.hpp>
Using Boost is generally a good idea when you have it available, but in
this case I think it's shooting gnats with intercontinental ballistic
H-bomb missiles. Will kill them gnats, guaranteed, yes. But, overkill...
using namespace std;
struct FILE_INPUT {
It's a good idea to reserve ALL UPPERCASE for macro names.
That way you tend to avoid name collisions and unintended text
substitutions.
Conversely, it's not a good idea to use ALL UPPERCASE for anything else
-- in C and C++.
Java and C# conventions are a different matter, since neither Java nor
C# has a preprocessor.
It's quite a bit ironic in a way. Java got its convention for constants
from C, where constants had to be defined as macros, hence ALL
UPPERCASE. So the Java convention is really about using ALL UPPERCASE
for macros-that-denote-constants, but Java doesn't have a preprocessor,
and does have a facility for defining constants, so it's all misplaced.
int ID;
Again, ungood ALL UPPERCASE name.
int Asset_ID;
char T_Name[];
Oh noes, that won't work! In standard C++ an array must have a specified
size. And unless it's dynamically allocated, size must be >0.
This shouldn't compile with strict ISO compliance.
An alternative for unknown-string-size is to use a `std::string`.
char Symbol[];
char Series[];
char Gap;
int Date;
int price;
};
int main() {
typedef std::map<int, int> unordmap;
unordmap ask;
FILE_INPUT fl_inp;
memset( &fl_inp, 0, sizeof(fl_inp) );
Oh! `memset`, that's easy to get wrong, and needlessly verbose.
In standard C++ just do
FILE_INPUT fl_inp = {};
to zero it.
See, it's safer, speedier, and shorter... ;-)
ifstream in ("input.txt");
string s;
const char delimiter = '|';
while ( getline (in, s) ) {
trim( s );
I do not see where you get that unqualified `trim` function from, but
perhaps Boost (formally incorrect) defines it in the `std` namespace so
that it's found by argument dependent lookup?
if ( !s.empty() ) {
stringstream strm( s );
string item;
getline( strm, item );
This reads the whole line from the stream. And the whole line is all
there is. What is the purpose of that?
stringstream stra( item );
string tmp;
getline( stra, tmp, delimiter );
{
stringstream strb( tmp );
strb >> fl_inp.ID;
}
getline( stra, tmp, delimiter )
{
stringstream strb( tmp );
strb >> fl_inp.price;
}
Presumably the above code is what remained after you removed error
checking etc., so as to get simpler code for presentation here?
ask.insert( std::make_pair((fl_inp.ID),(fl_inp.price)) );
unordmap::iterator pos = ask.begin();
for (pos = ask.begin(); pos != ask.end(); ++pos) {
std::cout << "ID: " << pos->first << "\t"
<< "Price: " << pos->second << std::endl;
}
std::cout << " " << endl;
}
}
}
Consider something like this (it differs from yours in not verifying
that the strings are valid number specifications, but you can just add
that):
[code]
#include <algorithm> // std::replace
#include <iostream>
#include <map> // std::map
#include <sstream> // std::istringstream
#include <stdlib.h> // EXIT_FAILURE
#include <string> // std::string
using namespace std;
#define ITEMS_OF( c ) c.begin(), c.end()
auto main()
-> int
{
string line;
while( getline( cin, line ) )
{
replace( ITEMS_OF( line ), '|', ' ' );
istringstream stream( line );
for( int i = 1; i <= 7; ++i )
{
string word;
if( (stream >> word).fail() )
{
cout << endl;
cerr << "! Not enough items on this input line:" << endl;
cerr << "! '" << line << "'" << endl;
return EXIT_FAILURE;
}
if( i == 1 ) { cout << "ID: " << word << " "; }
if( i == 7 ) { cout << "Price: " << word << endl; }
}
}
}
[/code]
Cheers & hth.,
- Alf