How do I use STL algorithms with ICU's iterators? - c++

I wonder how to use ICU library iterators with STL. For instance, what if we decided to output all permutations of a string?
With std::string it looks like the following:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
static void _usage(const char *executable)
{
cout << "Usage: " << executable << " <string>" << endl;
}
int main (int argc, char const* argv[]) {
if (argc < 2) {
cerr << "Target string expected" << endl;
_usage(argv[0]);
return 1;
}
string s(argv[1]);
do {
cout << s << endl;
} while (next_permutation(s.begin(), s.end()));
return 0;
}
I tried to do the same using ICU:
#include <unicode/unistr.h>
#include <unicode/uchriter.h>
#include <unicode/ustdio.h>
#include <algorithm>
#include <string>
#include <iostream>
using namespace std;
static void _usage(const char *executable)
{
cout << "Usage: " << executable << " <string>" << endl;
}
int main (int argc, char const* argv[]) {
if (argc < 2) {
cerr << "Target string expected" << endl;
_usage(argv[0]);
return 1;
}
UnicodeString ustr(argv[1]);
UChar *uc = ustr.getBuffer(-1);
int32_t len = u_strlen(uc);
UCharCharacterIterator iter_start(uc, len);
UCharCharacterIterator iter_end(uc, len, len - 1);
do {
// XXX
} while (next_permutation(iter_start, iter_end ));
return 0;
}
But it fails to compile:
x86_64-pc-linux-gnu-g++ -I/usr/include -licuio -licui18n -licuuc -licudata permute2.C -o permute2
In file included from /usr/lib/gcc/x86_64-pc-linux-gnu/4.5.4/include/g++-v4/algorithm:63:0,
from permute2.C:4:
/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.4/include/g++-v4/bits/stl_algo.h: In function ‘bool std::next_permutation(_BIter, _BIter) [with _BIter = icu_49::
UCharCharacterIterator]’:
permute2.C:31:49: instantiated from here
/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.4/include/g++-v4/bits/stl_algo.h:3531:7: error: no match for ‘operator++’ in ‘++__i’
/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.4/include/g++-v4/bits/stl_algo.h:3535:7: error: no match for ‘operator--’ in ‘--__i’
/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.4/include/g++-v4/bits/stl_algo.h:3540:4: error: no match for ‘operator--’ in ‘--__i’
/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.4/include/g++-v4/bits/stl_algo.h:3541:4: error: no match for ‘operator*’ in ‘*__ii’
/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.4/include/g++-v4/bits/stl_algo.h:3541:4: error: no match for ‘operator*’ in ‘*__i’
/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.4/include/g++-v4/bits/stl_algo.h:3544:8: error: no match for ‘operator--’ in ‘--__j’
/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.4/include/g++-v4/bits/stl_algo.h:3544:8: error: no match for ‘operator*’ in ‘*__i’
...
What's the proper way to make use of STL with ICU? Extend the UCharCharacterIterator class and provide code for all these operators?

Related

Is there any alternative to using if walls instead of something else in C++?

