Objective-c - get count elements of an array - objective-c

I'm an Objective-C rookie, and I want to get the elements count of an array of chars. I managed to find only this way:
#autoreleasepool {
char parola[30];
int c;
NSLog(#"Write word:");
scanf("%c",&parola[30]);
c = sizeof(parola)/sizeof(parola[0]);
NSLog(#"The word has %i letters",c);
}
return 0;
The problem is that it gives me the length I specified in the array declaration, not the elements count.
Any idea?

You have a few errors there.
You want the user to input a "word", i.e. a string. Then don't use %c, which only scans one character, but %s instead, which scans one string (note that that can mean that the user also enters spaces, or more than 29 characters).
You store beyond the array. The array is declared as
char parola[30];
That means it can be indexed with values 0 .. 29. But your &parola[30] points beyond the array (at index 30, which does not "exist"). That is not what you want. Do this:
scanf("%s", parola);
And hope that the user doesn't enter more than 29 characters.
The length of the string can then be found using
c = strlen(parola);
So this becomes:
#autoreleasepool {
char parola[30];
unsigned long c;
NSLog(#"Write word:");
scanf("%s", parola);
c = strlen(parola);
NSLog(#"The word has %ld letters", c);
}
return 0;
Instead of NSLog, you can also use printf:
printf("Write word: ");
and
printf("The word has %ld letters\n", c);
That will look cleaner, as NSLog() always shows these extra infos, like
2017-06-04 12:37:25.758802+0200 SOTest[4718:2690388]
And that is, IMO, plain ugly. Good for a log, but not good for clean screen output. The output now becomes:
Write word: Tesla
The word has 5 letters
Program ended with exit code: 0

Related

Objective-C Displaying Numbers as Words Using Math

I have an exercise in my Objective-C book in which I must design a program using only the knowledge the book has given me so far to do so. It tells me to use math to do this not any methods from Objective-C.
What I must do is get any integer from the user and then convert each number to a word.
For example if the user enters: 956
The output must then be:
nine
five
six
I am not the best math student and definitely need help here. I can of course use loops of any kind as well as if statements and basic math operators as well as arrays but no built in methods.
I assume that I need to get each digit separated into its own integer variable and then use switch of if statements to then create the strings and display them but cannot successfully do this.
Please help, thanks!
Here's an example I quickly came up with. See the comments in the code below for an explanation.
//Create an array of number strings. They must be in order starting from 0 so the indexes line up
NSArray *numbers = #[#"zero", #"one", #"two", #"three", #"four", #"five", #"six", #"seven", #"eight", #"nine"];
//Create whatever string you're processing
NSString *numString = #"956";
//Loop through the substrings of the number string
while (numString.length > 0) {
//Get the first character in the string
int currentNum = [[numString substringToIndex:1] intValue];
//Print the number. The number string should be at the index of this value in the array
NSLog(#"%#", numbers[currentNum]);
//Remove everything before the first character
numString = [numString substringFromIndex:1];
}
Output:
nine
five
six
Here is a working example using C (one of your tags):
This one makes use of a char *[] (array of C strings) and ascii values of each char...
char *number[]={"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
int main(void)
{
char dig[20];
int len, i;
printf("enter integer: "); //instruction to user
scanf("%s", dig); //read from user
len = strlen(dig);
for(i=0;i<len;i++)
{
if(isdigit(dig[i]))//test to verify good user input (accept only digits)
{
printf("%s\n", number[dig[i]-48]); // 48-57 is range of ASCII values for 0-9
}
}
return 0;
}
Example session:

How split a string by equial parts?

How I can split a string into equal parts and not a character, ie, a string that is 20 characters divided into 5 strings with 2 characters each no matter what kind of character is?
don't work to me [NSString componentsSeparatedByString]: because the characters change randomly.
i'm using objetive-c on xcode 5
This is just an example of what you're probably looking to do. This method assumes the length of the string is evenly divisible by the intended substring length, so having a test string with 20 characters and a substring length of 2, will produce an array with 10 substrings with 2 characters in each. If the test string is 21 characters the 21st char will be ignored. Once again, this is not THE way to do exactly what you want to do (which still isn't totally clear), but it is merely a demonstration of something similar to what you may want to be doing:
// create our test substring (20 chars long)
NSString *testString = #"abcdefghijklmnopqrstu";
// our starting point will begin at 0
NSInteger startingPoint = 0;
// each substring will be 2 characters long
NSInteger substringLength = 2;
// create our empty mutable array
NSMutableArray *substringArray = [NSMutableArray array];
// loop through the array as many times as the substring length fits into the test
// string
for (NSInteger i = 0; i < testString.length / substringLength; i++) {
// get the substring of the test string starting at the starting point, with the intended substring length
NSString *substring = [testString substringWithRange:NSMakeRange(startingPoint, substringLength)];
// add it to the array
[substringArray addObject:substring];
// increment the starting point by the amount of the substring length, so next iteration we
// will start after the last character we left off at
startingPoint += substringLength;
}
The above produced this:
2014-08-23 15:33:41.662 NewTesting[49723:60b] (
ab,
cd,
ef,
gh,
ij,
kl,
mn,
op,
qr,
st )

Count number of arbitrary repeating decimal numbers in NSString

In my code, I'm dealing with an NSString that contains an NSNumber value. This NSNumber value could possibly be a repeating decimal number (e.x. 2.333333333e+06) that shortens to "2.333333" in a string format. It could also be a terminating number (e.x. 2.5), negative, or irrational number (2.398571892858...) (only dealing with decimals here)
I need to have a way to figure out if there are the repeating numbers in the string (or the NSNumber, if necessary). In my code, I would have no way to know what the repeating number would be, as it's a result of computations started by the user. I have tried this for loop (see below) that doesn't work the way I want it to, due to my inexperience with string indexing/ranges/lengths.
BOOL repeat = NO; //bool to check if repeating #
double repNum, tempNum; //run in for loop
NSString *repeating = [numVal stringValue]; //string that holds possible repeating #
for (int i = 3; i <= [repeating length]-3; i++) { //not sure about index/length here
if (i == 3) {
repNum = [repeating characterAtIndex:i];
}
tempNum = [repeating characterAtIndex:i];
if (tempNum == repNum) {
repeat = YES;
} else {
repeat = NO;
}
}
This code doesn't work as I'd like it to, mainly because I also have to account for negative dashes in the string and different amounts of numbers (13 1/3 vs. 1 1/3). I've used the modffunction to separate the integers from the decimals, but that hasn't worked well for me either.
Thank you in advance. Please let me know if I can clarify anything.
EDIT:
This code works with the finding of different solutions for polynomials (quadratic formula). Hope this helps put it into context. See here. (Example input)
NSNumber *firstPlusSolution, *secondMinusSolution;
NSString *pValueStr, *mValueStr;
firstPlusSolution = -(b) + sqrt(square(b) - (4)*(a)*(c)); //a, b, c: "user" provided
firstPlusSolution /= 2*(a);
secondMinusSolution = -(b) - sqrt(square(b) - 4*(a)*(c));
secondMinusSolution /= 2*(a);
pValueStr = [firstPlusSolution stringValue];
mValueStr = [secondMinusSolution stringValue];
if ([NSString doesString:pValueStr containCharacter:'.']) { //category method I implemented
double fractionPart, integerPart;
fractionPart = modf(firstPlusSolution, &integerPart);
NSString *repeating = [NSString stringWithFormat:#"%g", fractionPart];
int repNum, tempNum;
BOOL repeat = NO;
//do for loop and check for negatives, integers, etc.
}
if ([NSString doesString:mValueStr containCharacter'.']) {
//do above code
//do for loop and check again
}
Use C. Take the fractional part. Convert to a string with a known accuracy. If length of string indicates that last digits are missing, then it does not repeat. Use NSString-UTF8String to convert a string. Get rid of the last digit (may be rounding or actual floating point arithmetic error). Use function int strncmp ( const char * str1, const char * str2, size_t num ) to perform comparison within the string itself. If the result is 8 characters long and the last 2 characters match the first 2 characters, then shall the first 6 characters be considered repeating?
Assuming that fraction knowledge your desire:
• Possibility 1: Use fractions. Input fractions. Compute with fractions. Output fractions. Expand upon one of the many examples of a c++ fraction class if necessary and use it.
• Possibility 2: Choose an accuracy which is much less than double. Make a fraction from the result. Reduce the fraction allowing rounding based upon accuracy.
I suggest use not optimal but easy to write solution
Create NSMutableDictionary that will contain number as key and count of occurrence as value.
You can use componentsSeparatedByString: if numbers in string delimited by known symbol
In loop check valueForKey in dictionary and if need increase value
Last step is analyzing our dictionary and do anything you need with numbers

Concatenating an int to a string in Objective-c

How do I concatenate the int length to the string I'm trying to slap into that array so it is "C10" given length == 10, of course. I see #"%d", intVarName way of doing it used else where. In Java I would of done "C" + length;. I am using the replaceObjectAtIndex method to replace the empty string, "", that I have previously populated the MSMutableArray "board" with. I am getting an error though when I add the #"C%d", length part at the end of that method (second to last line, above i++).
As part of my homework I have to randomly place "Chutes" (represented by a string of format, "C'length_of_chute'", in this first assignment they will always be of length 10 so it will simply be "C10") onto a game board represented by an array.
-(void)makeChutes: (int) length {// ??Change input to Negative number, Nvm.
//??Make argument number of Chutes ??randomly?? across the board.
for(int i = 0; i < length;){
int random = arc4random_uniform(101);
if ([[board objectAtIndex:random] isEqual:#""]) {
//[board insertObject:#"C%d",length atIndex:random];
[board replaceObjectAtIndex:random withObject:#"C%d",length];
i++;
}
}
}
Please ignore the extra and junk code in there, I left it in for context.
In Objective-C the stringWithFormat method is used for formatting strings:
NSString *formattedString = [NSString stringWithFormat:#"C%d", length];
[someArray insertObject:formattedString];
It's often easier to create your formatted string on a line of its own in Objective-C, since as you can see the call can be fairly verbose!

Questions about validating user input in Objective-C, number vs string

Why 'exactly' does this code loop endlessly if you enter a non number character?
The first question comes about because I want to learn good defensive coding. Does anyone know a good way to check user input? My google-fu failed me. Some people seemed to be of the opinion that if I specify %f in scanf that I am 'demanding' a float; I verified this, in a way, by printing the value of userInput. In fact, if I comment out the do while loop, there is 'no problem' with the execution of the code. It assigns a 0 to userInput and goes about its business.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
float userInput;
float result;
NSLog(#"3X^3 -5x^2 + 6");
do {
NSLog(#"What is x?");
scanf("%f", &userInput);
NSLog(#"userInput = %f", userInput);
} while(userInput == 0);
result = 3 * (userInput * userInput * userInput) - 5 * (userInput * userInput) + 6;
NSLog(#"the result is: %f", result);
[pool drain];
return 0;
}
This is really nothing to do with Objective-C or Cocoa. The issue is simply to do with the use of the standard C library function scanf, and handling the error condition. From the scanf manpage, describing the return code:
Zero indicates that, although there was input available, no conversions were assigned; typically this is due to an invalid input character, such as an alphabetic character for a `%d' conversion.
A valid numeric input can be parsed by scanf with the %f specifier, so that obviously works as expected. But if you enter in a non-numeric character, scanf cannot convert this to a float, and leaves the text in the buffer of stdin. Since the code is not checking the return code from scanf, and only testing if userInput is non-zero, the loop will never exit, as userInput happens to start at 0.0, and will never be updated as scanf will not pull the non-numeric characters out of the stdin buffer. So that is why your code runs in an infinite loop.
If you had initialized userInput to a non-zero value, that would fix the problem one way, as non-numeric input would cause scanf to fail and the while condition would be triggered. But a better fix would be to check the return code of scanf. If it is zero, print an error message, and do a fpurge(stdin) to clear out the invalid input before you loop around again, like this:
int rc = scanf("%f", &userInput);
if (rc == 0)
{
NSLog(#"Invalid input, try again.");
fpurge(stdin);
}
So this is the plain C approach to input and parsing. The bottom line for defensive coding is that you should always check the return code!
As Chris mentions, for an actual Cocoa application, you would want to look at NSNumberFormatter and the like, but then you would presumably be taking input from widgets rather than file streams, so the code would be quite different to the above.
The proper way to validate user input in Cocoa is to use an instance of an appropriate subclass of NSFormatter, in this case something like NSNumberFormatter.