NSString loop characters and NSDictionary objectForKey - nsstring

I have a NSString #"Test" and NSDictionary #"T" -> #"String1" | #"e" -> #"String2" | #"s" -> #"String3"
I would like to loop through all characters of the string and for each character perform NSDictionary objectForKey method.
The result should be a NSString #"String1 String2 String 3 String 1"

Here is one way to do this:
NSString *str = #"test!";
NSDictionary *dict = #{#"t":#"T",#"e":#"E",#"s":#"S"};
NSMutableArray *result = [NSMutableArray array];
for (NSUInteger i=0, n=str.length; i<n; i++) {
NSString *key = [str substringWithRange:NSMakeRange(i, 1)];
id value = dict[key];
[result addObject:(value != nil)? value : #"?"];
}

Related

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

Solving QT's QString arg() ambiguity

There is an issue using QString::arg() when a string contains a digit right after a place marker. It's not clear from the QString::arg() function description what would happen in case of such a replacement:
QString("String for replacement %1234").arg("blah");
Will this result in "String for replacement blah234" or "String for replacement blah34"?
I looked in the QT's source code to answer this question. It seems that the algorithm which looks for place markers is 'greedy' and it would take both digits in the example above.
Here is the source of the QT's function which is used inside the QString::arg() (QT 4.8.4):
static ArgEscapeData findArgEscapes(const QString &s)
{
const QChar *uc_begin = s.unicode();
const QChar *uc_end = uc_begin + s.length();
ArgEscapeData d;
d.min_escape = INT_MAX;
d.occurrences = 0;
d.escape_len = 0;
d.locale_occurrences = 0;
const QChar *c = uc_begin;
while (c != uc_end) {
while (c != uc_end && c->unicode() != '%')
++c;
if (c == uc_end)
break;
const QChar *escape_start = c;
if (++c == uc_end)
break;
bool locale_arg = false;
if (c->unicode() == 'L') {
locale_arg = true;
if (++c == uc_end)
break;
}
if (c->digitValue() == -1)
continue;
int escape = c->digitValue();
++c;
if (c != uc_end && c->digitValue() != -1) {
escape = (10 * escape) + c->digitValue();
++c;
}
if (escape > d.min_escape)
continue;
if (escape < d.min_escape) {
d.min_escape = escape;
d.occurrences = 0;
d.escape_len = 0;
d.locale_occurrences = 0;
}
++d.occurrences;
if (locale_arg)
++d.locale_occurrences;
d.escape_len += c - escape_start;
}
return d;
}
Is there a better way of solving such an ambiguity than always using a 2-digit place markers?
Since you can only use %1 to %99 as markers and you can skip marker numbers you can write:
QString("String for replacement %10234").arg("blah");
to output String for replacement blah234
Qt help states for arg(const QString & a, int fieldWidth = 0, QChar fillChar = QLatin1Char( ' ' ))
Returns a copy of this string with the lowest numbered place marker replaced by string a, i.e., %1, %2, ..., %99.
...
Place marker numbers must be in the range 1 to 99.
Therefore, what you're seeing is, by definition, correct; the first two numbers will be replaced. If you're wanting "String for replacement blah234", then you could define the string as: -
QString("String for replacement %1%2").arg("blah").arg(234);
I have the same issue, but the order answers not looks like a good way for me.
I have resolve the ambiguity in this way.
QString myString= QString("ConcatenatedNumbers%0123").arg(66,3,10, QChar('0'));
The string will be:
ConcatenatedNumbers06623

sqlite iphone sdk help?

I am reading the sqlite but unable to get data instead it showing nil values. please refer the given code....
-(void)getDatabasePath:(NSString *)dBPath sqlCatagoryId:(NSString *)catId {
if(sqlite3_open([dBPath UTF8String], &_database) == SQLITE_OK) {
NSLog(#"database path %#", dBPath);
NSString *sqlStatement = [NSString stringWithFormat:#"SELECT * FROM SubCategories where CAT_ID = '%#'",catId];
NSString *aCategoryId, *aSubCategoryId, *aSubCategoryName, *aSubCategoryDescription;
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(_database, [sqlStatement UTF8String], -1, &statement, nil)
== SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW) {
char * str1 = (char *)sqlite3_column_text(compiledStatement, 1);
if (str1) {
aCategoryId = [NSString stringWithUTF8String:str1];
}
else {
aCategoryId = #"";
}
char * str2 = (char *)sqlite3_column_text(compiledStatement, 2);
if (str1) {
aSubCategoryId = [NSString stringWithUTF8String:str2];
}
else {
aSubCategoryId = #"";
}
char * str3 = (char *)sqlite3_column_text(compiledStatement, 3);
if (str1) {
aSubCategoryName = [NSString stringWithUTF8String:str3];
}
else {
aSubCategoryName = #"";
}
char * str4 = (char *)sqlite3_column_text(compiledStatement, 4);
if (str1) {
aSubCategoryDescription = [NSString stringWithUTF8String:str4];
}
else {
aSubCategoryDescription = #"";
}
NSData *aSubCategoryImage;
NSUInteger blobLength = sqlite3_column_bytes(compiledStatement, 5);
if(blobLength > 0){
aSubCategoryImage = [NSData dataWithBytes:sqlite3_column_blob(compiledStatement, 5) length:blobLength];
}
else {
aSubCategoryImage = nil;
}
SubCategoryModel *subCategoryModel = [[SubCategoryModel alloc] initWithCategoryId:aCategoryId subCategoryId:aSubCategoryId subCategoryName:aSubCategoryName subCategoryDescription:aSubCategoryDescription subCategoryImage:aSubCategoryImage];// database:database
//Add the details object to the Array
[subCategorryArray addObject:subCategoryModel];
[subCategoryModel release];
}
sqlite3_finalize(statement);
}
}
[self.aTableView reloadData];
}
please point out where I am going wrong or why I am not able to get data from sqlite. thanks
I was doing wrong in sqlite3_stmt *statement; and sqlite3_stmt * compiledStatement;
that I mixed the both sqlite3_stmt

How can I partition a QByteArray efficiently?

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.

Resources