What is the easiest/optimal way to transform AnsiString into Cyrillic using C++ STL!
in php it would be
<?php
// функция превода текста с кириллицы в траскрипт
function encodestring($st)
{
// Сначала заменяем "односимвольные" фонемы.
$st=strtr($st,"абвгдеёзийклмнопрстуфхъыэ_",
"abvgdeeziyklmnoprstufh'iei");
$st=strtr($st,"АБВГДЕЁЗИЙКЛМНОПРСТУФХЪЫЭ_",
"ABVGDEEZIYKLMNOPRSTUFH'IEI");
// Затем - "многосимвольные".
$st=strtr($st,
array(
"ж"=>"zh", "ц"=>"ts", "ч"=>"ch", "ш"=>"sh",
"щ"=>"shch","ь"=>"", "ю"=>"yu", "я"=>"ya",
"Ж"=>"ZH", "Ц"=>"TS", "Ч"=>"CH", "Ш"=>"SH",
"Щ"=>"SHCH","Ь"=>"", "Ю"=>"YU", "Я"=>"YA",
"ї"=>"i", "Ї"=>"Yi", "є"=>"ie", "Є"=>"Ye"
)
);
// Возвращаем результат.
return $st;
}
?>
I prefer to use STL Containers, need help!
You may use the same code style in C++ also. Look to the std::map container. In newest standard C++11 you are also able to initialize it in a very convinient manner:
map letters =
{{ "f", "ф"},
{ "h", "х"},
//and so on
};
Finally I wrote my own func and it works well! I think it'll get my job done but not so optimized! Tried to use map.find() smth like this but .....
AnsiString Latin2Cyr(AnsiString inStr)
{
int l=inStr.Length();
if (!l) return "";
AnsiString strLat[]={"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"};
AnsiString strCyr[]={"а","б","с","д","е","ф","г","х","и","дж","к","л","м","н","о","п","к","р","с","т","у","в","у","кс","й","з"};
AnsiString outStr="";
typedef multimap<AnsiString,AnsiString> mmp;
mmp mStr;
int ln=(sizeof(strLat))/(sizeof(AnsiString));
for (int i = 0; i < ln; i++) mStr.insert(mmp::value_type(strLat[i],strCyr[i]));
AnsiString k=""; mmp::iterator it;
for (int j = 1; j <l+1; j++) {
for ( it=mStr.begin(); it!= mStr.end();++it ){
outStr+=((*it).first==inStr.SubString(j,1))? (*it).second : k ;
}
}
return outStr;
}
any ideas to optimize it?
Related
I am writing an Objective-C wrapper for a C++ class. On the OC side I have to take an NSData (read from a json file) get a list out from it and convert that to std::vector< std::string >. Here is my code so far (in an mm file):
NSData *input = [NSData dataWithContentsOfFile:[NSString stringWithUTF8String:"1455469592904_acceldata742283.json"]];
NSError* error;
NSDictionary* jsonArray = [NSJSONSerialization JSONObjectWithData:input options:NSJSONReadingMutableContainers error:&error];
NSMutableArray *accdata = [jsonArray valueForKeyPath:#"data.accelerometer" ];
int size = [accdata count];
vector<string> cppAccdata;
for (int i = 0; i< size; i++){
//~ cppAccdata.push_back();
NSLog(#"%#",[accdata objectAtIndex:i]);
}
The accdata speaking loosely is a list of strings. The json file basically looks like this (with more lines but that's beside the point):
{
"data" : {
"accelerometer" : [
"1455463005.714 -8.311620700836182 -3.969735990142822 -3.737648066711425",
"1455463005.724 -8.256703700256347 -4.017769660949707 -3.680336864471435" ] }}
The output of the code is:
2016-02-15 14:18:16.212 test-OC[10300] 1455463066.241 -7.960421244812011 -4.400093738555908 -3.746177410125732
2016-02-15 14:18:16.212 test-OC[10300] 1455463066.261 -8.019677735900878 -4.377498460388184 -3.634847032928467
2016-02-15 14:18:16.212 test-OC[10300] GSCBufferString
Technically I need to convert [accdata objectAtIndex:i] to an std::string, which I guess would work through a C const char *, but I have not been able to find anything on converting a GSCBufferString into anything. How can I achieve this? There also might be a more elegant way to loop through accdata.
NSArray *accdata = [jsonArray valueForKeyPath:#"data.accelerometer" ];
vector<string> cppAccdata;
for (NSString *str in accdata) {
cppAccdata.push_back(str.UTF8String);
}
Try this:
NSArray *jsonArray;
NSArray *accData = [jsonArray valueForKeyPath:#"data.accelerometer"];
vector<string> cppAccdata;
for (NSString *str in accData){
std::string *accString = new std::string([str UTF8String]);
cppAccdata.push_back(*accString);
}
The two answer proposed were correct in the way of doing the conversion, but the loop syntax didn't compile. This workaround works though:
int size = [accdata count];
vector<string> cppAccdata;
for (int i = 0; i< size; i++){
cppAccdata.push_back([[accdata objectAtIndex:i] UTF8String]);
}
enum { WOOD, BRICK, GRAIN, HEMP, WOOL, RAWMETAL, HONEY, SALT, METALGOODS, MEAD, CLOTH, BEER, STOCKFISH, CLOTHING, CHEESE, PITCH, PELTS, MEAT, WINE, SPICES, TOTALRESOURCES };
// An array of strings for each of the resource names
// As long as these are in the same order as the enum everything should match up
// .: resName[PIGIRON] is "Pig Iron"
string resName[]{ "Wood", "Brick", "Grain", "Hemp", "Wool", "Raw Metal", "Honey", "Salt", "Metal Goods", "Mead", "Cloth", "Beer", "Stockfish", "Clothing", "Cheese", "Pitch", "Pelts", "Meat", "Wine", "Spices" };
enum { Edinburgh, Scarborough, Boston, London, Bruges, Haarlem, Nimwegen, Groningen, Cologne, Minden, Bremen, Erfurt, Hamburg, Lubeck, Rostock, Berlin, Ripen, Flensburg, Aalborg, Naevsted, Bergen, Stavanger, Oslo, Stockholm, Gothenburg, Malmo, Ahus, Visby, Stettin, Posen, Breslau, Danzig, Thorn, Warsaw, Konigsberg, Kaunas, Riga, Reval, Helsinki, Novgorod, TOTALTOWNS};
string townName[]{ "Edinburgh", "Scarborough", "Boston", "London", "Bruges", "Haarlem", "Nimwegen", "Groningen", "Cologne", "Minden", "Bremen", "Erfurt", "Hamburg", "Lubeck", "Rostock", "Berlin", "Ripen", "Flensburg", "Aalborg", "Naevsted", "Bergen", "Stavanger", "Oslo", "Stockholm", "Gothenburg", "Malmo", "Ahus", "Visby", "Stettin", "Posen", "Breslau", "Danzig", "Thorn", "Warsaw", "Konigsberg", "Kaunas", "Riga", "Reval", "Helsinki", "Novgorod"};
class resource
{
public:
float demand, production, businessNeeds, businessProduction;
// This function, called a constructor, is run every time a new resource is created
// In this case, it assigns 0 to everything
resource()
{
demand = 0;
production = 0;
businessNeeds = 0;
businessProduction = 0;
}
float net()
{
return (this->production - this->demand);
}
float businessNet()
{
return (this->businessProduction - this->businessNeeds);
}
};
class town
{
public:
// The array of pointers to each of a our resource objects
resource *resList[TOTALRESOURCES];
// This is the town constructor
town()
{
// Loops through the array and creates a new resource object in each
// the resource constructor assigns the default values of 0.
for (int i = 0; i < TOTALRESOURCES; i = i + 1)
{
resList[i] = new resource();
}
}
~town()
{
// Loops through the array and deletes each resource object
for (int i = 0; i < TOTALRESOURCES; i = i + 1)
{
delete resList[i];
}
};
int main()
{
//What do I do here?
for (int i = 0; i < TOTALTOWNS; i++)
{
town townName[i];
}
system("pause");
return 0;
}
So, I'm a software engineering student and I just switched majors so I decided to take some personal time to learn how to code in c++ a bit better. I decided to build a program that can plan the logistics for a videogame called Patrician IV.
I have put about 5 days worth of work into this project and have found some serious problems with my initial code (hard to add new functionality and change stuff around). So I took a step back and am trying to build my classes in a more succinct manner while also being able to loop through each instance of town later in a loop so I can update the demand, production, businessNeeds, and businessProduction values easily. I was copying and pasting about 6 lines of code 40 times before this.
I want to know:
(A) is it possible to do what I want - i.e. can I use enums and a for-loop to construct instances of town.
(B) how to loop through each of the towns so that I can add values to the resource variables.
(C) a third-grade-level explanation of how to use pointers for similar purposes would also be great.
:) THANK YOU!
In your main function, use the same idea as resList to initialize your town objects, so:
town* townName[TOTALTOWNS]
for (int i = 0; i < TOTALTOWNS; i++)
{
townName[i]= new town();
}
Then, I'm guessing you want to give different values for each of the different resources. Switch statements go along with enums well. So I would recommend something like this:
for (int i = 0; i < TOTALRESOURCES; i = i + 1)
{
switch(i)
{
case WOOD:
townName[EDINBURGH]->resList[WOOD]->demand= yourValue;
break;
case BRICK:
break;
}
}
Or if you're cycling through towns:
for (int i = 0; i < TOTALTOWNS; i = i + 1)
{
switch(i)
{
case EDINBURGH:
break; //etc.
}
}
If you only want to update a single town or resource, depending on how you're organizing everything, you could create something like this. A function that takes your town array and the enum indexes, like this:
updateTownResources(town* (*townName)[TOTALTOWNS], int townEnum, int resourceEnum, int dValue, int pValue )
{
townName[townEnum]->resList[resourceEnum]->demand= dValue;
townName[townEnum]->resList[resourceEnum]->production= pValue;
//etc...
}
int main()
{
std::vector<town*> townArray;
//What do I do here?
for (int i = 0; i < TOTALTOWNS; i++)
{
town* pTown = new(std::nothrow) town;
townArray.push_back (pTown);
}
std::vector<town*>::iterator iter = townArray.begin();
for (;iter != townArray.end(); iter++) {
(*iter); // gives access to individual objects
}
system("pause");
return 0;
}
I don't know if my title is right but I am trying to eliminate duplicate so I think I should put this definitions in an array. Can someone suggest me how I could put the pButtons in array? I am thinking something like pButton[EButtonHost], pButton[EButtonUsername] etc.
#define pButtonHost static_cast<XQtMultipleStringInputButton*>(m_pButtonList[EButtonHost])
#define pButtonUsername static_cast<XQtMultipleStringInputButton*>(m_pButtonList[EButtonUsername])
#define pButtonPassword static_cast<XQtMultipleStringInputButton*>(m_pButtonList[EButtonPassword])
I have a method below like this.
XIniFile readIniFile;
readIniFile.open(k_systemIniFile, EIniReadOnly);
string data;
readIniFile.readString("Server", "host", data);
pButtonHost->setString(data);
m_host = pButtonHost->getString();
readIniFile.readString("Server", "username", data);
pButtonUsername->setString(data);
m_username = pButtonUsername->getString();
readIniFile.readString("Server", "password", data);
pButtonPassword->setString(data);
m_password = pButtonPassword->getString();
They look like duplicates so I am trying to optimize it. Thanks!
Update:
I have something like this now. Would this be right? or do you have any better suggestions?
for (int i = 0; i < 3; ++i) {
readIniFile.readString("Server", k_dataList[i], data);
static_cast<XQtMultipleStringInputButton*>(m_pButtonList[i])->setString(data);
m_pData[i] = static_cast<XQtMultipleStringInputButton*>(m_pButtonList[i])->getString();
}
A below code looks clear by using auto and `lambda',
auto GetConfigInfo = [&](string section_name, ButtonType btn_type)-> string
{
readIniFile.readString("Server", section_name, data);
m_pButtonList[btn_type_]->setString(data);
return m_pButtonList->getString();
};
m_host = GetConfigInfo("host", EButtonHost);
m_username = GetConfigInfo("username", EButtonUserName);
m_password = GetConfigInfo("password", EButtonPassword);
and a define data type by using struct can be other method.
struct ConfigDefine
{
string section_;
ButtonType btn_type_; //your enum button type, such as EButtonHost, EButtonUserName
string& result_;
}configs[] =
{
{"host", EButtonHost, m_host},
{"username", EButtonUserName, m_username},
{"password", EButtonPassword, m_password}
};
for_each(std::begin(configs), std::end(configs), [&](ConfigDefine& config)
{
readIniFile.readString("Server", config.section_, data);
m_pButtonList[config.btn_type_]->setString(data);
config.result_ = pButtonHost->getString();
});
Do you intend to have something like this one?
#define ASIZE 3
int indx[ASIZE] = {EButtonHost, EButtonUsername, EButtonPassword};
string s[ASIZE] = {"host", "username", "password"};
string *m[ASIZE] = {&m_host, &m_username, &m_password};
for (int i = 0; i < ASIZE; i++) {
readIniFile.readString("Server", s[i].c_str(), data);
pButtonHost->setString(data);
*m[i] = pButtonHost->getString();
}
This is more a, I'm kind of curious to know if it would make sense question, than a, I have a real problem question, I'm interessted in your opinion. If there are any syntax errors, I use pseudo-code to illustrate what intent to describe.
I have a program that uses a for-loop.
for (frame_pos = 0; frame_pos < frame_size; frame_pos++) {
ABC...
}
Now I want to add another possible way to iterate through my program.
for (frame_pos = framelist.first; framlist.hasNext; frame_pos = framelist.getNext) {
ABC...
}
So I wrote an if statement
if(a == true){
for (frame_pos = 1; frame_pos <= frame_size; frame_pos++) {
ABC...
}
}else{
for (frame_pos = framelist.first; framlist.hasNext; frame_pos = framelist.getNext) {
ABC...
}
}
But somehow I didn't like it beacause I had duplicated my code.
ABC...
Of course I could move everything from within my loops to a method and only invoke that method. But I was wondering, if something like
switch(a){
case(true):
for (frame_pos = 1; frame_pos <= frame_size; frame_pos++) {
break;
default:
for (frame_pos = framelist.first; framlist.hasNext; frame_pos = framelist.getNext) {
break;
}
would be possible and, if possible, usefull and make sense, because I would have used it here. It, of course, doesn't necessarily has to be a switch-case it could be some other mechanism. But my intention was/is to split the, from my point of view, atomic
for( ; ; ) {
...
}
body and recombine it.
Make ABC a function (extract method) and call that.
If you do not want to switch between both method during run-time, you could solve this on pre-processor level:
#define _USENEXT /* Comment out this line to use the "counter" approach. */
...
for (
#ifdef _USENEXT
frame_pos = framelist.first; framlist.hasNext; frame_pos = framelist.getNext
#else
frame_pos = 1; frame_pos <= frame_size; frame_pos++
#endif
)
{
<some code>
}
As an alternative to #defineing _USENEXT in the code as by my example, one could specify it as option when compiling. For gcc this would be -D _USENEXT.
Some languages have mechanisms to easily make such patterns reusable. C# for example, would let you write something like the following:
IEnumerable<Frame> Frames1() {
for (frame_pos = 0; frame_pos < frame_size; frame_pos++) {
yield return framelist[framepos];
}
}
IEnumerable<Frame> Frames2() {
for (frame_pos = framelist.first; framlist.hasNext; frame_pos = framelist.getNext) {
yield return framelist[framepos];
}
}
And then you can use treat these iteration patterns as first class objects like any other.
foreach(var frame in a? Frames1() : Frames2()) {
ABC...
}
With such a feature you can avoid implementation details like those silly boilerplatey low-level error-prone primitive for loops from C.
C++ doesn't have such a syntactic feature, but it also has a similar established mechanism for reusing iteration patterns: iterators. Writing an iterator isn't as dead simple as in C#, though :(
But standard containers already provide suitable iterators. You can then reuse any of the many existing iteration patterns provided in the standard library.
std::vector<int> v = ...;
std::set<int> s = ...;
auto are_equal = std::equal(v.begin(), v.end(), s.begin(), s.end());
Good C++ libraries will similarly provide suitable iterators too. (Yeah, good luck with that; it seems a large portion of people writing "C++ libraries" doesn't know C++)
If you really don't want to make ABC a function an then switch between two different for loops you could instead write three functions:
int initFramepos( int a )
{
return( a ? 1 : framelist.first );
}
int checkFramepos( int frame_pos, int a )
{
return( a ? frame_pos < frame_size ? framelist.hasNext );
}
int incrFramepos( int frame_pos, int a )
{
return( a ? frame_pos+1 ? framelist.getNext );
}
Then your for-loop could look like this:
for( frame_pos = initFramepos( a ); checkFramepos( frame_pos, a ); frame_pos = incrFramepos( frame_pos, a ) )
{
ABC
}
The clean solution (for C++ code - this will not work for C) would be to write an iterator class implementation for your specific case. Then, you could write your client code in terms of an iterator, and decide what iteration means independent of how it is implemented (you will be able to decide what iteration means for you at any point, without changing client code at all).
If you do this and specialize std::begin and std::end, you will be able to use the entire iterators algorithms library in std as a bonus: (sort, copy, find/find_if, for_each, all_of, any_if, transform and accumulate are the most useful, out of the top of my head).
Regarding other solutions, do not use a macro: it results in brittle code with many difficult to see caveats. As a rule of thumb, using a macro in C++ should be (close to) the last considered solution for anything.
What you describing here is exactly the problem that strategy pattern was meant to solve.
Basically, what you need to do here is to make each loop as a method within a class, and then set one of them as your strategy. And of course you can switch between strategies whenever you want.
it will look like this:
class Strategy {
virtual void func () = 0;
};
.
class StrategyA : public Strategy {
virtual void func () {
for (frame_pos = 0; frame_pos < frame_size; frame_pos++) {
ABC...
}
}
};
.
class StrategyB : public Strategy {
virtual void func () {
for (frame_pos = framelist.first; framlist.hasNext; frame_pos = framelist.getNext) {
//ABC...
}
}
};
.
class StrategyToTake {
private:
Strategy* strategy;
public:
void execute () {strategy->func();}
void setStrategy (Strategy* newStrategy) {this.strategy = newStrategy;}
};
.
If i have a string as such
"I am not here... \n..Hello\n.\n....Whats happening"
I want to replace the above string so:
"I am not here... \n..Hello\n. \n....Whats happening"
^ Space added
Just a bit of a background on what im doing. Im using sendmail in C++ and \n.\n is End Of Message Equivalent of sendmail. I just created a class that uses sendmail to send mails. but obviously if the user from the outsite gives sendmail that command i want it to be removed. Here is my message function just incase.:
//Operator to add to the message
void operator<<(string imessage){
if (imessage != ""){ message += imessage; }
}
How would i go about doing this. Thanks in advance :D
This is my last version :)
This code handles the case mentioned by #Greg Hewgill
string& format_text(string& str)
{
const string::size_type dot_offset = 2;
string::size_type found_at_start = str.find("\n.\n"),
found_at = str.find("\n.\n");
if(found_at_start != string::npos)
str.insert(0, " ");
while(found_at != string::npos)
{
str.insert(found_at+dot_offset+1, " ");
found_at = str.find("\n.\n", found_at+1);
}
return str;
}
int main()
{
string text = ".\nn\n.\nn";
std::cout << format_text(text);
}
Look up String.find and String.replace
For example (not tested)
string endOfMessage = "\n.\n";
string replacement = "\n. \n";
size_t position;
while (position = message.find(endOfMessage))
{
message.replace(position, endOfMessage.length(), replacement);
}
This is derived from Dan McG's answer so upvote him ;)
string endOfMessage = "\n.\n";
string replacement = "\n. \n";
size_t position;
while (position = message.find(endOfMessage, position) != message.npos)
{
message.replace(position, endOfMessage.length(), replacement);
position += replacement.length();
}
Boost has Boost.Regex (a regular expression module). Might be overkill if this is the only replacement you need to do.
Use std::search and the insert method of sequence containers such as string, deque, or whatever you use to store the message text.
typedef std::string::iterator SIter; // or whatever container you use
static const char *end_seq = "\n.\n";
for ( SIter tricky_begin = msg.begin();
tricky_begin = std::search( tricky_begin, msg.end(), end_seq, end_seq+3 ),
tricky_begin != msg.end(); ) {
tricky_begin = msg.insert( tricky_begin + 2, ' ' );
}