Objective C Pointers - objective-c

I am experiencing a very odd problem with pointers. As you could see from the below code, I am using a method that generates a random 4 by 4 character grid. It return a pointer to a two dimensional character array. The problem is that when i try to assign the returned pointer to another pointer and try to print the generated grid, I get just one strange symbol.
Header File
#import <Foundation/Foundation.h>
#interface GridGenerator : NSObject
{
}
-(char (*)[4]) generateGrid;
-(int (*)[2]) bbb;
-(void) print;
#end
Implementation File
#import "GridGenerator.h"
#implementation GridGenerator
-(char (*)[4])generateGrid{
char vowels[6] = {'A','E','I','O','U','Y'};
char consonants[20] = {'B','C','D','F','G','H','J','K','L','M','N','P','Q','R','S','T','V','W','X','Z'};
char grid[4][4];
int vowelsLength = (sizeof vowels / sizeof vowels[0]);
int consLength = (sizeof consonants / sizeof consonants[0]);
int gridSize = (sizeof grid / sizeof grid[0]);
for(int i=0;i<gridSize;i++){
int vowelsInGridRow = 0;
int noOfVowels = (arc4random() % 2) + 1;
for(int j=0;j<gridSize;j++){
if(noOfVowels != vowelsInGridRow){
int vowIndex = arc4random() % vowelsLength;
char s = vowels[vowIndex];
grid[i][j] = s;
vowelsInGridRow++;
}
else{
int consIndex = arc4random() % consLength;
char s = consonants[consIndex];
grid[i][j] = s;
}
}
}
char (*sd)[4]= grid;
return sd;
}
-(void)print{
char (*grid)[4] = [self generateGrid];
NSString *s = #"\n";
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
s = [s stringByAppendingString:[NSString stringWithFormat:#"%c",grid[i][j]]];
}
s = [s stringByAppendingString:#"\n"];
}
NSLog(#"%#",s);
}
Main File(Test)
#import <Foundation/Foundation.h>
#import "Crossword.h"
#import "GridGenerator.h"
int main(int argc, const char * argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
GridGenerator *gen = [[GridGenerator alloc] init];
[gen print];
[pool release];
return 0;
}
When I run the code, you can see the result below. After the 'U' there is an inverted question mark(could not be pasted here).
2013-06-02 11:24:29.923 CrosswordTest[646:303]
U
Do you have an idea, what could causes this to happen? I am struggling already for several hours and I cannot find any explanation.

You are returning a reference to a temporary. Explosion (undefined behavior) should be expected.
Workaround. Create a structure:
typedef struct {char at[4][4];} t_grid;
Then populate and return the t_grid by value:
- (t_grid)generateGrid
{
char vowels[6] = {'A','E','I','O','U','Y'};
char consonants[20] = {'B','C','D','F','G','H','J','K','L','M','N','P','Q','R','S','T','V','W','X','Z'};
t_grid grid;
...
int gridSize = (sizeof grid.at / sizeof grid.at[0]);
...
grid.at[i][j] = s;
...
return grid;
}
- (void)print
{
t_grid grid = [self generateGrid];
...
Note that you should not use this approach for large arrays or variable length arrays. 4*4 octets is small.

Related

Invalid memory reference (SIGSEGV) and incomplete implementation of class error

I am writing a small recursive function to calculate the sum of integers from an array. However, I am getting errors and warnings. Anybody help me to solve these issues?
#import <Foundation/Foundation.h>
#interface SumIntegers:NSObject
{
NSInteger result;
}
-(NSInteger)calcutateSum:(NSInteger)value;
-(void) printSum;
#end
#implementation SumIntegers
-(NSInteger)calculateSum:(NSInteger)value
{
NSInteger sum = 0;
//sum = sum + [[self calculateSum:[array objectAtIndex:i]] integerValue];
sum = sum + [self calculateSum:value];
result = sum;
return result;
}
-(void) printSum
{
NSLog(#"Sum of integer list is %i",result);
}
#end
int main (int argc, const char * argv[])
{
NSInteger i;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSMutableArray *intArray = [NSMutableArray arrayWithObjects:[NSNumber numberWithInteger:1],[NSNumber numberWithInt:3],[NSNumber numberWithInt:5]
,[NSNumber numberWithInt:7],[NSNumber numberWithInt:9],nil];
SumIntegers *sumIntegers = [[SumIntegers alloc]init];
for (i = 0; i<[intArray count]; i++)
{
NSInteger hhh = [sumIntegers calculateSum:[[intArray objectAtIndex:i] integerValue]];
}
[sumIntegers printSum];
[pool drain];
return 0;
}
What I did is I created an interface SumIntegers and created a recursive function to calculate the sum of integers. However, somehow this function is not recognized and also getting warning "incomplete implementation of class #end" and memory error.
Warning(s):
source_file.m:31:1: warning: incomplete implementation of class ‘SumIntegers’
#end
^
source_file.m:31:1: warning: method definition for ‘-calcutateSum:’ not found
source_file.m: In function ‘main’:
source_file.m:44:19: warning: unused variable ‘hhh’ [-Wunused-variable]
NSInteger hhh = [sumIntegers calculateSum:[[intArray objectAtIndex:i] integerValue]];
^
Error(s):
Invalid memory reference (SIGSEGV)
Here is my answer to above problem. There is no need of return value or argument in the calculateSum method. Simply adding array value into the sum and then calling the calculateSum method again until num is less than array count.
#import <Foundation/Foundation.h>
#interface SumOfIntegers:NSObject
{
NSMutableArray *intArray;
NSInteger sum;
NSInteger num;
}
#property NSMutableArray *intArray;
#property NSInteger sum, num;
-(void) calculateSum;
#end
#implementation SumOfIntegers
#synthesize intArray, sum, num;
-(void) calculateSum{
if(num < [intArray count])
{
NSLog(#"number is.... %i", num);
sum = sum + [[intArray objectAtIndex:num++] integerValue];
[self calculateSum];
}
else
{
NSLog(#"Sum of integers is %i", sum);
}
}
#end
int main (int argc, const char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSMutableArray *array = [NSMutableArray arrayWithObjects:[NSNumber numberWithInteger:1],[NSNumber numberWithInt:3],[NSNumber numberWithInt:5]
,[NSNumber numberWithInt:7],[NSNumber numberWithInt:9],nil];
SumOfIntegers *sumOfIntegers = [[SumOfIntegers alloc]init];
sumOfIntegers.intArray = array;
sumOfIntegers.sum = 0;
sumOfIntegers.num = 0;
[sumOfIntegers calculateSum];
[pool drain];
return 0;
}
In modern ObjC:
int main(int argc, const char * argv[]) {
#autoreleasepool {
NSArray *nums = #[#(1), #(2), #(3)];
NSLog(#"%#", [nums valueForKeyPath:#"#sum.self"]);
}
return 0;
}

Objective C - Method Definition not in #implementation context

My Code:
#import <Foundation/Foundation.h>
-(NSString *) Fibonacci:(int) number{
//Fibonacci Calculations
}
int main (int argc, const char * argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog(#"Fibonacci Output: %#", Fibonacci(5));
[pool drain];
return 0;
}
I am very new to Objective-C world and hence am not able to get the above working.
Facing the following errors:
Error(s):
source_file.m:5:1: error: method definition not in #implementation context
-(NSString *) lastdigitsFibonacci:(int) number{
^
source_file.m:6: confused by earlier errors, bailing out
Any help on the above would be deeply appreciated. Thanks
As #Larme said, Fibonacci(5) seems to be like a function. -(NSString *) Fibonacci:(int) number seems to be like a method.
So to call Fibonacci(5), you should rewrite -(NSString *) Fibonacci:(int) number as a func.
NSString* Fibonacci(int number) {
int t1 = 0;
int t2 = number > 1 ? 1 : 0;
int tmp;
for (int i = 3; i <= number; i++) {
tmp = t2;
t2 += t1;
t1 = tmp;
}
return [NSString stringWithFormat:#"%lu", t2];
}
int main(int argc, char* argv[]) {
#autoreleasepool {
NSLog(#"%#", Fibonacci(999));
}
}
#import <Foundation/Foundation.h>
NSString* Fibonacci(int number) ;
int main(int argc, const char * argv[]) {
#autoreleasepool {
// insert code here...
NSLog(#"Fibonacci Output: %#", Fibonacci(5));
}
return 0;
}
NSString* Fibonacci(int number)
{
//Fibonacci Calculations and return
}

How to solve HackerRank problems in Objective-C

Can anybody explain how to give the hacker rank test in objective-C. Specially the part "Read input from STDIN. Print output to STDOUT"
How to read input and out in objective-c ?
What i have got so far is get input like
NSFileHandle *fileHandler = [NSFileHandle fileHandleWithStandardInput];
NSData *inputData = [fileHandler availableData];
NSString *inputString = [[NSString alloc] initWithData:inputData encoding:NSUTF8StringEncoding];
But to print output, following does not print anything on HackerRank console (but works flawlessly on Xcode console)
NSFileHandle* fileHandler=[NSFileHandle fileHandleWithStandardOutput];
[fileHandler writeData: [formattedString dataUsingEncoding: NSNEXTSTEPStringEncoding]];
The simplest possible way to "Read input from STDIN. Print output to STDOUT" would be to use scanf and printf.
Here's a sample template to get you started:
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int count;
scanf("%d", &count);
NSMutableArray *inputIntegers = [NSMutableArray new];
for (int i=0; i<count; i++) {
int inputElement;
scanf("%d", &inputElement);
[inputIntegers addObject:[NSNumber numberWithInt:inputElement]];
}
//to print a specific element:
printf("printing element 0: %d", (int)[inputIntegers[0] integerValue]);
[pool drain];
return 0;
}
Before you take a shot at this journey, a few things:
Make sure ARC is disabled (search for CLANG_ENABLE_OBJC_ARC in build settings, and set it to NO)
Avoid using self. This is functional programming.
Use C functions, not Objective-C methods, meaning, use
instead of
- (NSInteger)sumOfNumbers : (NSInteger)a and:(NSInteger)b {
return a + b;
}
use
int sumOfNumbers(int a, int b){
return a + b;
}
Happy Programming.
Having just been handed one of these tests, I opted to get out of main.m immediately and into Objective-C like so:
#import <Foundation/Foundation.h>
//Objective-C helper class to take over from main.m
//.h
#interface MainClass : NSObject
+ (BOOL)startMain;
#end
//.m
#implementation MainClass
+ (BOOL)startMain {
//Read the STDIN here using the Objective-C wrapper methods
NSInteger n = [self readInt];
[self printInt:n];
NSArray *numbers = [self readIntArrayOfLength:n];
[self printIntNumberArray:numbers];
return YES;
}
+ (NSInteger)readInt {
int n;
scanf("%i",&n);
return n;
}
+ (NSArray *)readIntArrayOfLength:(NSInteger)len {
NSMutableArray *result = [NSMutableArray array];
for (int i =0; i < len; i++) {
[result addObject:[NSNumber numberWithInt:[self readInt]]];
}
return [result copy];
}
//Helpers to print an int and array of ints to STDOUT
+ (void)printInt:(NSInteger)i {
printf("%li\n",(long)i);
}
+ (void)printIntNumberArray:(NSArray *)array {
printf("[");
[array enumerateObjectsUsingBlock:^(NSNumber *n, NSUInteger idx, BOOL * _Nonnull stop) {
printf("%li",(long)[n integerValue]);
if (idx < array.count-1) {
printf(",");
}
}];
printf("]\n");
}
#end
//This is what will actually run when you hit "Run Code"
int main(int argc, char * argv[]) {
#autoreleasepool {
return [MainClass startMain];
}
}
Now you can do whatever you like from here using Objective-C.
So in this example a sample input of:
3
11 2 4
Would produce this output:
3
[11,2,4]
Not useful in of itself but illustrates the successful read.
It's a lot simpler in Swift, but here's code to accomplish the same thing anyway:
func readInt() -> Int? {
if let ln = readLine() {
return Int(ln)
}
return nil
}
func readIntArray() -> [Int]? {
if let ln = readLine() {
return ln.characters.split(" ").filter({ Int(String($0)) != nil }).map({ Int(String($0))! })
}
return nil
}
let n = readInt()!
let array = readIntArray()!
print(n)
print(array)
The functions return optionals because even though you are going to force-unwrap the input, better the crash for a nil optional happens in your code than the boilerplate.
#import <Foundation/Foundation.h>
int sum(int a, int b) {
return a + b;
}
int main() {
#autoreleasepool {
int T;
int A;
int B;
printf("Enter number of test cases: ");
scanf("%d", &T);
for (int i=0; i < T; i++) {
scanf("%d", &A);
scanf("%d", &B);
printf("%d\n", sum(A,B));
}
}
return 0;
}
That ought to do it.
Your question is really too general for SO, do not be surprised if it gets closed soon. You need in general to ask specific questions, show what you've tried, etc. But if you're just after a few hints to get you going...
You don't say whether you are a programmer already or know Objective-C in particular, assuming both:
In Xcode look at the Command Line Tool project type
Look into NSFileHandle and its methods, e.g. fileHandleWithStandardInput
Note you can also use the C stdio functions, converting C-style to Objective-C styles strings etc. as needed.
I created github repo with some hackerrank problem solutions written in objective-c. It is on the beginning stage, feel free to contribute by adding your solutions as well.
HackerRank for Objective-C
Since Objective-C is a superset of C, you can use C methods for reading and printing out:
NSInteger n;
char *input[25];
NSMutableArray *strings = [NSMutableArray array];
NSString *s;
NSString *temp;
scanf("%lu", &n);
for (NSInteger i = 0; i < n; ++i) {
scanf("%s", input);
s = [NSString stringWithUTF8String:input];
[inputs addObject:s];
}
If n is of type int, you can read it as:
scanf("%d", &n);

Converting an NSString to bit value

NSString *strVal= #"BAAA";
How do I convert the above string into a bit value? Should I do the byte conversion before this?
Need help on this. I have previously checked this question for integer conversion.
Whether you convert the string to UTF-8 first is up to you; it depends what you want. Internally NSString stores characters as UTF-16 (might be UCS-2 actually) using the unichar type, so you need to decide whether you want the binary of the internal representation or of some other external encoding.
I expect you want the binary of the UTF-8 encoding, so try this (tested):
#import <Foundation/Foundation.h>
#interface BinFuncs : NSObject
+ (NSString *)binaryOfString:(NSString *)str;
#end
#implementation BinFuncs
+ (NSString *)binaryOfString:(NSString *)str {
NSMutableString *binStr = [[NSMutableString alloc] init];
const char *cstr = [str UTF8String];
size_t len = strlen(cstr);
for (size_t i = 0; i < len; i++) {
uint8_t c = cstr[i];
for (int j = 0; j < 8; j++) {
[binStr appendString:((c & 0x80) ? #"1" : #"0")];
c <<= 1;
}
}
return binStr;
}
#end
int main(int argc, const char **argv) {
#autoreleasepool {
for (int i = 1; i < argc; i++) {
NSString *binStr = [BinFuncs binaryOfString:[NSString stringWithUTF8String:argv[i]]];
NSLog(#"%#", binStr);
}
}
return 0;
}
$ clang -o binstr binstr.m -framework Foundation
$ ./binstr 'the quick brown fox jumps over the lazy dog'
2013-09-30 09:19:49.674 binstr[58474:707] 01110100011010000110010100100000011100010111010101101001011000110110101100100000011000100111001001101111011101110110111000100000011001100110111101111000001000000110101001110101011011010111000001110011001000000110111101110110011001010111001000100000011101000110100001100101001000000110110001100001011110100111100100100000011001000110111101100111

Is there a way to log all the property values of an Objective-C instance

I was just wondering if there is a quick and easy way of printing out to the log all of the various values of the properties to my class for debugging purposes. Like I would like to know what the values of all of the BOOLs, floats, etc. are.
This question seems the have the answer to your question.
Update:
I got curious and made a catagory:
//Using Xcode 4.5.2 - iOS 6 - LLDB - Automatic Reference Counting
//NSObject+logProperties.h
#interface NSObject (logProperties)
- (void) logProperties;
#end
//NSObject+logProperties.m
#import "NSObject+logProperties.h"
#import <objc/runtime.h>
#implementation NSObject (logProperties)
- (void) logProperties {
NSLog(#"----------------------------------------------- Properties for object %#", self);
#autoreleasepool {
unsigned int numberOfProperties = 0;
objc_property_t *propertyArray = class_copyPropertyList([self class], &numberOfProperties);
for (NSUInteger i = 0; i < numberOfProperties; i++) {
objc_property_t property = propertyArray[i];
NSString *name = [[NSString alloc] initWithUTF8String:property_getName(property)];
NSLog(#"Property %# Value: %#", name, [self valueForKey:name]);
}
free(propertyArray);
}
NSLog(#"-----------------------------------------------");
}
#end
Include it in your class: #import "NSObject+logProperties.h"
and call [self logProperties]; to those properties!
The current answers just show how to do it for properties. If you want every instance variable printed out you could do something like the below.
- (void)logAllProperties {
unsigned int count;
Ivar *ivars = class_copyIvarList([self class], &count);
for (unsigned int i = 0; i < count; i++) {
Ivar ivar = ivars[i];
const char *name = ivar_getName(ivar);
const char *type = ivar_getTypeEncoding(ivar);
ptrdiff_t offset = ivar_getOffset(ivar);
if (strncmp(type, "i", 1) == 0) {
int intValue = *(int*)((uintptr_t)self + offset);
NSLog(#"%s = %i", name, intValue);
} else if (strncmp(type, "f", 1) == 0) {
float floatValue = *(float*)((uintptr_t)self + offset);
NSLog(#"%s = %f", name, floatValue);
} else if (strncmp(type, "#", 1) == 0) {
id value = object_getIvar(self, ivar);
NSLog(#"%s = %#", name, value);
}
// And the rest for other type encodings
}
free(ivars);
}
Although I wouldn't particularly suggest doing this in practice, but if it's for debug purposes then that's fine. You could implement this as a category on NSObject and keep it lying around for use when debugging. If completed for all type encodings then it could make for a very nice little method.
There are now these methods on NSObject :
#interface NSObject (Private)
-(id)_ivarDescription;
-(id)_shortMethodDescription;
-(id)_methodDescription;
#end
In swift:
myObject.perform("_ivarDescription")
Thanks to this article
yes, one way would be to ask for all properties and then use KVC for example:
//properties
unsigned int cProperties = 0;
objc_property_t *props = class_copyPropertyList(self.class, &cProperties);
for(int i = 0; i < cProperties; i++) {
const char *name = property_getName(props[i]);
NSLog(#"%#=%#", name, [self valueForKey:name];
}
an alternate way is to go through all the methods of a class, get the return type, invoke and print it
The quick and dirty would be to override debugDescription:
-(NSString*)debugDescription {
NSString *str = [[NSString alloc] initWithFormat:#"My BOOL 1: %d, My Float: %f", self.myBool, self.myFoat];
return str;
}
Of course, if your object is complex, this could be time consuming.