How can I partition a QByteArray efficiently? - qt

I want to partition a QByteArray message efficiently, so this function I implemented take the Bytes, the part I want to extract, and toEnd flag which tells if I want to extract part1 till the end of the array. my dilimeter is spcae ' '
example if I have:
ba = "HELLO HOW ARE YOU?"
ba1 = getPart(ba, 1, false) -> ba1 = "HELLO"
ba2 = getPart(ba, 2, true) -> ba2 = "HOW ARE YOU?"
ba3 = getPart(ba, 3, false) -> ba3 = "ARE"
the function below works just fine, but I am wondering if this is efficient. should I consider using split function?
QByteArray Server::getPart(const QByteArray message, int part, bool toEnd)
{
QByteArray string;
int startsFrom = 0;
int endsAt = 0;
int count = 0;
for(int i = 0; i < message.size(); i++)
{
if(message.at(i) == ' ')
{
count++;
if(part == count)
{
endsAt = i;
break;
}
string.clear();
startsFrom = i + 1;
}
string.append(message.at(i));
}
if(toEnd)
{
for(int i = endsAt; i < message.size(); i++)
{
string.append(message.at(i));
}
}
return string;
}

What about this:
QByteArray Server::getPart(const QByteArray& message, int part, bool toEnd)
{
int characters(toEnd ? -1 : message.indexOf(' ', part) - part);
return message.mid(part, characters);
}

Why not make it a regular QString and use split. That will give you a QStringList.

Related

How do I correctly parse a string with "()" and ","

I'm going to parse a string of mathematical functions in Qt 5.12, for example
"fabs( sin( pow( cos(30) , pow(1,2) ) ) )"
How do I parse out each function name and its arguments correctly, continue parsing when the function argument is another function, and call a library function with the same name for a numeric value? Finally, the result is returned to the function above.
I tried to write code like this, with ", "as the separator to get each parameter. But when the argument is a function that requires more than one argument, a BUG occurs. But I can't think of a solution
double Cal::calculate(const QString & funcstr)
{
int lb = funcstr.indexOf("(");
int rb = funcstr.lastIndexOf(")");
double result = 0;
if(funcstr.startsWith("pow", Qt::CaseInsensitive))
{
QStringList paramList_str = funcstr.mid(lb + 1, rb - lb - 1).split(",");
QList<double> paramList;
for(int i = 0; i < paramList_str.size(); ++i)
{
if(parse(paramList_str[i]))
{
paramList.push_back(paramList_str[i].toDouble());
}else{
paramList.push_back(calculate(paramList_str[i]));
}
}
result = pow(paramList[0], paramList[1]);
}
else if(funcstr.startsWith("sin", Qt::CaseInsensitive))
{
QString param = funcstr.mid(lb + 1, rb - lb - 1);
if(parse(param))
result = sin(param.toDouble());
else
result = sin(calculate(param));
}else if(funcstr.startsWith("cos", Qt::CaseInsensitive))
{
QString param = funcstr.mid(lb + 1, rb - lb - 1);
if(parse(param))
result = cos(param.toDouble());
else
result = cos(calculate(param));
}else if(funcstr.startsWith("tan", Qt::CaseInsensitive))
{
QString param = funcstr.mid(lb + 1, rb - lb - 1);
if(parse(param))
result = tan(param.toDouble());
else
result = tan(calculate(param));
}
retur result;
}
bool parse(const QString &funcName)
{
QChar c = funcName[0];
bool res = true;
if(c.isLetter())
res = false;
return res;
}

Hashing, can't insert to hash table

struct googlePlayApp{
string name;
string category;
double rating;
int reviews;
googlePlayApp *next;
};
void appInsert(googlePlayApp &newApp, int &cmps) {
int slot = hash1(newApp.name, HASH_SIZE);
int cmps1 = 1;
googlePlayApp *tmp = appHash[slot];
if (tmp == 0)
appHash[slot] = &newApp;
else
{
while(tmp->next != 0)
{
tmp = tmp->next;
cmps1++;
}
tmp->next = &newApp;
}
cmps += cmps1;
}
while (getline(inFile, inputLine)) {
googlePlayApp newApp;
readSingleApp(inputLine, newApp);
appInsert(newApp, cmps);
linesRead++;
}
My program stops on the 65th iteration of the while loop....
64th for the appInsert call...
Why can't I get this to work?
This is a program where it reads a data file and stores it in a hash table and collision dealt with open addressing....
updated question
bool appFind(const string &name, googlePlayApp &foundApp, int &cmps) {
// Implement this function
int slot = hash1(name);
int cmps1 = 1;
googlePlayApp *tmp = appHash[slot];
while(tmp && tmp->name != name)
{
cmps1++;
tmp = tmp->next;
}
cmps += cmps1;
if(tmp)
{
foundApp.name = appHash[slot]->name;
foundApp.category = appHash[slot]->category;
foundApp.rating = appHash[slot]->rating;
foundApp.reviews = appHash[slot]->reviews;
}
else return false;
}
this is my serach function and I'm trying to search if an app exists based on the data I stored from my code above. I'm trying to search it by the hash addresses, but it's not working...

how to split a string into words in arduino?

