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
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]));
}
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.
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;
}
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 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;
}