NSString comparing - objective-c

I am searching for an algorithm where I can compare two strings and read out the failers.
I know the normal code to compare two strings but this isn't enough.
Example:
NSString *userinput = #"xaplseiPhonr";// (Input from the user)
NSString *correct =#"apple iphone";
In the next step i would check this strings and put out the failers for this example: x,l,s, ,r = 5 failers
I tested many things, saved the two strings in an array with two for-loops and compared it but something is wrong, the hardest thing is if the word has 2 letters that are the same. Or if you have no dynamic index search then are the whole letters after the "l" or the missing space in the userinput false, and so on.
So, It would be nice if anyone has fine code for me
edit: code to compare, but this doesn't work if you missed a letter or space.
for (int i = 0; i < [originalWordLetters count]; i++)
{
NSString *originalLetter = [originalWordLetters objectAtIndex:i];
//NSLog(#"%i: %#", d, originalLetter);
BOOL letterFound = FALSE;
while (letterFound == FALSE && d < [userWordLetters count])
{
if ([originalLetter caseInsensitiveCompare:[userWordLetters objectAtIndex:d]] == NSOrderedSame)
{
//NSLog(#"letter %i correct", d+1);
letterFound = TRUE;
}
else
{
//NSLog(#"letter %i false", d+1);
failedLetters++;
}
d++;
}
}
I have a working algorithm where you can compare two strings. And put out the mistakes
I've uploaded the sample project to GitHub:
NSString compareTwoStrings: algorithm outputs the mistakes

What you want to do is compute the Damerau-Levenshtein distance between two strings. Here is an open source implementation for NSString: GitHub JanX2/NSString-DamerauLevenshtein

You can use NSScanner to do this.

Related

Comparing string to a character of another string?