I'm doing some C++ and my app accepts subcommands, for example ./my_app test 123.
I'm semi-new to C++ and I can't find anything on the internet so I don't know haha.
For example in python I'd do:
#!/usr/bin/env python3
import sys
def test(num):
print(f"Test {num}")
subcommands = {"test": test}
subcommands[sys.argv[1](sys.argv[2])
any C++ eq to this? if so, should I use it or stick to if-else_if-else?
Have a look at std::map/std::unordered_map, for example:
#include <iostream>
#include <map>
#include <string>
void test(const std::string &value) {
std::cout << "Test " << value << std::endl;
}
using cmdFuncType = void(*)(const std::string &);
const std::map<std::string, cmdFuncType> subcommands = {
{"test": &test}
};
int main(int argc, char* argv[]) {
if (argc != 3) {
std::cerr << "usage: program command value" << std::endl;
return 0;
}
auto iter = subcommands.find(argv[1]);
if (iter == subcommands.end()) {
std::cerr << "unknown command: " << argv[1] << std::endl;
return 0;
}
iter->second(argv[2]);
return 0;
}
Is this what you are trying to achieve:
#include <string>
#include <functional>
#include <iostream>
#include <map>
void test(int num) {
std::cout << "Test " << num << "\n";
}
std::map<std::string, std::function<void(int)>> subcommands = {
{"test", test}
};
int main(int argc, char* argv[]) {
subcommands[argv[1]](std::atoi(argv[2]));
}

when I use the c++ STL sort function in string sort,there is some problem

C++ code
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <fstream>
using namespace std;
int
main ()
{
vector < string > elem (4);
ifstream infile ("test.txt");
if (!infile)
{
cerr << "Oops! unable to save session data !\n";
}
int i;
for (i = 0; infile >> elem[i]; i++);
for (i = 0; i < 4; i++)
{
cout << elem[i] << ' ';
}
cout << "\nThe result after sorting\n";
sort (elem, elem + 4);
for (i = 0; i < 4; i++)
{
cout << elem[i] << ' ';
}
cout << endl;
return 0;
}
THis is my full code,when I run,there is some problem
main.cpp: In function ‘int main()’:
main.cpp:24:20: error: no match
for ‘operator+’ (operand types are ‘std::vector >’ and ‘int’) sort
(elem, elem + x);
~~~~~^~~
Your usage of std::sort is C-ish. You have to supply iterators to begin/end, i.e., write something like
sort(elem.begin(), elem.end());
Besides, your program will crash if the test.txt file is more than 4 lines (trying to read into non-existent elem[4]).
Be careful though, check that the default comparison does what you want. Here it does.

Requesting a function from another file in a class not working

I have 2 .cpp files called "FactoringProgram.cpp" and "FactoringProgram2nd.cpp", also 1 header file called "FactoringProgram.h". I've already tried searching for this problem on StackOverflow and a couple other sites and haven't found a solution that worked for me. When I try to run this command: "g++ FactoringProgram.cpp FactoringProgram2nd.cpp" I get this error:
FactoringProgram.cpp: In function ‘int main()’: FactoringProgram.cpp:8:11: error: request for member ‘InitialMessage’
in ‘Problem1’, which is of non-class type ‘Factoring()’
Problem1.InitialMessage();
The code for "FactoringProgram.h" is:
#ifndef FactoringProgram_h
#define FactoringProgram_h
#include <stdio.h>
#include <iostream>
class Factoring
{
private:
int m_FirstCoefficent;
char m_FirstOperator;
int m_SecondCoefficent;
char m_SecondOperator;
int m_3rdExpression;
public:
Factoring();
int InitialMessage();
};
#endif
FactoringProgram.cpp code:
#include <stdio.h>
#include <iostream>
#include "FactoringProgramH.h"
int main()
{
Factoring Problem1();
Problem1.InitialMessage();
return 0;
}
FactoringProgram2nd.cpp code:
#include "FactoringProgramH.h"
#include <stdio.h>
#include <iostream>
Factoring::Factoring(int FirstCoefficent=0, char FirstOperator='+',
int SecondCoefficent=1, char SecondOperator='+', int 3rdExpression=1)
: m_FirstCoefficent(FirstCoefficen), m_FirstOperator(FirstOperator),
m_SecondCoefficent(SecondCoefficent), m_SecondOperator(SecondOperator),
m_3rdExpression(3rdExpression);
{
}
int Factoring::InitialMessage()
{
std::cout << "Ok right now your expression is looking like: "
<< FirstCoefficent << "x^2 " << FirstOperator << " " << SecondCoefficent
<< " x" << SecondOperator << " " << 3rdExpression;
}
Your code has several small errors. Here is a version that works (you can compare and see what I had to change). A summary of the changes are:
default parameter values should be in the header file (*.h);
you cannot start variable/argument names with numbers;
int InitialMessage() doesn't return anything, so I changed it to void InitialMessage();
when you initialize fields in a constructor, the last field cannot end with a semi-colon;
fixed the most vexing parsing (per #RSahu comment) in main.cpp.
FactoringProgram.h
#ifndef FactoringProgram_h
#define FactoringProgram_h
#include <stdio.h>
#include <iostream>
class Factoring
{
private:
int m_FirstCoefficent;
char m_FirstOperator;
int m_SecondCoefficent;
char m_SecondOperator;
int m_3rdExpression;
public:
Factoring(int FirstCoefficent = 0, char FirstOperator = '+',
int SecondCoefficent = 1, char SecondOperator = '+', int thirdExpression = 1);
void InitialMessage();
};
#endif
FactoringProgram.cpp
#include "FactoringProgram.h"
Factoring::Factoring(int firstCoefficent, char firstOperator, int SecondCoefficent, char SecondOperator, int thirdExpression) :
m_FirstCoefficent(firstCoefficent),
m_FirstOperator(firstOperator),
m_SecondCoefficent(SecondCoefficent),
m_SecondOperator(SecondOperator),
m_3rdExpression(thirdExpression)
{}
void Factoring::InitialMessage()
{
std::cout << "Ok right now your expression is looking like: "
<< m_FirstCoefficent << "x^2 " << m_FirstOperator << " " << m_SecondCoefficent
<< " x" << m_SecondOperator << " " << m_3rdExpression;
}
main.cpp
#include <stdio.h>
#include <iostream>
#include "FactoringProgram.h"
int main()
{
Factoring Problem1;
Problem1.InitialMessage();
return 0;
}
To this error substitute:
Factoring Problem1();
by:
Factoring Problem1 = Factoring();
The problem is that the compiler is interpreting this line as a function declaration rather than a variable declaration. AS mentioned in the comments, this is known as the most vexing parser problem.
Obs: The code you posted contain many more minor errors.
You should define Factoring() without params and I used headers in FactoringProgram.h
FactoringProgram.h
#include <stdio.h>
#include <iostream>
class Factoring
{
private:
int m_FirstCoefficent;
char m_FirstOperator;
int m_SecondCoefficent;
char m_SecondOperator;
int m_3rdExpression;
public:
Factoring();
Factoring(int,char,int,char,int);
int InitialMessage();
};
#endif
FactoringProgram.cpp
#include "FactoringProgram.h"
int main()
{
Factoring Problem1 = Factoring();
Problem1.InitialMessage();
system("pause");
return 0;
}
FactoringProgram2nd.cpp
#include "FactoringProgram.h"
Factoring::Factoring()
{
*this = Factoring(0, '+', 1, '+', 1);
}
Factoring::Factoring(int FirstCoefficent = 0, char FirstOperator = '+',int SecondCoefficent = 1, char SecondOperator = '+', int _3rdExpression = 1) : m_FirstCoefficent(FirstCoefficent), m_FirstOperator(FirstOperator),m_SecondCoefficent(SecondCoefficent), m_SecondOperator(SecondOperator),m_3rdExpression(_3rdExpression)
{
}
int Factoring::InitialMessage()
{
std::cout << "Ok right now your expression is looking like: "
<< m_FirstCoefficent << "x^2 " << m_FirstOperator << " " << m_SecondCoefficent
<< " x" << m_SecondOperator << " " << m_3rdExpression;
return 0;
}

How compare char str[MAXCHAR] with a string?

I want compare if both sequence are equals and i'm using the following code but comparation always return false.
=========================================================================
// testecompare.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <string>
#include <iostream>
#include <fstream>
#include <Windows.h>
using namespace std;
string getCurrentDirectoryOnWindows()
{
const unsigned long maxDir = 260;
char currentDir[maxDir];
GetCurrentDirectory(maxDir, currentDir);
strcat(currentDir, "\\l0gs.txt");
return string(currentDir);
}
string ReadFileContent() {
string STRING;
string aux;
ifstream infile;
infile.open(getCurrentDirectoryOnWindows());
while (!infile.eof())
{
getline(infile, STRING);
return STRING;
}
infile.close();
return "";
}
int _tmain(int argc, _TCHAR* argv[])
{
char str[MAXCHAR] = "";
sprintf(str, "0x0%X", "1D203E5");
cout << str << endl;
cout << "File content: " << ReadFileContent() << endl;
// if i have the string "0x01D203E5" in my txt file
if (_stricmp(str,ReadFileContent().c_str()) == 0) {
cout << "Contents are equals!\n";
}
system("pause");
return 0;
}
How make this comparation correctly?
Thank you very much.
An easy trick for comparing instances of different types is to convert them to a common type then compare.
So for example:
std::string content(ReadFileContent());
std::string from_array(str)
if (from_array == content)
{
}
Edit 1: Working example
The code works.
Here is a working program:
#include <iostream>
#include <string>
int main()
{
static const char text[] = "Hello";
std::string text_as_string(text);
std::string expected_str("Hello");
if (text_as_string == expected_str)
{
std::cout << "Strings are equal: " << text_as_string << "\n";
}
else
{
std::cout << "Strings are not equal.\n";
}
return 0;
}
$ g++ -o main.exe main.cpp
$ ./main.exe
Strings are equal: Hello
Remember, the above code samples are compare entire or whole strings, not substrings. If you want to search for a key string within a larger string, that requires different functions.

Lexical cast Partial conversion - Is it possible?

lexical_cast throws an exception in the following case. Is there a way to use lexical_cast and convert the string to integer.
#include <iostream>
#include "boost/lexical_cast.hpp"
#include <string>
int main()
{
std::string src = "124is";
int iNumber = boost::lexical_cast<int>(src);
std::cout << "After conversion " << iNumber << std::endl;
}
I understand, I can use atoi instead of boost::lexical_cast.
If I'm understanding your requirements correctly it seems as though removing the non-numeric elements from the string first before the lexical_cast will solve your problem. The approach I outline here makes use of the isdigit function which will return true if the given char is a digit from 0 to 9.
#include <iostream>
#include "boost/lexical_cast.hpp"
#include <string>
#include <algorithm>
#include <cctype> //for isdigit
struct is_not_digit{
bool operator()(char a) { return !isdigit(a); }
};
int main()
{
std::string src = "124is";
src.erase(std::remove_if(src.begin(),src.end(),is_not_digit()),src.end());
int iNumber = boost::lexical_cast<int>(src);
std::cout << "After conversion " << iNumber << std::endl;
}
The boost/lexical_cast uses stringstream to convert from string to other types,so you must make sure the string can be converted completely! or, it will throw the bad_lexical_cast exception,This is an example:
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <string>
#define ERROR_LEXICAL_CAST 1
int main()
{
using boost::lexical_cast;
int a = 0;
double b = 0.0;
std::string s = "";
int e = 0;
try
{
// ----- string --> int
a = lexical_cast<int>("123");//good
b = lexical_cast<double>("123.12");//good
// -----double to string good
s = lexical_cast<std::string>("123456.7");
// ----- bad
e = lexical_cast<int>("abc");
}
catch(boost::bad_lexical_cast& e)
{
// bad lexical cast: source type value could not be interpreted as target
std::cout << e.what() << std::endl;
return ERROR_LEXICAL_CAST;
}
std::cout << a << std::endl; // cout:123
std::cout << b << std::endl; //cout:123.12
std::cout << s << std::endl; //cout:123456.7
return 0;
}