Parameters of a object get lost (XCode for IPhone) - string

I have here a strange behaviour. XCode 4 for iOS 6 (Iphone 4s)
In the init-section I want to read data from a file.
NSString *rawData = [[NSString alloc] initWithContentsOfFile:filePathLib encoding:NSUTF8StringEncoding error:NULL];
NSArray *zeilen = [rawData componentsSeparatedByString:#";"];
NSLog(#"Check1 \n%#\n%#",rawData, zeilen);
OK, now the LogItem shows me, that the correct data were read.
Now I have an if-condition:
if ([zeilen count]==4){
A = [zeilen objectAtIndex:0];
B = [zeilen objectAtIndex:1];
C = [zeilen objectAtIndex:2];
D =[[zeilen objectAtIndex:3] intValue];
NSLog(#"Check2 \n%#\n%# - %# - %# - %# - %d",rawData, zeilen, A, B, C, D);
} else {
A = #"A0";
B = #"B0";
C = #"C0";
D = 3;
}
Now I run this programm.
If the first branch was used, the program crashes, if the second was used, it runs perfectly.
If I use break points I can observe the following:
A NSString * 0x20063bf0 #"A123" (the correct value)
B, C, D also correct
later, a line before the crash:
file-read branch:
A, B and C are NOT available, D is correct.
default, branch:
A, B, C and D are correct.
The variables are nowhere else manipulated or even deleted.
Has anyone an idea, where the problem is?
My assumption: The array "zeilen" does not contain NSString-values and therefore they are somehow deleted. But, I do not really believe in this theory, because at the beginning the elements are correct and available and only later they are deleted.
Any idea?

Solved it:
replace:
A = [zeilen objectAtIndex:0];
by
A = [[NSString alloc] stringWithFormat:#"%#",[zeilen objectAtIndex:0]];
Memory was not allocated, therefore it got lost.

Related

Not able to deallocate static based variable

I'm getting strange results when attempting to de-allocate a static based variable. Below is a small test program I've created to demo the issue I'm having. The static based variable is in the proc1 sub-procedure of this test program. Its name is myIx, with based pointer of myIx_p. I put comments in the main body of the program to indicate the issues that I'm having. What am doing wrong here?
D ix s 5i 0
/free
ix = proc1(*off); // ix is 1 after this statement => Expected
ix = proc1(*off); // ix is 2 after this statement => Expected.
ix = proc1(*on); // ix is 0, which is expected. But myIx_p is not being set to null => NOT Expected
ix = proc1(*off); // ix is 3 after this statement => NOT Expected. Expecting 1.
ix = proc1(*on); // try to shutdown again and get CEE0810 error => NOT Expected
*inlr = *on;
*------------------------------------------------------------------------------------------
* proc1 to test based static variable
*------------------------------------------------------------------------------------------
P proc1 B
D pi 5i 0
D piShutDown n const
D myIx s 5i 0 based(myIx_p)
D myIx_p s * static
// caller only wants to shutdown the proc
if (piShutDown and myIx_p <> *null);
dealloc myIx_p;
return 0;
endif;
// allocate myIx if not yet allocated
if (myIx_p = *null);
myIx_p = %alloc(%size(myIx));
endif;
// increase the value by 1 as a test
myIx += 1;
return myIx;
P E
/end-free
The answer is right there in your comments. You do not set myIx_p = *null after you dealloc. Failure to set it to *null means it is still pointing to the same memory location that it was only the operating system no longer sees it as allocated. The behavior you are seeing is entirely expected. The fix is as simple as:
// caller only wants to shutdown the proc
if (piShutDown and myIx_p <> *null);
dealloc myIx_p;
myIx_p = *null;
return 0;
endif;
You can also resolve it as thus according to the IBMi documentation:
// caller only wants to shutdown the proc
if (piShutDown and myIx_p <> *null);
dealloc(n) myIx_p;
return 0;
endif;
If you don't use (n), you must set it to *null yourself like in the first example. See the documentation about dealloc here: https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_74/rzasd/zzdeall.htm

Implement phone directory using two tries

I have encountered an interview question
“Implement a phone directory using Data Structures”
I want to solve it using tries.By solving it with tries,I tried using two tries,one for name and another for phone number,
but I faced a difficulty .
Suppose ,I have to add three entries( AB “112” BC ”124” CD ”225”)
Then if I query the name for number “225”,how do I return CD.
that is,how these two tries will be linked .
One approach I was thinking was taking two pointers in both the tries.
These pointers will point to the first and last word in the other trie.
For example,if the structures are as follows:
Struct nametrie
{
Struct nametrie *child[26];
struct phonetrie*head,*tail;
struct phonetrie*root;
-----------
}
Struct phonetrie
{
struct phonetrie*child[9];
struct nametrie*head,*tail;
struct nametrie*root;
-----------
}
Then for AB “112”,
Name trie willstore head(1) and tail (2).
But I think this approach will not work for duplicate entries(one name and multiple numbers.)
Can someone please explain a good approach.I am not looking for code but good understanding of approach,may be via diagram or algorithm.
I dont know C so I cant comment in your code.
The idea of using tries is valid.
you seems to be missing what data the nodes can hold in tries
the node in trees has 2 main components
the data it has which can be anytype
list of childen (or left , right childeren) or any combination of children
what we will do here is that we will add another field to each node and call it the value "theValue"
So the trie node will look like this
Class TrieNode{
public char theChar;
public String theValue;
public List<TrieNode> children;
}
So for forward lookup (name to phone) you construct one Trie and on the node that match entry in the directory you will set theValue to that entrie.
you will need to create 2nd trie to do the same for reverse lookup (phone to name)
So to give you example how it will look like for this data it will be
( AB “112” AC ”124” ACD ”225”)
//create nodes
TrieNode root = new TrieNode();
TrieNode A = new TrieNode();
A.theChar = 'A';
TrieNode B = new TrieNode();
A.theChar = 'B';
TrieNode C = new TrieNode();
A.theChar = 'C';
TrieNode C2 = new TrieNode();
A.theChar = 'C';
TrieNode D = new TrieNode();
A.theChar = 'D';
//link nodes together
root.children = new ArrayList<>();
root.children.add(A);
A.children = new ArrayList<>();
A.children.add(B);
A.children.add(C);
B.children = new ArrayList<>();
B.children.add(C2);
//fill the data
B.theValue = "112";
C.theValue = "124";
C2.theValue = "225";
now you can easy traverse this Trie and when you reach a node and whant to check the value just read theValue
i hope it is clear

AS3 "Advanced" string manipulation

I'm making an air dictionary and I have a(nother) problem. The main app is ready to go and works perfectly but when I tested it I noticed that it could be better. A bit of context: the language (ancient egyptian) I'm translating from does not use punctuation so a phrase canlooklikethis. Add to that the sheer complexity of the glyph system (6000+ glyphs).
Right know my app works like this :
user choose the glyphs composing his/r word.
app transforms those glyphs to alphanumerical values (A1 - D36 - X1A, etc).
the code compares the code (say : A5AD36) to a list of xml values.
if the word is found (A5AD36 = priestess of Bast), the user gets the translation. if not, s/he gets all the possible words corresponding to the two glyphs (A5A & D36).
If the user knows the string is a word, no problem. But if s/he enters a few words, s/he'll have a few more choices than hoped (exemple : query = A1A5AD36 gets A1 - A5A - D36 - A5AD36).
What I would like to do is this:
query = A1A5AD36 //word/phrase to be translated;
varArray = [A1, A5A, D36] //variables containing the value of the glyphs.
Corresponding possible words from the xml : A1, A5A, D36, A5AD36.
Possible phrases: A1 A5A D36 / A1 A5AD36 / A1A5A D36 / A1A5AD36.
Possible phrases with only legal words: A1 A5A D36 / A1 A5AD36.
I'm not I really clear but to things simple, I'd like to get all the possible phrases containing only legal words and filter out the other ones.
(example with english : TOBREAKFAST. Legal = to break fast / to breakfast. Illegal = tobreak fast.
I've managed to get all the possible words, but not the rest. Right now, when I run my app, I have an array containing A1 - A5A - D36 - A5AD36. But I'm stuck going forward.
Does anyone have an idea ? Thank you :)
function fnSearch(e: Event): void {
var val: int = sp.length; //sp is an array filled with variables containing the code for each used glyph.
for (var i: int = 0; i < val; i++) { //repeat for every glyph use.
var X: String = ""; //variable created to compare with xml dictionary
for (var i2: int = 0; i2 < val; i2++) { // if it's the first time, use the first glyph-code, else the one after last used.
if (X == "") {
X = sp[i];
} else {
X = X + sp[i2 + i];
}
xmlresult = myXML.mot.cd; //xmlresult = alphanumerical codes corresponding to words from XMLList already imported
trad = myXML.mot.td; //same with traductions.
for (var i3: int = 0; i3 < xmlresult.length(); i3++) { //check if element X is in dictionary
var codeElement: XML = xmlresult[i3]; //variable to compare with X
var tradElement: XML = trad[i3]; //variable corresponding to codeElement
if (X == codeElement.toString()) { //if codeElement[i3] is legal, add it to array of legal words.
checkArray.push(codeElement); //checkArray is an array filled with legal words.
}
}
}
}
var iT2: int = 500 //iT2 set to unreachable value for next lines.
for (var iT: int = 0; iT < checkArray.length; iT++) { //check if the word searched by user is in the results.
if (checkArray[iT] == query) {
iT2 = iT
}
}
if (iT2 != 500) { //if complete query is found, put it on top of the array so it appears on top of the results.
var oldFirst: String = checkArray[0];
checkArray[0] = checkArray[iT2];
checkArray[iT2] = oldFirst;
}
results.visible = true; //make result list visible
loadingResults.visible = false; //loading screen
fnPossibleResults(null); //update result list.
}
I end up with an array of variables containing the glyph-codes (sp) and another with all the possible legal words (checkArray). What I don't know how to do is mix those two to make legal phrases that way :
If there was only three glyphs, I could probably find a way, but user can enter 60 glyphs max.

Cannot access UIBezierPath in a NSMutable array

so I have a [NSMutableArray *paths] that contains UIBezierPaths that correspond to each separate path drawn on the screen. I also have another NSMutable array colors that contains the corresponding color for the path. The problem that I am having is that although the two arrays are mutating and I can see the count of both going up, the following drawRect method only seems to draw the last path in the array.
I have scoured through a lot of questions and based on what I have read so far, this very problem seems to get us newbies and mostly because of type mismatch. I even tried to Typecast the return and it was futile.
Here is my code from the drawRect
int cnt = paths.count;
if (cnt != 0)
{
for(int i = 0; i < cnt; i++)
{
NSLog(#"Drawing path:%i", i);
UIColor *color;
color = [colors objectAtIndex:i];
[color setStroke];
UIBezierPath *path = [paths objectAtIndex:i];
path.lineWidth = 2;
[path stroke];
}
}
every time I call [self setNeedsDisplay] it wipes out my entire screen.
Am I correct in assuming that I am not handling my
UIBezierPath *path = [paths objectAtIndex:i];
well?
Thank you very much and in advance.
UPDATE:
I was rummaging through some more codes and now it almost looks like there is another possibility that ARC is releasing the contents of my NSMutable array. I tried the do the following and got a compiler error.
[paths retain];
Besure you add your path to your path array afer each draw
- (void)drawRect:(CGRect)rect {
[brushPattern setStroke];
UIBezierPath *drawPath = [UIBezierPath bezierPath];
drawPath.lineCapStyle = kCGLineCapRound;
drawPath.miterLimit = 0;
drawPath.lineWidth = thisLineWidth;
for (UIBezierPath *path in pathArray)
[drawPath appendPath:path];
UIBezierPath *path = [self pathForCurrentLine];
if (path)
[drawPath appendPath:path];
[drawPath stroke];
}
- (UIBezierPath*)pathForCurrentLine {
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:startPoint];
[path addLineToPoint:endPoint];
return path;
}

NSString problems

I have problems with a simple NSString on Mac OS X:
NSString *letters = #"abcdefghijklmnopqrstuvwxyz0123456789";
myString = [myString stringByAppendingFormat:#"%c", [letters characterAtIndex:3]];
When I try to access this string again, Xcode is returning EXC_BAD_ACCESS
This error just occures, when I'm using the format #"%c"
When I'm using #"%#", sometimes the same error, sometimes this string: control 0x10040a480 and sometimes this:
{(
<CFRunLoopObserver 0x10015ac60 [0x7fff70731ee0]>{locked = No, valid = Yes, activities = 0x21, repeats = Yes, order = 0, callout = _ZL15FlushAllBuffersP19__CFRunLoopObservermPv (0x7fff88a147d4), context = <CFRunLoopObserver context 0x0>}
)}
The errors occur randomly even, if I don't change anything in the code and re-run it.
I try to get a random String by doing:
randomString = #"";
NSString *letters = #"abcdefghijklmnopqrstuvwxyz0123456789";
srand(time(NULL));
for (int i=0; i<5; i++)
{
randomString = [randomString stringByAppendingFormat:#"%c", [letters characterAtIndex:(rand()%[letters length])]];
}
randomString is declared in header.h
I also tried using a NSMutableString but that didn't work too.
Every time I try to access the string (or mutable string) via #"%#" I'm getting EXC_BAD_ACCESS
Any idea?
Hope somebody can help me!
Greets,
Julian
Your problem is that myString gets autoreleased before you access it.
You need to change:
myString = [myString stringByAppendingFormat:#"%c", [letters characterAtIndex:3]];
to:
myString = [[myString stringByAppendingFormat:#"%c", [letters characterAtIndex:3]] retain];
Remember to run [myString release]; when you are done with it.
this works for me:
define letters at top of file:
#define letters #"abcdefghijklmnopqrstuvwxyz0123456789"
then append a random character like this:
NSString *randomString = #"";
for (int i = 0; i < 5; i++)
{
UInt64 index = rand() % [letters length];
NSString *randomCharacter = [letters substringWithRange: NSMakeRange(index, 1)];
randomString = [randomString stringByAppendingString:randomCharacter];
}
NSLog(#"%#", randomString);

Resources