I have a string in arduino
String name="apple orange banana";
Is it possible to store each item in an array arr
so that
arr[0]="apple"
arr[1]="orange" ......etc
if not store them in individual variables?
How to split a string using a specific delimiter in Arduino? I believe this would help you, you could do a while loop like:
int x;
String words[3];
while(getValue(name, ' ', x) != NULL){
words[x] = getValue(name, ' ', x);
}
Using this function:
// https://stackoverflow.com/questions/9072320/split-string-into-string-array
String getValue(String data, char separator, int index)
{
int found = 0;
int strIndex[] = {0, -1};
int maxIndex = data.length()-1;
for(int i=0; i<=maxIndex && found<=index; i++){
if(data.charAt(i)==separator || i==maxIndex){
found++;
strIndex[0] = strIndex[1]+1;
strIndex[1] = (i == maxIndex) ? i+1 : i;
}
}
return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}
If you know your list length and the max characters per list item, you could do
char arr[3][6] = {"apple", "orange", banana"};
edit: if you are looking for something like String arr[3] you aren't going to get it because of how memory is managed with the C language

how to tokenize a string in arduino

i am using arduino due. what i am trying to do is to receive a string at serial. like this one:
COMSTEP 789 665 432 END
if the string starts with comstep, then to tokenize the string and get an integer array {789, 665, 432}.
is there anyway to do that?
P.S: im a noob at programming, so any help is appreciated.
I have a function that I wrote long ago to parse strings up in an easy manner. It is in use on several of my Arduino projects.
Sample usage:
char pinStr[3];
char valueStr[7];
int pinNumber, value;
getstrfld (parms_in, 0, 0, (char *)",", pinStr);
getstrfld (parms_in, 1, 0, (char *)",", valueStr);
pinNumber = atoi (pinStr);
value = atoi (valueStr);
The functions:
// My old stand-by to break delimited strings up.
char * getstrfld (char *strbuf, int fldno, int ofset, char *sep, char *retstr)
{
char *offset, *strptr;
int curfld;
offset = strptr = (char *)NULL;
curfld = 0;
strbuf += ofset;
while (*strbuf) {
strptr = !offset ? strbuf : offset;
offset = strpbrk ((!offset ? strbuf : offset), sep);
if (offset) {
offset++;
} else if (curfld != fldno) {
*retstr = 0;
break;
}
if (curfld == fldno) {
strncpy (retstr, strptr,
(int)(!offset ? strlen (strptr)+ 1 :
(int)(offset - strptr)));
if (offset)
retstr[offset - strptr - 1] = 0;
break;
}
curfld++;
}
return retstr;
}
// Included because strpbrk is not in the arduino gcc/g++ libraries
// Or I just could not find it :)
char * strpbrk (const char *s1, const char *s2)
{
const char *c = s2;
if (!*s1) {
return (char *) NULL;
}
while (*s1) {
for (c = s2; *c; c++) {
if (*s1 == *c)
break;
}
if (*c)
break;
s1++;
}
if (*c == '\0')
s1 = NULL;
return (char *) s1;
}
A light-weight approach (no strict checks on valid parses of the integers and ignoring any list elements past a fixed maximum):
char buf[32] = "COMSTEP 789 665 432 END"; // assume this has just been read
int res[8], nres = 0;
bool inlist = false;
for (char *p = strtok(buf, " "); p; p = strtok(0, " "))
if (inlist)
{
if (!strcmp(p, "END"))
{
inlist = false;
break;
}
else if (nres < sizeof(res) / sizeof(*res))
res[nres++] = atoi(p);
}
else if (!strcmp(p, "COMSTEP"))
inlist = true;
if (!inlist)
for (size_t i = 0; i < nres; ++i)
printf("%d%s", res[i], i + 1 < nres ? " " : "\n"); // do whatever

How to count how many different vowels are in one word from text file in C?

I am confused about counting how many differents vowels are in one word? This is were i got so far... I am saving word by word in the variable word[] and then check char by char whether is vowel or not... but i don't know how to count how many different vowels are in the word? Please help. Thanks in advance.
int i,j,words = 0;
while(fgets(row,MAX,f) != NULL)
{
int flag = 0;
int n = 0;
for(i = 0; i < strlen(row); i++)
{
if(isalpha(row[i]))
{
if(!flag)
{
flag = 1;
}
word[n++] = row[i];
}
else if(flag)
{
flag = 0;
word[n] = '\0';
for(j = 0; j < strlen(word);j++)
{
if(isvowel(word[i]))
{
c = word[i];
}
// i stopped here cause i donno how to check whether the char is different from all the others
}
}
}
}
As you find each vowel, simple set a flag of an array to note the vowel was found. Then count the number of flags. The trick is to effectively convert c (the vowel) into an index - that is where you are stuck.
char *strchr(const char *s, int c) is useful. It locates the first occurrence of (char) c in the string pointed to by s. Converting the result to an index for the flag array is then easy.
Let's say 'A' is the same as 'a' for vowel counting.
int DifferentVowelCount(const char *s) {
static const char *Vowels = "AaEeIiOoUu";
bool VowelExist[5] = { 0 };
while (*s) {
char *p = strchr(Vowels, *s);
if (p != NULL) {
int index = (int) (p - Vowels); // index is 0 to 9
index /= 2;
VowelExist[index] = 1;
}
s++;
}
int sum = 0;
int i;
for (i = 0; i < 5; i++) {
if (VowelExist[i]) {
sum++;
}
}
return sum;
}
Okay it seems like the function for counting the different vowels in one word is created manually, but this solution really works and here it is:
int diff_vowels(char *word)
{
char a = 'a',b = 'e', c = 'i', d = 'o', e = 'u';
int a1 = 0,b1 = 0,c1 = 0,d1 = 0,e1 = 0;
while(*word)
{
if(isalpha(*word))
{
if(tolower(*word) == 'a') a1 = 1;
else if(tolower(*word) == 'e') b1 = 1;
else if(tolower(*word) == 'i') c1 = 1;
else if(tolower(*word) == 'o') d1 = 1;
else if(tolower(*word) == 'u') e1 = 1;
}
word++;
}
return a1 + b1 + c1 + d1 + e1;
}

Resources