Why isn't this print method working? - objective-c

It works when I use NSLog, but not printf. I want to use printf because then all the elements in setA will be displayed in one line.
#import <Foundation/Foundation.h>
#define INTOBJ(v) [NSNumber numberWithInteger: v]
#interface NSSet (Printing)
-(void) print;
#end
#implementation NSSet (Printing)
-(void) print {
for (NSNumber *element in self)
printf("%li", (long) [element integerValue]);
}
#end
int main (int argc, char *argv[]) {
#autoreleasepool {
NSMutableSet *setA = [NSMutableSet setWithObjects:INTOBJ(3), INTOBJ(10), INTOBJ(1), INTOBJ(5), nil];
[setA print];
}
return 0;
}

NSLog is essentially a different version of printf that allows for Objective C stuff, while printf can't handle Objective C material.
If your printf method isn't working, this is probably the problem.

try -longValue instead of -integerValue it should cast them implicitly, but you never know...

Convert from the NSNumber which is an object into an NSInteger first, then you can output to the console with your printf statement, and all of the integers should appear on one line.
for(NSNumber *element in setA)
{
NSInteger num = [element intValue];
printf("%li", (long)num);
}

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;
}

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);

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.

string with format as argument for method (objective-c)

The [NSString stringWithFormat:]; can take multiple arguments even though it's declared as NSString not NSArray and there's only one colon.
How can I have this for my own method, which is like a replacement for NSLog that writes to a text field so it's used often and I don't want to keep adding more square brackets.
Use an ellipsis after your argument name:
(NSNumber *) addValues:(int) count, ...;
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocDefiningClasses.html
You then need to use va_list and va_start to iterate through the arguments provided:
- (NSNumber *) addValues:(int) count, ...
{
va_list args;
va_start(args, count);
NSNumber *value;
double retval;
for( int i = 0; i < count; i++ )
{
value = va_arg(args, NSNumber *);
retval += [value doubleValue];
}
va_end(args);
return [NSNumber numberWithDouble:retval];
}
Example from: http://numbergrinder.com/node/35
Note that this is a built-in C functionality, not part of Objective-C specifically; there is a good explanation of the va_arg usage here:
http://publications.gbdirect.co.uk/c_book/chapter9/stdarg.html

Is it possible to NSLog() without the time and date stamps, and the automatic newline? [duplicate]

This question already has answers here:
In Xcode, is there a way to disable the timestamps that appear in the debugger console when calling NSLog?
(8 answers)
Closed 9 years ago.
Does NSLog() have variants that print without the time and date stamps, and the automatic newline?
Thanks. Now with following code, I can print NSString, cString, or objects:
#import <Foundation/Foundation.h>
#import <stdio.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString *s = #"Hello, World!";
NSDate *today = [NSDate date];
NSLog(#"%#", s);
printf("%s at %s", [s UTF8String], [[today description] UTF8String]);
[pool drain];
return 0;
}
Use printf() instead of NSLog()
This code will work
#ifdef DEBUG
#define NSLog(FORMAT, ...) fprintf(stderr,"%s\n", [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
#else
#define NSLog(...) {}
#endif
It bothered me too, so I wrote a function to replace NSLog() and printf():
void IFPrint (NSString *format, ...) {
va_list args;
va_start(args, format);
fputs([[[[NSString alloc] initWithFormat:format arguments:args] autorelease] UTF8String], stdout);
va_end(args);
}
Then, you can just use it instead of NSLog() (e.g. IFPrint(#"Current date: %#", [NSDate date])), but it won't print out any timestamps or a newline, and you don't have to mess around with C strings and arrays, and whatnot. It's pretty handy, I'd say.
If you want, check out my full code (I've also written a replacement for fprintf, scanf, and fscanf) here.
(There's also an SO topic about it here).
Define a macro
#if __has_feature(objc_arc)
#define DLog(format, ...) CFShow((__bridge CFStringRef)[NSString stringWithFormat:format, ## __VA_ARGS__]);
#else
#define DLog(format, ...) CFShow([NSString stringWithFormat:format, ## __VA_ARGS__]);
#endif
And use this macro in you code like
NSLog(#"Content with time stamp");
DLog(#"Content without time stamp");
Here is the output of console
NSLog->2014-01-28 10:43:17.873 TestApp[452:60b] Content with time stamp
DLog -> Content without time stamp
P.S.
If anyone wants Custom Logs which gives you more info like method name / line number etc. can download the open source MLog.h on GitHub.
I like the Itai's solution. I just modified the code to use CFShow under ARC environment.
void CFLog(NSString *format, ...)
{
va_list args;
va_start(args, format);
CFShow((__bridge CFStringRef)[[NSString alloc] initWithFormat:format arguments:args]);
va_end(args);
}
the FIRST thing I do on ANY project is drop in (my condensed version of) this class... which gets rid of ALL the NONSENSE in NSLog… Place this at the top of an .m file - and your console output will be PERFECT.
#import <Foundation/Foundation.h>
#import <stdio.h>
#define MLogString(s,...) \
[MLog logFile:__FILE__ lineNumber:__LINE__ \
format:(s),##__VA_ARGS__]
#interface MLog : NSObject { }
+ (void) logFile: (char*) sourceFile lineNumber: (int) lineNumber format: (NSString*) format, ...;
+ (void) setLogOn: (BOOL) logOn;
#end
#ifndef NDEBUG
extern void _NSSetLogCStringFunction(void (*)(const char *string, unsigned length, BOOL withSyslogBanner));
static void PrintNSLogMessage(const char *string, unsigned length, BOOL withSyslogBanner){ puts(string); }
static void HackNSLog(void) __attribute__((constructor));
static void HackNSLog(void){ _NSSetLogCStringFunction(PrintNSLogMessage); }
#endif
static BOOL __MLogOn = NO;
#implementation MLog
+ (void) initialize { char * env = getenv("MLogOn");
if (strcmp(env == NULL ? "" : env, "NO") != 0) __MLogOn = YES;
}
+ (void) logFile: (char *) sourceFile lineNumber: (int) lineNumber format: (NSString *) format, ...; {
va_list ap; NSString *print, *file;
if (__MLogOn == NO) return; va_start(ap, format);
file = [[NSString alloc] initWithBytes: sourceFile length:strlen(sourceFile) encoding: NSUTF8StringEncoding];
print = [[NSString alloc] initWithFormat:format arguments: ap];
va_end(ap); // NSLog handles synchronization issues
NSLog(#"%s: %d %#", [[file lastPathComponent] UTF8String], lineNumber, print); return;
}
+ (void) setLogOn: (BOOL) logOn { __MLogOn = logOn; }
#end