I create a program who I need to compare two Chinese characters.
I use this function to compare :
void fengshuitradition::comparerAuto()
{
Stockage obj_stockage;
Lunar lunar;
LunarObj* obj = lunar.solar2lunar(ui->SBSelection_4->value(), ui->SBSelection_3->value(), ui->SBSelection_2->value());
string day = obj->ganzhiDay;
for(int i = 0; i<64; i++)
{
string jourComparer = obj_stockage.appelStockage(i,1);
string jourComparer2 = obj_stockage.appelStockage(i,2);
if (day.compare(0,6,jourComparer,0,6) == 0 && day.compare(7,6,jourComparer2,0,6) == 0)
{
ui->label_0->setText(obj_stockage.appelStockage(i,0));
ui->label_1->setText(obj_stockage.appelStockage(i,1));
ui->label_2->setText(obj_stockage.appelStockage(i,2));
ui->label_3->setText(obj_stockage.appelStockage(i,3));
ui->label_4->setText(obj_stockage.appelStockage(i,4));
ui->label_5->setText(obj_stockage.appelStockage(i,5));
ui->label_6->setText(obj_stockage.appelStockage(i,6));
return;
}
}
}
My values are stock like this :
const char* stockage[64][7] = {
{"1",
"\u7532 B+",
u8"\u5b50 E+ hiver",
"24 F",
"8",
"癸E-",
". ."},
// ainsi de suite
And I use a library :
static std::string Gan[] = {"\u7532","\u4e59","\u4e19","\u4e01","\u620a","\u5df1","\u5e9a","\u8f9b","\u58ec","\u7678"};
static std::string Zhi[] = {"\u5b50","\u4e11","\u5bc5","\u536f","\u8fb0","\u5df3","\u5348","\u672a","\u7533","\u9149","\u620c","\u4ea5"};
Thanks for your help.
Related
I have a character array like below:
char array[] = "AAAA... A1... 3. B1.";
How can I split this array by the string "..." in Arduino? I have tried:
ptr = strtok(array, "...");
and the output is the following:
AAAA,
A1,
3,
B1
But I actually want output to be
AAAA,
A1,
3.B1.
How to get this output?
edit:
My full code is this:
char array[] = "AAAA... A1... 3. B1.";
char *strings[10];
char *ptr = NULL;`enter code here`
void setup()
{
Serial.begin(9600);
byte index = 0;
ptr = strtok(array, "..."); // takes a list of delimiters
while(ptr != NULL)
{
strings[index] = ptr;
index++;
ptr = strtok(NULL, "..."); // takes a list of delimiters
}
for(int n = 0; n < index; n++)
{
Serial.println(strings[n]);
}
}
The main problem is that strtok does not find a string inside another string. strtok looks for a character in a string. When you give multiple characters to strtok it looks for any of these. Consequently, writing strtok(array, "..."); is exactly the same as writing strtok(array, ".");. That is why you get a split after "3."
There are multiple ways of doing what you want. Below I'll show you an example using strstr. Unlike strtokthe strstr function do find a substring inside a string - just what you are looking for. But.. strstr is not a tokenizer so some extra code is required to print the substrings.
Something like this should do:
int main()
{
char array[] = "AAAA... A1... 3. B1...";
char* ps = array;
char* pf = strstr(ps, "..."); // Find first substring
while(pf)
{
int len = pf - ps; // Number of chars to print
printf("%.*s\n", len, ps);
ps = pf + 3;
pf = strstr(ps, "..."); // Find next substring
}
return 0;
}
You can implement your own split as strtok except the role of the second argument :
#include <stdio.h>
#include <string.h>
char * split(char *str, const char * delim)
{
static char * s;
char * p, * r;
if (str != NULL)
s = str;
p = strstr(s, delim);
if (p == NULL) {
if (*s == 0)
return NULL;
r = s;
s += strlen(s);
return r;
}
r = s;
*p = 0;
s = p + strlen(delim);
return r;
}
int main()
{
char s[] = "AAAA... A1... 3. B1.";
char * p = s;
char * t;
while ((t = split(p, "...")) != NULL) {
printf("'%s'\n", t);
p = NULL;
}
return 0;
}
Compilation and execution:
/tmp % gcc -g -pedantic -Wextra s.c
/tmp % ./a.out
'AAAA'
' A1'
' 3. B1.'
/tmp %
I print between '' to show the return spaces, because I am not sure you want them, so delim is not only ... in that case
Because you tagged this as c++, here is a c++ 'version' of your code:
#include <iostream>
using std::cout;
using std::endl;
#include <vector>
using std::vector;
#include <string>
using std::string;
class T965_t
{
string array;
vector<string> strings;
public:
T965_t() : array("AAAA... A1... 3. B1.")
{
strings.reserve(10);
}
~T965_t() = default;
int operator()() { return setup(); } // functor entry
private: // methods
int setup()
{
cout << endl;
const string pat1 ("... ");
string s1 = array; // working copy
size_t indx = s1.find(pat1, 0); // find first ... pattern
// start search at ---------^
do
{
if (string::npos == indx) // pattern not found
{
strings.push_back (s1); // capture 'remainder' of s1
break; // not found, kick out
}
// else
// extract --------vvvvvvvvvvvvvvvvv
strings.push_back (s1.substr(0, indx)); // capture
// capture to vector
indx += pat1.size(); // i.e. 4
s1.erase(0, indx); // erase previous capture
indx = s1.find(pat1, 0); // find next
} while(true);
for(uint n = 0; n < strings.size(); n++)
cout << strings[n] << "\n";
cout << endl;
return 0;
}
}; // class T965_t
int main(int , char**) { return T965_t()(); } // call functor
With output:
AAAA
A1
3. B1.
Note: I leave changing "3. B1." to "3.B1.", and adding commas at end of each line (except the last) as an exercise for the OP if required.
I looked for a split function and I didn't find one that meets my requirement, so I made one and it works for me so far, of course in the future I will make some improvements, but it got me out of trouble.
But there is also the strtok function and better use that.
https://www.delftstack.com/es/howto/arduino/arduino-strtok/
I have the split function
Arduino code:
void split(String * vecSplit, int dimArray,String content,char separator){
if(content.length()==0)
return;
content = content + separator;
int countVec = 0;
int posSep = 0;
int posInit = 0;
while(countVec<dimArray){
posSep = content.indexOf(separator,posSep);
if(posSep<0){
return;
}
countVec++;
String splitStr = content.substring(posInit,posSep);
posSep = posSep+1;
posInit = posSep;
vecSplit[countVec] = splitStr;
countVec++;
}
}
Llamada a funcion:
smsContent = "APN:4g.entel;DOMAIN:domolin.com;DELAY_GPS:60";
String vecSplit[10];
split(vecSplit,10,smsContent,';');
for(int i = 0;i<10;i++){
Serial.println(vecSplit[i]);
}
String input:
APN:4gentel;DOMAIN:domolin.com;DELAY_GPS:60
Output:
APN:4g.entel
DOMAIN:domolin.com
DELAY_GPS:60
RESET:true
enter image description here
I wrote:
string a[100] = { "B", "F", "R", "P", "D", "\0" };
class BD{
//data member
static int id;
//.......
};
void setid(int d){ id = d;
for (int i = 0; i < 5; i++){
id = i + 1;
user[id];
}
cout << " ID : " << id << endl;
}
int BD::id = 0;
in this code, has an array include name of user and for each user a different ID number but in run (output) always will be 5 !
I know it's a logical error.
when enter : B
ID : 5
but I want to print :
if user enter name `B`
ID : 1
if user enter name F
ID : 2
You are rewriting id in the loop
id = i + 1;
Thus as the last i used in the body of the loop is equal to 4 then you always get that id = 5
EDIT:
If you want to find a string in an array of strings and return its index + 1 then the function can look like
int getId( const std::string &s )
{
string a[100] = { "B", "F", "R", "P", "D", "\0" };
int id = 0;
while ( a[id] != "\0" && a[id] != s ) ++id;
return a[id] == "\0" ? 0 : id + 1;
}
However it seems you do not understand the difference between objects of type std::string and character arrays and string literals. So you need something different than the function I showed.
I'm trying to replace multiple words with their "pirate pair", for example:
Normal: "Hello sir, where is the hotel?"
Pirate: "Ahoy matey, whar be th' fleagbag inn?"
This is what I tried before:
#include<iostream>
#include<string>
#include<conio.h>
using namespace std;
void speakPirate(string s);
int main()
{
string phrase;
cout << "Enter the phrase to Pirate-Ize: ";
getline(cin, phrase);
speakPirate(phrase);
_getch();
return 0;
}
void speakPirate(string s)
{
int found;
// list of pirate words
string pirate[12] = { "ahoy", "matey", "proud beauty", "foul blaggart", "scurvy dog", "whar", "be", "th'", "me", "yer", "galley", "fleabag inn" };
// list of normal words
string normal[12] = { "hello", "sir", "madam", "officer", "stranger", "where", "is", "the", "my", "your", "restaurant", "hotel" };
for (int i = 0; i < s.length(); i++)
{
found = s.find(normal[i]);
if (found > -1)
{
string left = s.substr(0, found - 1); // get left of the string
string right = s.substr(found + pirate[i].length(), s.length()); // get right of string
s = left + " " + pirate[i] + " " + right; // add pirate word in place of normal word
}
}
cout << s;
}
But it didn't really work and was very buggy, so I tried using the replace() function instead:
#include<iostream>
#include<string>
#include<conio.h>
using namespace std;
void speakPirate(string s);
int main()
{
string phrase;
cout << "Enter the phrase to Pirate-Ize: ";
getline(cin, phrase);
speakPirate(phrase);
_getch();
return 0;
}
void speakPirate(string s)
{
int found;
// list of pirate words
string pirate[12] = { "ahoy", "matey", "proud beauty", "foul blaggart", "scurvy dog", "whar", "be", "th'", "me", "yer", "galley", "fleabag inn" };
// list of normal words
string normal[12] = { "hello", "sir", "madam", "officer", "stranger", "where", "is", "the", "my", "your", "restaurant", "hotel" };
for (int i = 0; i < s.length(); i++)
{
found = s.find(normal[i]);
if (found > -1)
{
s.replace(found, found + pirate[i].length(), pirate[i]);
}
}
cout << s;
}
I'm not sure why, but this doesn't really work either. I also notice that when I try changing a larger word into a smaller word, some of the original word is leftover, for example:
Enter the phrase to Pirate-Ize: hello
ahoyo
And I just noticed that it sometimes might not even change the word at all, for example:
Enter the phrase to Pirate-Ize: where
where
How come? Could someone please tell me what I need to do or a more effective solution that I could implement? Thanks a lot.
Here you iterate over the length of the text:
for (int i = 0; i < s.length(); i++)
It should be the length of the array of texts, something like
for (int i = 0; i < 12; i++)
However, you should use a std::map to model the mapping between the normal words and their pirate version.
std::map<std::string, std::string> words = {
{"hello", "ahoy"},
// .. and so on
};
for(auto const & kvp : words)
{
// replace kvp.first with kvp.second
}
Marius is correct that the major error is that you need to iterate over the length of the arrays. A different way than mapping would be to use erase() and insert() where you used replace(). replace() does not account for the lengths of the strings being different, but removing a substring and then adding in a new substring will. This can be done as follows
for (int i = 0; i < 12; i++)
{
found = s.find(normal[i]);
// Locate the substring to replace
int pos = s.find( normal[i], found );
if( pos == string::npos ) break;
// Replace by erasing and inserting
s.erase( pos, normal[i].length() );
s.insert( pos, pirate[i] );
}
I'm trying to convert some strings, I'd like to be able to remove diacritics from strinf. (Exemple : éùèà would become euea)
i have try this :
static str AALRemoveDiacritics( System.String input )
{
int i;
System.Text.NormalizationForm FormD;
str normalizedString = input.Normalize(FormD);
System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder();
for (i = 0; i < strLen(normalizedString); i++)
{
System.Char c = normalizedString[i];
if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
{
stringBuilder.Append(c);
}
}
return stringBuilder.ToString().Normalize(NormalizationForm.FormC);
}
It looks like you tried making this post work in X++ and were very close.
Here's a working job I just wrote you can use:
static void AlexRemoveDiacritics(Args _args)
{
str strInput = 'ÁÂÃÄÅÇÈÉàáâãäåèéêëìíîïòóôõ£ALEX';
System.String input = strInput;
str retVal;
int i;
System.Char c;
System.Text.NormalizationForm FormD = System.Text.NormalizationForm::FormD;
str normalizedString = input.Normalize(FormD);
System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder();
for (i = 0; i <= strLen(normalizedString); i++)
{
c = System.Char::Parse(subStr(normalizedString, i, 1));
if (System.Globalization.CharUnicodeInfo::GetUnicodeCategory(c) != System.Globalization.UnicodeCategory::NonSpacingMark)
{
stringBuilder.Append(c);
}
}
input = stringBuilder.ToString();
input = input.Normalize();
retVal = input;
info(strFmt("Before: '%1'", strInput));
info(strFmt("After: '%1'", retVal));
}
Suppose I have the following func and want to compare field as variable and value as value. How can I do it?
bool ReadFile::compareField(string field, string value)
{
if (field == "value")
}
If you're talking about C++, then the answer is: you can't. Variables are a compile-time thing; they don't exist at run-time.
If you want to access parameters as strings, then you might consider using e.g. a std::map:
class MyClass
{
private:
std::map<std::string, int> params;
public:
MyClass()
{
params["height"] = 165;
params["weight"] = 65;
params["legs"] = 2;
}
int getParam(const std::string &str) const
{
return params[str];
}
};
I changed the above func without map to the following func:
bool ReadFile::compareField( string * field, string value){
int i;
string fieldName = *field;
//converting to lower case
for (i = 0; i< strlen(value.c_str());i++)
value[i] = tolower(value[i]);
for (i = 0; i< strlen(fieldName.c_str());i++)
fieldName[i] = tolower(fieldName[i]);
/////
cout << fieldName << endl;
if (strstr(fieldName.c_str(),value.c_str()) != NULL){
return true;
}
return false;
}
At first i convert to lowercase and then search with strstr func, But here is a nice note that i use address of that variable instead of its name.