This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I'm currently using the class given in this tutorial: http://www.dreamincode.net/forums/topic/183191-create-a-simple-configuration-file-parser/
Initially it worked fine, but since I split the single source file into seperate header and cpp files I've been unable to call the getValueOfKey function
header:
#ifndef CONFIGFILE_H
#define CONFIGFILE_H
#include <iostream>
#include <string>
#include <sstream>
#include <map>
#include <fstream>
#include <typeinfo>
class ConfigFile
{
private:
std::map<std::string, std::string> contents;
std::string fName;
void removeComment(std::string &line) const;
bool onlyWhitespace(const std::string &line) const;
bool validLine(const std::string &line) const;
void extractKey(std::string &key, size_t const &sepPos, const std::string &line) const;
void extractValue(std::string &value, size_t const &sepPos, const std::string &line) const;
void extractContents(const std::string &line);
void parseLine(const std::string &line, size_t const lineNo);
void ExtractKeys();
public:
ConfigFile(const std::string &fName);
bool keyExists(const std::string &key) const;
template <typename ValueType>
ValueType getValueOfKey(const std::string &key, ValueType const &defaultValue) const;
};
#endif /* CONFIGFILE_H */
cpp:
#include "ConfigFile.h"
std::map<std::string, std::string> contents;
std::string fName;
template <typename T>
static std::string T_to_string(T const &val)
{
std::ostringstream ostr;
ostr << val;
return ostr.str();
}
template <typename T>
static T string_to_T(std::string const &val)
{
std::istringstream istr(val);
T returnVal;
if (!(istr >> returnVal))
std::cout << "CFG: Not a valid " << (std::string)typeid (T).name() << " received!\n" << std::endl;
return returnVal;
}
template <>
std::string string_to_T(std::string const &val)
{
return val;
}
void ConfigFile::removeComment(std::string &line) const
{
if (line.find(';') != line.npos)
line.erase(line.find(';'));
}
bool ConfigFile::onlyWhitespace(const std::string &line) const
{
return (line.find_first_not_of(' ') == line.npos);
}
bool ConfigFile::validLine(const std::string &line) const
{
std::string temp = line;
temp.erase(0, temp.find_first_not_of("\t "));
if (temp[0] == '=')
return false;
for (size_t i = temp.find('=') + 1; i < temp.length(); i++)
if (temp[i] != ' ')
return true;
return false;
}
void ConfigFile::extractKey(std::string &key, size_t const &sepPos, const std::string &line) const
{
key = line.substr(0, sepPos);
if (key.find('\t') != line.npos || key.find(' ') != line.npos)
key.erase(key.find_first_of("\t "));
}
void ConfigFile::extractValue(std::string &value, size_t const &sepPos, const std::string &line) const
{
value = line.substr(sepPos + 1);
value.erase(0, value.find_first_not_of("\t "));
value.erase(value.find_last_not_of("\t ") + 1);
}
void ConfigFile::extractContents(const std::string &line)
{
std::string temp = line;
temp.erase(0, temp.find_first_not_of("\t "));
size_t sepPos = temp.find('=');
std::string key, value;
extractKey(key, sepPos, temp);
extractValue(value, sepPos, temp);
if (!keyExists(key))
contents.insert(std::pair<std::string, std::string > (key, value));
else
std::cout << "CFG: Can only have unique key names!\n" << std::endl;
}
void ConfigFile::parseLine(const std::string &line, size_t const lineNo)
{
if (line.find('=') == line.npos)
std::cout << "CFG: Couldn't find separator on line: " << T_to_string(lineNo) << "\n" << std::endl;
if (!validLine(line))
std::cout << "CFG: Bad format for line: " << T_to_string(lineNo) << "\n" << std::endl;
extractContents(line);
}
void ConfigFile::ExtractKeys()
{
std::ifstream file;
file.open(fName.c_str());
if (!file)
std::cout << "CFG: File " << fName << " couldn't be found!\n" << std::endl;
std::string line;
size_t lineNo = 0;
while (std::getline(file, line))
{
lineNo++;
std::string temp = line;
if (temp.empty())
continue;
removeComment(temp);
if (onlyWhitespace(temp))
continue;
parseLine(temp, lineNo);
}
file.close();
}
ConfigFile::ConfigFile(const std::string &fName)
{
this->fName = fName;
ExtractKeys();
}
bool ConfigFile::keyExists(const std::string &key) const
{
return contents.find(key) != contents.end();
}
template <typename ValueType>
ValueType ConfigFile::getValueOfKey(const std::string &key, ValueType const &defaultValue = ValueType()) const
{
if (!keyExists(key))
return defaultValue;
return string_to_T<ValueType> (contents.find(key)->second);
}
I am attempting to call it using the same method as when it was a single file, something like std::cout << Config.getValueOfKey<std::string>("test");, but now I am getting the following compiler error
main.cpp: In function 'int main(int, char**)':
main.cpp:29:71: error: no matching function for call to 'ConfigFile::getValueOfKey(const char [5])'
main.cpp:29:71: note: candidate is:
In file included from main.h:17:0,
from main.cpp:9:
ConfigFile.h:35:12: note: template<class ValueType> ValueType ConfigFile::getValueOfKey(const string&, const ValueType&) const
ConfigFile.h:35:12: note: template argument deduction/substitution failed:
main.cpp:29:71: note: candidate expects 2 arguments, 1 provided
Given my poor grasp on templates I can't really see what this error is trying to tell me, I have tried passing a direct string instead of a char array to no avail. Any help or explanation would be greatly appreciated, my heads worn a nice hole in the desk over the past few hours.
You declared the method taking 2 arguments:
ValueType getValueOfKey(const std::string &key, ValueType const &defaultValue) const;
// | |
// first parameter second parameter
and only supply one:
Config.getValueOfKey<std::string>("test");
I've yet to encounter a compiler that guesses what you mean without any help.
You'll need to move the default to the header file, where you declare the method:
ValueType getValueOfKey(const std::string &key, ValueType const &defaultValue = ValueType()) const;
// | |
// first parameter second parameter
You'll probably get a linker error afterwards, so you might want to check this.
Related
I have the following code. What I'm trying to do is implement a word count function similar to wc in unix. It takes a file as input and gives back the number of lines, words and characters in that file.
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
std::vector< std::string> split(std::istream& is, char delim){
std::vector<std::string> result;
std::string elem;
while(std::getline(is, elem, delim))
{
if(elem != "")
result.push_back(std::move(elem));
}
return result;
}
std::vector< std::string> split(const std::string& val, char delim){
std::stringstream is(val);
return split(is, delim);
}
struct WCResult {
std::string Name;
std::size_t LineCount;
std::size_t WordCount;
std::size_t ByteCount;
WCResult(const std::string& name = "", std::size_t lc = 0, std::size_t wc = 0, std::size_t bc = 0): Name(name), LineCount(lc), WordCount(wc), ByteCount(bc)
{}
void output(std::ostream& os)
{
os << this->LineCount << " " << this->WordCount << " " << this->ByteCount << " " << this->Name << std::endl;
}
};
WCResult getWordCount(const std::istream& is, const std::string& name){
std::stringstream is_str(is); //Error1: argument types are: (const std::istream)
std::vector<std::string> linecount = split(is_str, '\n');
std::vector<std::string> wordcount = split(is, ' '); //Error2: argument types are: const std::istream, char)
std::size_t bytecount = 0;
for(std::string str : wordcount){
bytecount += str.size();
}
return WCResult{name, linecount.size(), wordcount.size(), bytecount};
}
int main(int argc, char** argv){
std::vector<std::string> args(argv, argv + argc);
std::ifstream file(args[1]);
WCResult wc_result = getWordCount(file, args[1]);
wc_result.output(std::cout);
return 0;
}
I'm trying to pass my file either as a string or as an input stream. It does work for the function std::vector< std::string> split(const std::string& val, char delim).
Why am I getting the errors?
Error:
src/newwc.cpp:45:48: error: binding reference of type ‘std::istream&’ {aka ‘std::basic_istream<char>&’} to ‘const istream’ {aka ‘const std::basic_istream<char>’} discards qualifiers
45 | std::vector<std::string> wordcount = split(is, ' ');
| ^~
src/newwc.cpp:7:46: note: initializing argument 1 of ‘std::vector<std::__cxx11::basic_string<char> > split(std::istream&, char)’
7 | std::vector<std::string> split(std::istream& is, char delim)
This is the only error i get when i compile, but the I also get another error in the IDE, which seems not to get caught when compiling.
I'm unable to figure out why the output I received isn't just "00110" but has other giberrish characters in it. Not sure what's wrong with my vector push_back.. It definitely makes sense to me. If I changed it to std::string implementation, it would give a correct output. But in this case, I would need to use vector for proper encapsulation of the object's state. I've been debugging for a few hours now, but still can't find out why. Hope anyone is able to help! Thanks! Note: main() can't be modified.
#include <iostream>
#include <vector>
template<size_t NumBits>
class bitsetts
{
private:
static const unsigned int NO_OF_BITS = CHAR_BIT * sizeof(int); //32 bits
static const unsigned NumBytes = (NumBits - 7) /8;
unsigned char array[NumBytes];
public:
bitsetts() { }
void set(size_t bit, bool val = true) {
if (val == true)
{
array[bit] |= (val << bit );
}
else
{
array[bit] &= (val << bit );
}
}
bool test(size_t bit) const {
return array[bit] & (1U << bit );
}
const std::string to_string()
{
std::vector<char> str;
for (unsigned int i=NumBits; i-- > 0;)
str.push_back('0' + test(i));
return str.data();
}
friend std::ostream& operator<<(std::ostream& os, const bitsetts& ob)
{
for (unsigned i = NumBits; i-- > 0;)
os << ob.test(i);
return os << '\n';
}
};
int main()
{
try
{
bitsetts<5> bitsetts;
bitsetts.set(1);
bitsetts.set(2);
const std::string st = bitsetts.to_string();
if (st != "00110")
{
std::cout << st << std::endl;
throw std::runtime_error{ "-" };
}
}
catch (const std::exception& exception)
{
std::cout << "Conversion failed\n";
}
}
You are filling the std::vector with char values and then constructing a std::string from the raw char data using the std::string constructor that takes a single const char* parameter. That constructor expects the char data to be null-terminated, but you are not pushing a null terminator into your vector, which is why you get extra garbage on the end of your std::string.
So, either push a null terminator into the vector, eg:
const std::string to_string()
{
std::vector<char> str;
for (unsigned int i=NumBits; i-- > 0;)
str.push_back('0' + test(i));
str.push_back('\0'); // <-- add this!
return str.data();
}
Or, use a different std::string constructor that can take the vector's size() as a parameter, eg:
const std::string to_string()
{
std::vector<char> str;
for (unsigned int i=NumBits; i-- > 0;)
str.push_back('0' + test(i));
return std::string(str.data(), str.size()); // <-- add size()!
}
On a side note: your to_string() method should be marked as const, eg:
const std::string to_string() const
Which would then allow you to use to_string() inside of your operator<<, eg:
friend std::ostream& operator<<(std::ostream& os, const bitsetts& b)
{
return os << b.to_string() << '\n';
}
Good afternoon everyone,
Firstly, thank you for taking your time into inputting and helping me understand my problem. I will disclose that this is a Assignment problem so i would like to understand it rather than be given the full code.
As per the title of the question, I am trying to design a program for my assignment. I have included the information below.
Write a program to manage DVD rental in a video rental store. Create
an abstract data type that represents a DVD in this store. Consider all
the data and operations that may be necessary for the DVD type to
work well within a rental management system. Include a print()
member function that displays all the information about the DVD. Test
your data type by creating an array of ten DVD instances and filling
them using information read from a test input file that you create.
Display the DVD information.
Here is what i have so far:
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
int main()
{
string mArrayO[10]; //create array of 10 string objects
string filename = "testfile.txt";
ifstream file(filename.c_str()); //// open file constructor because the constructor for an ifstream takes a const char*, not a string in pre C++11
// go through array till index 10
for( int x=0; x< 10; x++)
{
getline(file, mArrayO[x]); //get line and store into array
cout << "Line "<< x<<":"<< mArrayO[x]<<endl; //display
}
return 0;
}
So far my output is :
Line:0 Lord of the rings|2005|Fantasy|126 minutes|PG-13
Line:1 Titanic|1997|Romance|104 minutes|R
Line:2 Shawshank Redemption|1993|Drama|120 minutes|R
Line:3 The Lion King|1987|Cartoon|84 minutes|PG-10
Line:4 The God Father|1988|Violence|146 minutes|R
Line:5 Bruce Almighty|2009|Comedy|78 minutes|R
Line:6 Spiderman|2006|Action|84 minutes|PG-13
Line:7 Finding Nemo|2007|Cartoon|87 minutes|E
Line:8 The Martian|2015|SciFi|104 minutes|PG-13
Line:9 Insidious 3|2015|Horror|97 minutes|R
So as you can see i have put the data into one array. Now here is what i am trying to do. I want to be able to parse through this data and feed it into my DVD class. Specifically as my question outlines I want to be able to put all the movie names in one array, dates in another and so on until every data set is matched.Once that is done i want to be able to prompt the user to pick an option and from there have the corresponding function occur.
I also have made the following template for my DVD class:
class movie
{
public:
/// These are our methods to get the information
string getMovieName()
{
return moviename;
}
string getYear()
{
return year;
}
string getGenre()
{
return genre;
}
string getTime()
{
return time;
}
string getRating()
{
return rating;
}
private: // these are the members of this class. They will store all the information we need for this class
string moviename;
string year;
string genre;
string time;
string rating;
};
Here is another portion of my code. I have put it here incase people needed to see if i have attempted
bool done= false; // Client wants to continue.
while (!done)
{
cout<< "This is a test";
cin.ignore();
done=ask_to_continue();
}
//finish
cout<< "Thank you for using the DVD rental management system";
return 0;
bool ask_to_continue()
{
char again; //using keystroke
cout << "Do you need more help? Y or N? " << endl;
cin >> again;
if(again == 'n')
return true; // Exit program
return false; // Still using program
}
You have successfully read in the data from your text file and populated your array of strings. Now what you need to do is to write a parsing function that will parse each string or line in your array. Then while parsing each line you will then need to save each content into your class.
I can offer you a generic function that will parse strings for you provided that you are using the same delimiter; it is encapsulated in a Utility class as a static method along with a few other useful string manipulation functions.
Utility.h
#ifndef UTILITY_H
#define UTILITY_H
class Utility {
public:
static void pressAnyKeyToQuit();
static std::string toUpper( const std::string& str );
static std::string toLower( const std::string& str );
static std::string trim( const std::string& str, const std::string elementsToTrim = " \t\n\r" );
static unsigned convertToUnsigned( const std::string& str );
static int convertToInt( const std::string& str );
static float convertToFloat( const std::string& str );
static std::vector<std::string> splitString( const std::string& strStringToSplit, const std::string& strDelimiter, const bool keepEmpty = true );
private:
Utility(); // Private - Not A Class Object
Utility( const Utility& c ); // Not Implemented
Utility& operator=( const Utility& c ); // Not Implemented
template<typename T>
static bool stringToValue( const std::string& str, T* pValue, unsigned uNumValues );
template<typename T>
static T getValue( const std::string& str, std::size_t& remainder );
}; // Utility
#include "Utility.inl"
#endif // UTILITY_H
Utility.inl
// stringToValue()
template<typename T>
static bool Utility::stringToValue(const std::string& str, T* pValue, unsigned uNumValues) {
int numCommas = std::count(str.begin(), str.end(), ',');
if (numCommas != uNumValues - 1) {
return false;
}
std::size_t remainder;
pValue[0] = getValue<T>(str, remainder);
if (uNumValues == 1) {
if (str.size() != remainder) {
return false;
}
}
else {
std::size_t offset = remainder;
if (str.at(offset) != ',') {
return false;
}
unsigned uLastIdx = uNumValues - 1;
for (unsigned u = 1; u < uNumValues; ++u) {
pValue[u] = getValue<T>(str.substr(++offset), remainder);
offset += remainder;
if ((u < uLastIdx && str.at(offset) != ',') ||
(u == uLastIdx && offset != str.size()))
{
return false;
}
}
}
return true;
} // stringToValue
Utility.cpp
#include "stdafx.h"
#include "Utility.h"
// pressAnyKeyToQuit()
void Utility::pressAnyKeyToQuit() {
std::cout << "Press any key to quit" << std::endl;
_getch();
} // pressAnyKeyToQuit
// toUpper()
std::string Utility::toUpper(const std::string& str) {
std::string result = str;
std::transform(str.begin(), str.end(), result.begin(), ::toupper);
return result;
} // toUpper
// toLower()
std::string Utility::toLower(const std::string& str) {
std::string result = str;
std::transform(str.begin(), str.end(), result.begin(), ::tolower);
return result;
} // toLower
// trim()
// Removes Elements To Trim From Left And Right Side Of The str
std::string Utility::trim(const std::string& str, const std::string elementsToTrim) {
std::basic_string<char>::size_type firstIndex = str.find_first_not_of(elementsToTrim);
if (firstIndex == std::string::npos) {
return std::string(); // Nothing Left
}
std::basic_string<char>::size_type lastIndex = str.find_last_not_of(elementsToTrim);
return str.substr(firstIndex, lastIndex - firstIndex + 1);
} // trim
// getValue()
template<>
float Utility::getValue(const std::string& str, std::size_t& remainder) {
return std::stof(str, &remainder);
} // getValue <float>
// getValue()
template<>
int Utility::getValue(const std::string& str, std::size_t& remainder) {
return std::stoi(str, &remainder);
} // getValue <int>
// getValue()
template<>
unsigned Utility::getValue(const std::string& str, std::size_t& remainder) {
return std::stoul(str, &remainder);
} // getValue <unsigned>
// convertToUnsigned()
unsigned Utility::convertToUnsigned(const std::string& str) {
unsigned u = 0;
if (!stringToValue(str, &u, 1)) {
std::ostringstream strStream;
strStream << __FUNCTION__ << " Bad conversion of [" << str << "] to unsigned";
throw strStream.str();
}
return u;
} // convertToUnsigned
// convertToInt()
int Utility::convertToInt(const std::string& str) {
int i = 0;
if (!stringToValue(str, &i, 1)) {
std::ostringstream strStream;
strStream << __FUNCTION__ << " Bad conversion of [" << str << "] to int";
throw strStream.str();
}
return i;
} // convertToInt
// convertToFloat()
float Utility::convertToFloat(const std::string& str) {
float f = 0;
if (!stringToValue(str, &f, 1)) {
std::ostringstream strStream;
strStream << __FUNCTION__ << " Bad conversion of [" << str << "] to float";
throw strStream.str();
}
return f;
} // convertToFloat
// splitString()
std::vector<std::string> Utility::splitString( const std::string& strStringToSplit, const std::string& strDelimiter, const bool keepEmpty ) {
std::vector<std::string> vResult;
if ( strDelimiter.empty() ) {
vResult.push_back( strStringToSplit );
return vResult;
}
std::string::const_iterator itSubStrStart = strStringToSplit.begin(), itSubStrEnd;
while ( true ) {
itSubStrEnd = search( itSubStrStart, strStringToSplit.end(), strDelimiter.begin(), strDelimiter.end() );
std::string strTemp( itSubStrStart, itSubStrEnd );
if ( keepEmpty || !strTemp.empty() ) {
vResult.push_back( strTemp );
}
if ( itSubStrEnd == strStringToSplit.end() ) {
break;
}
itSubStrStart = itSubStrEnd + strDelimiter.size();
}
return vResult;
} // splitString
The includes required for this class that are found in stdafx.h are: vector, string, conio.h, and maybe tchar.h and I also use this enum for main's return values which is also found in stdafx.h
enum ReturnCode {
RETURN_OK = 0,
RETURN_ERROR = 1,
}; // ReturnCode
As for your Movie class you have defined your functions to retrieve data, but you have not shown that you have defined any setting methods nor constructors. Also your getters should be declared as const functions since these functions will not change the data stored in your class object. Your class should look as such:
Movie.h
#ifndef MOVIE_H
#define MOVIE_H
class Movie {
private:
std::string m_strTitle;
std::string m_strYear;
std::string m_strGenre;
std::string m_strLength;
std::string m_Rating;
public:
Movie(); // Default Constructor
Movie( const std::string& strTitle, const std::string& strYear, const std::string& strGenre,
const std::string& strLength, const std::string& strRating();
std::string getTitle() const;
std::string getYear() const;
std::string getGenre() const;
std::string getLength() const;
std::string getRating() const;
void setTitle( const std::string& strTile );
void setYear( const std::string& strYear );
void setGenre( const std::string& strGenre );
void setLength( const std::string& strLength );
void setRating( const std::string& strRating );
private:
Movie( const Movie& c ); // Not Implemented
Movie& operator=( const Movie& c ); // Not Implemented
}; // Movie
#endif // MOVIE_H
Movie.cpp
#include "stdafx.h"
#include "Movie.h"
// Movie()
Movie::Movie() {
} // Movie
// Movie()
Movie::Movie( const std::string& strTitle, const std::string& strYear, const std::string& strGenre,
const std::string& strLength, const std::string& strRating ) :
m_strTitle( strTitle ),
m_strYear( strYear ),
m_strGenre( strGenre ),
m_strLength( strLength ),
m_strRating( strRating ) {
} // Movie
// getTitle()
std::string Movie::getTitle() const {
return m_strTitle;
} // getTitle
// getYear()
std::string Movie::getYear() const {
return m_strYear;
} // getYear
// getGenre()
std::string Movie::getGenre() const {
return m_strGenre;
} // GetGenre
// getLength()
std::string Movie::getLength() const {
return m_strLength;
} // getLength
// getRating()
std::string Movie::getRating() const {
return m_strRating;
} // getRating
// setTitle()
void Movie::setTitle( const std::string& strTile ) {
m_strTitle = strTile;
} // setTitle
// setYear()
void Movie::setYear( const std::string& strYear ) {
m_strYear = strYear;
} // setYear
// setGenre()
void Movie::setGenre( const std::string& strGenre ) {
m_strGenre = strGenre;
} // setGenre
// setLength()
void Movie::setLength( const std::string& strLength ) {
m_strLength = strLength;
} // setLength
// setRating()
void Movie::setRating( const std::string& strRating ) {
m_strRating = strRating;
} // setRating
Now as for parsing your string the function of use in the Utility class is Utility::splitString() You will need to go through a for loop for as many entries as there are in your array and for each pass you will have to parse that string then construct a Movie object either by using its default constructor then populating each member or by constructing the object with the appropriate constructor. I will show you an example of how to use the splitString() function.
main.cpp
#include "stdafx.h"
#include "Utility.h"
#include "Movie.h"
int main() {
std::string test( "Hello World How Are You Today" );
std::vector<std::string>> vResults;
vResults = Utility::splitString( test, " " );
Utility::pressAnyKeyToQuit();
return RETURN_OK;
} // main
Here splitString will take as its first parameter the string that you want to parse, as its second parameter the delimiting string or char as in your case it would be the "|" character and it will save the results into a vector of strings. From here on each pass of your for loop then it is just a matter of constructing your Movie objects while assigning them the appropriate values.
To split a string, use the find or find_first_of function from std::string to get the positions of the delimiters. Then use substr to get the substrings between these delimiters.
I have just started learning c++ and I was thinking is their any way of splitting strings. Lemme make it more clear.
Suppose user enters the string, date of birth in the following format dd-mm-yy. Now I wish to store the date, month and year in 3 different variables. So how do I go about ??
P.S : I googled a bit and found that this can be accomplished using the boot::regex. But still, I was wondering if there was any easier way of doing the same. Being a beginner hampers me. :P
Anyways, Any help would be appreciated.
To Brief:
I want something like this.
Enter date: //Accept the date
22-3-17 //Input by user
Date : 22 //Output
Month: 3 //Output
Year : 17 //Output
You can use sscanf function:
http://en.cppreference.com/w/cpp/io/c/fscanf
#include <iostream>
#include <string>
using namespace std;
int main(int argc, const char * argv[]) {
string date;
cin>>date;
int day, month, year;
sscanf(date.c_str(), "%d-%d-%d", &day, &month, &year);
cout << day << ' ' << month << ' ' << year;
return 0;
}
There are different methods you could do this. For the 'easiest' way I would suggest using std::string::find() methods( http://www.cplusplus.com/reference/string/string/find/) in combination with std::string::substr() method (http://www.cplusplus.com/reference/string/string/substr/)
For the use of regex you do not need boost: http://www.cplusplus.com/reference/regex/
You can use the operator [] to get the characters of the string.
http://www.cplusplus.com/reference/string/string/operator[]/
Here is a full working program that has been compiled, built and successfully ran on an Intel Core 2 Quad Extreme running Windows 7 64-bit using Visual Studio 2015 Community edition that has retrieved the information the OP had asked for in a particular format, parsed the string of information or data appropriately, and displayed the results in the requested or required format.
stdafx.h
#ifndef STDAFX_H
#define STDAFX_H
#include <vector>
#include <algorithm>
#include <iterator>
#include <tchar.h>
#include <conio.h>
#include <string>
#include <iostream>
#include <iomanip>
enum ReturnCode {
RETURN_OK = 0,
RETURN_ERROR = 1,
}; // ReturnCode
#endif // STDAFX_H
stdafx.cpp
#include "stdafx.h"
Utility.h
#ifndef UTILITY_H
#define UTILITY_H
class Utility {
public:
static void pressAnyKeyToQuit();
static std::string toUpper( const std::string& str );
static std::string toLower( const std::string& str );
static std::string trim( const std::string& str, const std::string elementsToTrim = " \t\n\r" );
static unsigned convertToUnsigned( const std::string& str );
static int convertToInt( const std::string& str );
static float convertToFloat( const std::string& str );
static std::vector<std::string> splitString( const std::string& strStringToSplit, const std::string& strDelimiter, const bool keepEmpty = true );
private:
Utility(); // Private - Not A Class Object
Utility( const Utility& c ); // Not Implemented
Utility& operator=( const Utility& c ); // Not Implemented
template<typename T>
static bool stringToValue( const std::string& str, T* pValue, unsigned uNumValues );
template<typename T>
static T getValue( const std::string& str, std::size_t& remainder );
}; // Utility
#include "Utility.inl"
#endif // UTILITY_H
Utility.inl
// ----------------------------------------------------------------------------
// stringToValue()
template<typename T>
static bool Utility::stringToValue(const std::string& str, T* pValue, unsigned uNumValues) {
int numCommas = std::count(str.begin(), str.end(), ',');
if (numCommas != uNumValues - 1) {
return false;
}
std::size_t remainder;
pValue[0] = getValue<T>(str, remainder);
if (uNumValues == 1) {
if (str.size() != remainder) {
return false;
}
}
else {
std::size_t offset = remainder;
if (str.at(offset) != ',') {
return false;
}
unsigned uLastIdx = uNumValues - 1;
for (unsigned u = 1; u < uNumValues; ++u) {
pValue[u] = getValue<T>(str.substr(++offset), remainder);
offset += remainder;
if ((u < uLastIdx && str.at(offset) != ',') ||
(u == uLastIdx && offset != str.size()))
{
return false;
}
}
}
return true;
} // stringToValue
Utility.cpp
#include "stdafx.h"
#include "Utility.h"
// ----------------------------------------------------------------------------
// pressAnyKeyToQuit()
void Utility::pressAnyKeyToQuit() {
std::cout << "Press any key to quit" << std::endl;
_getch();
} // pressAnyKeyToQuit
// ----------------------------------------------------------------------------
// toUpper()
std::string Utility::toUpper(const std::string& str) {
std::string result = str;
std::transform(str.begin(), str.end(), result.begin(), ::toupper);
return result;
} // toUpper
// ----------------------------------------------------------------------------
// toLower()
std::string Utility::toLower(const std::string& str) {
std::string result = str;
std::transform(str.begin(), str.end(), result.begin(), ::tolower);
return result;
} // toLower
// ----------------------------------------------------------------------------
// trim()
// Removes Elements To Trim From Left And Right Side Of The str
std::string Utility::trim(const std::string& str, const std::string elementsToTrim) {
std::basic_string<char>::size_type firstIndex = str.find_first_not_of(elementsToTrim);
if (firstIndex == std::string::npos) {
return std::string(); // Nothing Left
}
std::basic_string<char>::size_type lastIndex = str.find_last_not_of(elementsToTrim);
return str.substr(firstIndex, lastIndex - firstIndex + 1);
} // trim
// ----------------------------------------------------------------------------
// getValue()
template<>
float Utility::getValue(const std::string& str, std::size_t& remainder) {
return std::stof(str, &remainder);
} // getValue <float>
// ----------------------------------------------------------------------------
// getValue()
template<>
int Utility::getValue(const std::string& str, std::size_t& remainder) {
return std::stoi(str, &remainder);
} // getValue <int>
// ----------------------------------------------------------------------------
// getValue()
template<>
unsigned Utility::getValue(const std::string& str, std::size_t& remainder) {
return std::stoul(str, &remainder);
} // getValue <unsigned>
// ----------------------------------------------------------------------------
// convertToUnsigned()
unsigned Utility::convertToUnsigned(const std::string& str) {
unsigned u = 0;
if (!stringToValue(str, &u, 1)) {
std::ostringstream strStream;
strStream << __FUNCTION__ << " Bad conversion of [" << str << "] to unsigned";
throw strStream.str();
}
return u;
} // convertToUnsigned
// ----------------------------------------------------------------------------
// convertToInt()
int Utility::convertToInt(const std::string& str) {
int i = 0;
if (!stringToValue(str, &i, 1)) {
std::ostringstream strStream;
strStream << __FUNCTION__ << " Bad conversion of [" << str << "] to int";
throw strStream.str();
}
return i;
} // convertToInt
// ----------------------------------------------------------------------------
// convertToFloat()
float Utility::convertToFloat(const std::string& str) {
float f = 0;
if (!stringToValue(str, &f, 1)) {
std::ostringstream strStream;
strStream << __FUNCTION__ << " Bad conversion of [" << str << "] to float";
throw strStream.str();
}
return f;
} // convertToFloat
// ----------------------------------------------------------------------------
// splitString()
std::vector<std::string> Utility::splitString( const std::string& strStringToSplit, const std::string& strDelimiter, const bool keepEmpty ) {
std::vector<std::string> vResult;
if ( strDelimiter.empty() ) {
vResult.push_back( strStringToSplit );
return vResult;
}
std::string::const_iterator itSubStrStart = strStringToSplit.begin(), itSubStrEnd;
while ( true ) {
itSubStrEnd = search( itSubStrStart, strStringToSplit.end(), strDelimiter.begin(), strDelimiter.end() );
std::string strTemp( itSubStrStart, itSubStrEnd );
if ( keepEmpty || !strTemp.empty() ) {
vResult.push_back( strTemp );
}
if ( itSubStrEnd == strStringToSplit.end() ) {
break;
}
itSubStrStart = itSubStrEnd + strDelimiter.size();
}
return vResult;
} // splitString
main.cpp
#include "stdafx.h"
#include "Utility.h"
int main () {
std::string date;
std::cout << "Enter Date in DD-MM-YY Format.\n" << std::endl;
std::getline( std::cin, date );
std::vector<std::string> vResults = Utility::splitString( date, "-" );
std::cout << "\nDate : " << vResults[0] << std::endl
<< "Month: " << vResults[1] << std::endl
<< "Year : " << vResults[2] << std::endl << std::endl;
Utility::pressAnyKeyToQuit();
return 0;
} // main
I am new in C++.C++ function will work like below.
Look up file :
POST OFFICE,PO
SUITE ACCESS ROOM, SAR
SUITE,STE
STREET,ST
NEW YORK,NY
POST,PST
LONG LINE STREET,LLS
There will be one c++ function which should have one parameter like "ARIJIT, 192 POST OFFICE, SUITE" and it will give output like "ARIJIT, 192 PO, STE". it will use one static look up file like upper content.
I did below code structure but not finding in which direction to go..
#include <iostream>
#include <fstream>
#include <string>
int main()
{
char * processAddress (char *input );
char *input = "ARIJIT, 192 POST OFFICE, SUITE";
char *output = processAddress(input);
std::cout << output;
return 0;
}
char * processAddress (char *input ) {
char *output = input;
std::ifstream file("LookUp.csv");
std::string str;
while (std::getline(file, str))
{
std:: cout << str << '\n';
}
return output;
}
Problem I am facing
1. How to map look up file
2. Find and Replace
Thanks in advance.
Thanks Guys
I solved it below is the code .
#include <iostream>
#include <fstream>
#include <string>
#include <map>
int main()
{
std::string processAddress (std:: string input);
std::string input = "ARIJIT, 192 POST OFFICE, SUITE";
std::string output = processAddress(input);
std::cout << output << "\n";
return 0;
}
std::string processAddress (std:: string input) {
void replaceAll(std::string& str, const std::string& from, const std::string& to);
std::ifstream file("LookUp.csv");
std::string str;
typedef std::map<std::string, std::string> MyMap;
MyMap my_map;
while (std::getline(file, str))
{
std::string delimiter = ",";
std::string token1 = str.substr(0, str.find(delimiter));
std::string token2 = str.substr(token1.length()+1, str.find(delimiter));
my_map[token1] = token2;
}
// Map Enumeration
for( MyMap::const_iterator it = my_map.end(); it != my_map.begin(); --it )
{
std::string key = it->first;
std::string value = it->second;
// find and replace
replaceAll(input, key, value);
}
std::string output = input ;
return output;
}
bool replace(std::string& str, const std::string& from, const std::string& to) {
size_t start_pos = str.find(from);
if(start_pos == std::string::npos)
return false;
str.replace(start_pos, from.length(), to);
return true;
}
void replaceAll(std::string& str, const std::string& from, const std::string& to) {
if(from.empty())
return;
size_t start_pos = 0;
while((start_pos = str.find(from, start_pos)) != std::string::npos) {
str.replace(start_pos, from.length(), to);
start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
}
}
Assuming you've loaded the strings from the file, split on the comma, and stored them in an accessible manner, the replace call you're looking for should be something like this:
size_t pos = input.find(toReplace); // toReplace = "text to replace"
if (pos != std::string::npos) {
input.replace(pos, toReplace.length(), shorterString); // shorterString = "new text"
} else {
// Your "text to replace" doesn't exist in input
}