Count number of zero(0) using objective-c - objective-c

I want to count how many number of zero(0) before numeric number. Because I need to save those number which is present before numeric.
Exam:- suppose I have a number 0000102. So I want to calculate how many zero(0) before numeric start. In this exam we are see here is 4 zero's(0) are present. It is possible to calculate this?

for (i=0;i<string.length;i++)
{
if ([[string characterAtIndex:i] intValue] <= 9 || [[string characterAtIndex:i] intValue] > 0 )
{
i++;
}
else
{
numerOfZeros++;
}
}

int count = 0;
NSString *strr = #"0000102";
unichar findC;
for (int i = 0; i<strr.length; i++)
{
findC = [strr characterAtIndex:i];
if (findC == '0')
{
count++;
}
else
break;
}
NSLog(#"%d",count);

Recursive approach for a one liner:
#implementation NSString (category)
- (NSUInteger)zeroPrefixCount
{
return [string hasPrefix:#"0"] ? 1 + [[string substringFromIndex:1] zeroPrefixCount] : 0;
}
#end
This is not an optimal solution, performance-wise, but it's typical of your first days at programming classes.
usage
// x will be 4
NSUInteger x = [#"0000102" zeroPrefixCount];

I recommend you to save this kind of numbers as String itself and no need to further evaluate how many zeros are there rather do a string comparison if needed.
If you really want to count zeros in your number then you can consider converting it to a string and use NSRange and NSString helper methods to get what you want. Similar situation is answered here.
search if NSString contains value

Related

Objective-C: Improve function

I´m new to developing apps and I would like to have some hints about the code I have here:
- (IBAction)button_increase_click:(id)sender {
int number = [self.label_content.text intValue];
number+=1;
NSString *increased_value = [NSString stringWithFormat:#"%d",number];
int count = [increased_value length];
while (count<4) {
increased_value = [NSString stringWithFormat:#"%#%#", #"0",increased_value];
count = [increased_value length];
}
self.label_content.text = increased_value;
}
What I need to do is to increase the value of "label_content" by 1 and fill it with leading zeros until it has reached 4 digits. eg "0001" "0013" "0132".
So how can I improve the above code and take care of its readability?
Thank you for helping me out.
The method can look like this:
- (IBAction)button_increase_click:(id)sender {
int number = [self.label_content.text intValue];
number++;
self.label_content.text = [NSString stringWithFormat:#"%04d", number];
}
Update For increasing readability use camel case for ivar method and other names. It's standard for iOS.
- (IBAction)increaseValue:(id)sender {
int number = [self.contentLabel.text intValue];
number++;
self.contentLabel.text = [NSString stringWithFormat:#"%04d", number];
}
See Apple's String Format Specifiers Documentation.
A better number formatter:
int number = 4;
[NSString stringWithFormat:#"%04d",number];
NSLog(#"number: %04d", number);
NSLog output:
number: 0004

Matching strings, consider some characters are the same

please help me with this problem.
I want to check if the targetString match the keyword or not. Consider some character may different, but should still return true.
Example:
targetString = #"#ß<"
keyword = #"abc", #"∂B(", #"#Aß<"
result: all must return true.
(Matched.targetString and all keyword are the same.)
Consider me have an array, contains list of character set that can be the same:
NSArray *variants = [NSArray arrayWithObjects:#"aA#∂", #"bBß", #"c©C<(", nil]
So that when matching, with this rule, it can match as the example above.
Here is what i've done so far (using recursion):
- (BOOL) test:(NSString*)aString include:(NSString*) keyWord doTrim:(BOOL)doTrim {
// break recursion.
if([aString length] < [keyWord length]) return false;
// First, loop through each keyword's character
for (NSUInteger i = 0; i < [keyWord length]; i++) {
// Get #"aA#∂", #"bBß", #"c©C<(" or only the character itself.
// like, if the keyword's character is A, return the string #"aA#∂".
// If the character is not in the variants set, eg. P, return #"P"
char c = [keyWord characterAtIndex:i];
NSString *rs = [self variantsWithChar:c];
// Check if rs (#"aA#∂" or #"P") contains aString[i] character
if([rs rangeOfString:[NSString stringWithCharacters:[aString characterAtIndex:i] length:1]].location == NSNotFound) {
// If not the same char, remove first char in targetString (aString), recursion to match again.
return [self test:[aString substringFromIndex:1] include:keyWord doTrim:NO];
}
}
// If all match with keyword, return true.
return true;
}
- (NSString *) variantsWithChar:(char) c {
for (NSString *s in self.variants) {
if ([s rangeOfString:[NSString stringWithFormat:#"%c",c]].location != NSNotFound) {
return s;
}
}
return [NSString stringWithFormat:#"%c", c];
}
The main problem is, variantsWithChar: doesn't return the correct string. I don't know which datatype and which function should I use here. Please help.
For thou who know ruby, here's the example in ruby. It work super fine!
require 'test/unit/assertions'
include Test::Unit::Assertions
class String
def matching?(keyword)
length >= keyword.length && (keyword.chars.zip(chars).all? { |cs| variants(cs[0]).include?(cs[1]) } || slice(1, length - 1).matching?(keyword))
end
private
VARIANTS = ["aA#∂", "bBß", "c©C<("]
def variants(c)
VARIANTS.find { |cs| cs.include?(c) } || c
end
end
assert "abc".matching?("#ß<")
PS: The fact is, it's containt a japanese character set that sounds the same (like あア, いイ... for thou who know japanese)
PS 2: Please feel free to edit this Question, since my engrish is sooo bad. I may not tell all my thought.
PS 3: And, maybe some may comment about the performance. Like, search about 10,000 target words, with nearly 100 variants, each variant have at most 4 more same characters.
So first off, ignore comments about ASCII and stop using char. NSString and CFString use unichar
If what you really want to do is transpose hiragana and katakana you can do that with CFStringTransform()
It wraps the ICU libraries included in OS X and iOS.
It makes it very simple.
Search for that function and you will find examples of how to use it.
After a while (a day) working on the code above, I finally get it through. But don't know about the performance. Someone comment and help me improve about performance, please. Thanks.
- (BOOL) test:(NSString*)aString include:(NSString*) keyWord doTrim:(BOOL)doTrim {
// break recursion.
if([aString length] < [keyWord length]) return false;
// First, loop through each keyword's character
for (NSUInteger i = 0; i < [keyWord length]; i++) {
// Get #"aA#∂", #"bBß", #"c©C<(" or only the character itself.
// like, if the keyword's character is A, return the string #"aA#∂".
// If the character is not in the variants set, eg. P, return #"P"
NSString* c = [NSString stringWithFormat:#"%C", [keyWord characterAtIndex:i]];
NSString *rs = [self variantsWithChar:c];
NSString *theTargetChar = [NSString stringWithFormat:#"%C", [aString characterAtIndex:i]];
// Check if rs (#"aA#∂" or #"P") contains aString[i] character
if([rs rangeOfString:theTargetChar].location == NSNotFound) {
// If not the same char, remove first char in targetString (aString), recursion to match again.
return [self test:[aString substringFromIndex:1] include:keyWord doTrim:NO];
}
}
// If all match with keyword, return true.
return true;
}
If you remove all comment, it'll be pretty short...
////////////////////////////////////////
- (NSString *) variantsWithChar:(NSString *) c{
for (NSString *s in self.variants) {
if ([s rangeOfString:c].location != NSNotFound) {
return s;
}
}
return c;
}
You could try comparing ascii values of the japanese characters in the variants's each character's ascii value. These japanese characters aren't treated like usual characters or string. Hence, string functions like rangeOfString won't work on them.
to be more precise: have a look at the following code.
it will search for "∂" in the string "aA#∂"
NSString *string = #"aA#∂";
NSMutableSet *listOfAsciiValuesOfString = [self getListOfAsciiValuesForString:string]; //method definition given below
NSString *charToSearch = #"∂";
NSNumber *ascii = [NSNumber numberWithInt:[charToSearch characterAtIndex:0]];
int countBeforeAdding = [listOfAsciiValuesOfString count],countAfterAdding = 0;
[listOfAsciiValuesOfString addObject:ascii];
countAfterAdding = [listOfAsciiValuesOfString count];
if(countAfterAdding == countBeforeAdding){ //element found
NSLog(#"element exists"); //return string
}else{
NSLog(#"Doesnt exists"); //return char
}
===================================
-(NSMutableSet*)getListOfAsciiValuesForString:(NSString*)string{
NSMutableSet *set = [[NSMutableSet alloc] init];
for(int i=0;i<[string length];i++){
NSNumber *ascii = [NSNumber numberWithInt:[string characterAtIndex:i]];
[set addObject:ascii];
}
return set;
}

Objective-C compare string object from NSArray to a string for equality

How do I properly compare a string that I am retrieving from an NSArray to a literal string? So far, I have filled an NSArray up with three blank spaces, " " in one method and now I am trying to replace 10 random indexes in the NSArray with the string "C10", but I don't want to replace what is there unless it is " " still.
Here I created the array of size 100 and filled each spot with 3 blank spaces.
-(void) initBoard{
_board = [board initWithCapacity: 100];
for(int i =0; i < 100; i++){
[_board addObject:#" "];
}
}
Here is the method that I'm having problems with the equality comparison.
-(void)makeChutes: (int) numOfChutes {
//Make argument number of Chutes randomly across the board.
for(int i = 0; i < numOfChutes || i>(-100);){
int random = arc4random_uniform(101);
if ([[_board objectAtIndex:random] isEqual:#" "]) {
NSString *fString = [NSString stringWithFormat:#"C%d", 10];
[_board replaceObjectAtIndex:random withObject:fString];
i++;//Only increments i if 3 blank spaces were at random index..
}
else{//Used to attempt to stop my accidental infinite loop.
i--;
NSLog(#"I, loop, ran %i times.", i);//Attempt failed:-(
}
}
}
I know the above code is a mess. In an attempt to stop the looping I made the i decrement every time it did not meet the for condition and then added an OR condition to my for loop, using ||, to try and stop it after 100 cycles. For some reason the || condition does not stop it from looping even while i is well south of -100.
My first question is how do I properly compare the string stored in the array at index "random" with the literal string of 3 blank spaces? I also tried the method isEqualToString, but it worked the same.
Secondly and less importantly, since I don't need it now, how do I properly code a bi-conditional for loop? I don't get any errors or warnings from Xcode with my for loop syntax and it compiles and runs, so I don't really get why it ignores my second conditions and keeps iterating even while i is < -100.
to know the exist or not and index of it simply use ContainsObject property over NSArray
[array containsObject:#"text"];
int indexOfObject = [array indexOfObject:#"text"];
Use this method for string comparison
[[_board objectAtIndex:random] isEqualToString:#" "]
Modified your code. I think this is what you are looking for
-(void)makeChutes: (int) numOfChutes
{
for(int i = 0; i < numOfChutes ;i++){
int random = arc4random_uniform(101);
if ([[_board objectAtIndex:random] isEqualToString:#" "])
{
[_board replaceObjectAtIndex:random withObject:#"C10"];
i++;
}
}
}
EDIT :
Solution from what you said in comments
-(void)makeChutes: (int) numOfChutes
{
int i=0;
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF contains[cd] ' '"];
NSArray *filteredArray = [_board filteredArrayUsingPredicate:predicate];
int arrayCount=[filteredArray count];
do {
int random = arc4random_uniform(101);
if ([[_board objectAtIndex:random] isEqualToString:#" "])
{
[_board replaceObjectAtIndex:random withObject:#"C10"];
i++;
if (arrayCount == i) {
i=numOfChutes;
}
}
} while (i<numOfChutes);
}
EDIT
From the DOCS
isEqualToString: Returns a Boolean value that indicates whether a
given string is equal to the receiver using a literal Unicode-based
comparison.
(BOOL)isEqualToString:(NSString *)aString Parameters aString The string with which to compare the receiver. Return Value YES if aString
is equivalent to the receiver (if they have the same id or if they are
NSOrderedSame in a literal comparison), otherwise NO.
Discussion The comparison uses the canonical representation of
strings, which for a particular string is the length of the string
plus the Unicode characters that make up the string. When this method
compares two strings, if the individual Unicodes are the same, then
the strings are equal, regardless of the backing store. “Literal” when
applied to string comparison means that various Unicode decomposition
rules are not applied and Unicode characters are individually
compared. So, for instance, “Ö” represented as the composed character
sequence “O” and umlaut would not compare equal to “Ö” represented as
one Unicode character.
My "initBoard" method was broken, causing the "makeChutes" method not to work as expected. Here is the correct initBoard:
-(void) initBoard{
_board = [[NSMutableArray alloc] initWithCapacity:100];
for(int i =0; i < 100; i++){
[_board addObject:#" "];
}
}
And the corrected makeChutes:
-(void)makeChutes: (int) numOfChutes{
//Make argument number of Chutes randomly across the board.
for(int i = 0; i < numOfChutes;){
int random = arc4random_uniform(100);//+1 of max index
if ([[_board objectAtIndex:random] isEqualTo:#" "]){
NSString *fString = [NSString stringWithFormat:#"C%d", 10];
[_board replaceObjectAtIndex:random withObject:fString];
i++;//Only increments i if 3 blank spaces were at random index.
}
}
}

obtaining objective c nsstring from c char[]

code below.
i'm tryind to obtain string answers like "a1", "c4"
this is what i'm having instead of "a1": "adresse finale: \340}00\214"
with this prinf:
printf("\nadresse finale: %s",[self convertCGPointToSquareAdress:self.frame.origin]);
the method is:
-(NSString *) convertCGPointToSquareAdress:(CGPoint ) point{
int x= point.x /PIECE_WIDTH;
int y=point.y/PIECE_WIDTH;
char lettreChiffre[2];
//char chiffre;
NSString *squareAdress;
//ascii a=97 , b=98... h=105
for (int i=97; i<105; i++) {
for (int j=8; j>0; j--) {
if(i-97==x && j-1==y ){
NSLog(#"enterrrrrrrrrred if convertCGPointToSquareAdress");
lettreChiffre[0]=i;
lettreChiffre[1]=(char) j;
printf(" lettreChiffre: %s ", lettreChiffre);
NSString *squareAdress=[NSString stringWithFormat:#"%s", lettreChiffre];
break;
}
}
}
return squareAdress;
}
can you please help me?
thanks in advance.
There are three problems I can see with your code:
1.
When you do
lettreChiffre[1]=(char) j;
remember j is a number between 1 and 8, so you're getting the ASCII character whose value is j, not the character 1...8. You should use
lettreChiffre[1]= '0' + j;
2.
lettreChiffre is a char array of length 2, which means there's no room for the terminal null character. This may work, but may give you gibberish. You should instead declare
char lettreChiffre[3];
lettreChiffre[2] = '\0';
3.
You're trying to use printf to print an NSString, which it can't do. Either use
NSLog(#"adresse finale: %#", mynsstring)
or convert the NSString back to a C-string:
printf("adresse finale: %s", [mynsstring UTF8String]);
Also, as noted by #dreamlax, you don't really need the loop. I assumed you were doing something else and ran into this trouble, so we're not really seeing the full code. But, if this is really the entirety of your code, then you can simply remove the loop as #dreamlax suggested.
What is the purpose of the loop? You have a loop that essentially brute forces a matrix to calculate the “square address”. Your method will also return an uninitialized pointer if x is greater than 8.
Your entire method could be made much simpler.
- (NSString *) convertCGPointToSquareAdress:(CGRect) point
{
unsigned int x = point.x / PIECE_WIDTH;
unsigned int y = point.y / PIECE_WIDTH;
// Do some range checking to ensure x and y are valid.
char lettreChiffre[3];
lettreChiffre[0] = 'a' + x;
lettreChiffre[1] = '1' + y;
lettreChiffre[2] = '\0';
return [NSString stringWithCString:letterChiffre encoding:NSASCIIStringEncoding];
}

I want to insert the line-feed character in the specified number of characters

Objective-C::
I want to insert the line-feed character in the specified number of characters.
Please teach when knowing.
for example
NSString str = #"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
?????? // -> #"aaaaa\naaaaa\naaaaa\n......"
No, apparently I don't have anything better to do on a Friday night than to answer random ancient "my tags" questions asked by people who were never that interested in the first place and have anyway long since departed SO.
-(NSString*)breakString:(NSString*)str everyNCharacters:(NSUInteger)n withDelimiter:(NSString*)delimiter
{
NSUInteger numBreaks = ([str length] / n) - (([str length] % n == 0) ? 1 : 0);
if ( numBreaks < 1 )
return str;
NSMutableString* result = [NSMutableString stringWithCapacity:([str length] + [delimiter length] * numBreaks)];
for ( int i = 0; i < numBreaks; ++i )
{
[result appendFormat:#"%#%#", [str substringWithRange:NSMakeRange(i * n, n)], delimiter];
}
[result appendString:[str substringFromIndex:(n * numBreaks)]];
return result;
}
In the specific case of the question, call thus:
NSString* answer = [arbitraryObjectContainingTheAboveMethod breakString:str everyNCharacters:5 withDelimiter:#"\n"];
Time for bed, said Zebedee.