Here's my program so far. My intention is to have it so the if statement compares the letter in the string letterGuessed to a character in the string userInputPhraseString. Here's what I have. While coding in xCode, I get an "expected '['"error. I have no idea why.
NSString *letterGuessed = userInputGuessedLetter.text;
NSString *userInputPhraseString = userInputPhraseString.text;
int loopCounter = 0;
int stringLength = userInputPhraseString.length;
while (loopCounter < stringLength){
if (guessedLetter isEqualToString:[userInputPhraseString characterAtIndex:loopIndexTwo])
{
//if statement true
}
loopCounter++;
}
You are missing enclosing square brackets on this line:
if (guessedLetter isEqualToString:[userInputPhraseString characterAtIndex:loopIndexTwo])
It should be:
if ([guessedLetter isEqualToString:[userInputPhraseString characterAtIndex:loopIndexTwo]])
Edit that won’t fix your problem, though, because characterAtIndex: returns a unichar, not an NSString.
It's not clear what you are trying to do.. But I suppose that letterGuessed has one character... And that userInputPhraseString has many characters. So you want to know if letterGuessed is inside userInputPhraseString correct?
This is one solution without loops involved.. I replaced the input with fixed values for testing and tested the code.. It works.
NSString *letterGuessed = #"A"; //Change to your inputs
NSString *userInputPhraseString = #"BBBA"; //Since it has A it will be true in the test
NSCharacterSet *cset = [NSCharacterSet characterSetWithCharactersInString:letterGuessed];
NSRange range = [userInputPhraseString rangeOfCharacterFromSet:cset];
if (range.location != NSNotFound) { //Does letterGuessed is in UserInputPhraseString?
NSLog(#"YES"); //userInput Does contain A...
} else {
NSLog(#"NO");
}
In regards to your code... I fixed a couple of errors, first you are trying to get a UniChar (Integer) value for the character and want to compare it to a NSString which is an Object. Also fixed a couple of issues with syntax you had and used the right approach which is to return a range of characters. Again for doing what you want to accomplish the example above is the best approach I know, but for the sake of learning, here is your code fixed.
NSString *letterGuessed = #"A"; //Change to your inputs
NSString *userInputPhraseString = #"BBBA"; //Since it has A it will be true in the test
NSInteger loopCounter = 0; //Use NSInteger instead of int.
NSInteger stringLength = userInputPhraseString.length;
BOOL foundChar = NO; //Just for the sake of returning NOT FOUND in NSLOG
while (loopCounter < stringLength){
//Here we will get a letter for each iteration.
NSString *scannedLetter = [userInputPhraseString substringWithRange:NSMakeRange(loopCounter, 1)]; // Removed loopCounterTwo
if ([scannedLetter isEqualToString:letterGuessed])
{
NSLog(#"FOUND CHARACTER");
foundChar = YES;
}
loopCounter++;
}
if (!foundChar) NSLog(#"NOT FOUND");
NSRange holds the position, length.. So we move to a new position on every iteration and then get 1 character.
Also if this approach is what you want, I would strongly suggest a for-loop.

Converting a string variable from Binary to Decimal in Objective C

Im trying to create a Binary to Decimal calculator and I am having trouble doing any sort of conversion that will actually work. First off Id like to introduce myself as a complete novice to objective c and to programming in general. As a result many concepts will appear difficult to me, so I am mostly looking for the easiest way to understand and not the most efficient way of doing this.
I have at the moment a calculator that will accept input and display this in a label. This part is working fine and I have no issues with it. The variable that the input is stored on is _display = [[NSMutableString stringWithCapacity:20] retain];
this is working perfectly and I am able to modify the data accordingly. What I would like to do is to be able to display an NSString of the conversion in another label. At the moment I have tried a few solutions and have not had any decent results, this is the latest attempt
- (NSMutableString *)displayValue2:(long long)element
{
_str= [[NSMutableString alloc] initWithString:#""];
if(element > 0){
for(NSInteger numberCopy = element; numberCopy > 0; numberCopy >>= 1)
{
[_str insertString:((numberCopy & 1) ? #"1" : #"0") atIndex:0];
}
}
else if(element == 0)
{
[_str insertString:#"0" atIndex:0];
}
else
{
element = element * (-1);
_str = [self displayValue2:element];
[_str insertString:#"0" atIndex:0];
NSLog(#"Prima for: %#",_str);
for(int i=0; i<[_str length];i++)
_str = _display;
NSLog(#"Dopo for: %#",_str);
}
return _str;
}
Within my View Controller I have a convert button setup, when this is pressed I want to set the second display field to the decimal equivalent. This is working as if I set displayValue2 to return a string of my choosing it works. All I need is help getting this conversion to work. At the moment this bit of code has led to "incomplete implementation" being displayed at the to of my class. Please help, and cheers to those who take time out to help.
So basically all you are really looking for is a way to convert binary numbers into decimal numbers, correct? Another way to think of this problem is changing a number's base from base 2 to base 10. I have used functions like this before in my projects:
+ (NSNumber *)convertBinaryStringToDecimalNumber:(NSString *)binaryString {
NSUInteger totalValue = 0;
for (int i = 0; i < binaryString.length; i++) {
totalValue += (int)([binaryString characterAtIndex:(binaryString.length - 1 - i)] - 48) * pow(2, i);
}
return #(totalValue);
}
Obviously this is accessing the binary as a string representation. This works well since you can easily access each value over a number which is more difficult. You could also easily change the return type from an NSNumber to some string literal. This also works for your element == 0 scenario.
// original number wrapped as a string
NSString *stringValue = [NSString stringWithFormat:#"%d", 11001];
// convert the value and get an NSNumber back
NSNumber *result = [self.class convertBinaryStringToDecinalNumber:stringValue];
// prints 25
NSLog(#"%#", result);
If I misunderstood something please clarify, if you do not understand the code let me know. Also, this may not be the most efficient but it is simple and clean.
I also strongly agree with Hot Licks comment. If you are truly interested in learning well and want to be an developed programmer there are a few basics you should be learning first (I learned with Java and am glad that I did).

Parsing arithmetic expression for long numbers that need formatting

I am trying to make a simple calculator app. Currently, the app works perfectly. One problem: It's smart enough to change results into formatted numbers (800000 = 800,000), but not full expressions (200*600/21000 = 200*600/21,000).
I would like to be able to have a method that I could feed a string and get back a string of properly formatted numbers with operations still inside the string.
Example:
I feed the method 30000/80^2. Method gives back 30,000/80^2.
EDIT: People seem to be misunderstanding the question (Or it's possible I am misunderstanding the answers!) I want to be able to separate the numbers - 60000/200000 would separate into 60000 & 200000. I can do it from there.
Well, what's the problem? You obviously can parse the whole expression (you say calculator works), you can format single numbers (you say you can format results).
The only thing you need is to parse the expression, format all the numbers and recompose the expression...
EDIT: There is a simpler solution. For formatting, you don't need to parse the expression into a tree. You just have to find the numbers.
I suggest to create character set of all operators
NSCharacterSet* operators = [NSCharacterSet characterSetWithCharactersInString:#"+*-/^()"];
NSCharacterSet* whitespaces = [NSCharacterSet whitespaceCharacterSet];
Then split the expression using this set:
NSString* expression = [...];
NSMutableString* formattedExpression = [NSMutableString string];
NSRange numberRange = NSMakeRange(0, 0);
for (NSUInteger i = 0; i < expression.length; i++) {
unichar character = [expression characterAtIndex:i];
if ([whitespaces characterIsMember:character] || [operators characterIsMember:character]) {
if (numberRange.length > 0) {
NSString* number = [expression substringWithRange:numberRange];
NSString* formattedNumber = [self formatNumber:number];
[formattedExpression appendString:number];
numberRange.length = 0;
}
}
else if (numberRange.length == 0) {
numberRange.location = i;
numberRange.length = 1;
}
else {
numberRange.length++;
}
if ([operators characterIsMember:character]) {
[formattedExpression appendFormat:#"%C", character];
}
}
if (numberRange.length > 0) {
NSString* number = [expression substringWithRange:numberRange];
NSString* formattedNumber = [self formatNumber:number];
[formattedExpression appendString:number];
}
Note that this should work even for numbers prefixed by a sign. I am ignoring all whitespaces because if you want to have a pretty expression, you probably want to handle whitespaces differently (e.g. no space after (, space before +/-, space after - only if it's not a number sign...). In general, for handling spaces, parsing the expression into a tree would simplify matters. Also note that infix expressions are not unambiguous - that means that you should sometimes add parenthesis. However, that can't be done without parsing into a tree.
Look up NSNumberFormatter. Not only will that handle formatting of numbers, it will do so based on the user's locale.

Eliminating Abbreviations in UITextChecker

I am trying to create an app in which random words are generated, however I want abbreviations to be ignored when they are created. To do this i randomly generate an array of letters, (Weighting them with the same weighting as scrabble ;P) and then run through the array checking for correct words using UITextChecker like so:
for (int i = 0; i < 14; i++) {
[word setString:#""];
for (int j = i; j < 14 ;j++) {
[word appendString:[letterArray objectAtIndex:j]];
NSRange misspelledWord = [checkText rangeOfMisspelledWordInString:word range:NSMakeRange(0, word.length) startingAt:0 wrap:NO language:#"en_GB"];
if (misspelledWord.location == NSNotFound && word.length > 2) {
NSRange misspelledWordSecondRun = [checkText rangeOfMisspelledWordInString:word range:NSMakeRange(0, word.length) startingAt:0 wrap:NO language:#"en_US"];
if (misspelledWordSecondRun.location == NSNotFound) {
NSLog(#"You generated the word: %#",word);
}
}
else {
}
}
}
The only problem is that this lets a ridiculous amount of abbreviations and acronyms through... is there any way I can reduce this number? There must be a language that I can send checkText which is an abbreviation free version of the english dictionary? Or some way of telling it to flag acronyms as misspelled words? As you can see I have tried to reduce the number by filtering the words a second time using us english rather than uk english, however this doesn't reduce the number of acronyms being let through at all :/
Implemented this using an array of words that I didn't want to include, each time a word is generated it checks to see if it's in this array. If it is it doesn't register it as a word, if it isn't it doesn't.

Matching Strings in Objective C

I have a for loop which loops through an array and want to match a search field's text to an object in the array.
I have the following code
for (int i = 0; i < [data2 count]; i++) {
if ([data2 objectAtIndex:i] == searchField.text) {
NSLog(#"MATCH");
break;
}
}
I know in Java it can be done by e.g. if(searchField.text.equalsIgnoreCase(the object to match against))
How is this done in objective C, to match the string without case?
Also, what if I wanted to match part of the string, would that be done in Obj C char by char or is there a built in function for matching parts of Strings?
Thanks
Assuming your strings are NSStrings, you can find your answers at the NSString Class Reference
NSString supports caseInsensitiveCompare: and rangeOfString: or rangeOfString:options: if you want a case insensitive search.
The code would look like this:
if (NSOrderedSame == [searchField.text caseInsensitiveCompare:[data2 objectAtIndex:i]) {
// Do work here.
}
[[data2 objectAtIndex:i] isEqualToString: searchField.text]
You use isEqual: (to compare objects in general) or isEqualToString: (for NSStrings specifically). And you can get substrings with the substringWithRange: method.