I am writing reverseString function by myself. (For test use) And I use iOS platform to run my c code, which sounds weird, but again, for test use...
Here is my code:
-(char *) reverseString:(char *)str
{
char *end = str;
char tmp;
if (str)
{
while (*end) { end++; }
--end;
NSLog(#"%c", *end);
while (end>str)
{
tmp = *str;
*str = *end;
str++;
*end = tmp;
end--;
}
}
NSLog(#"%s", str);
return str;
}
After running the function by calling:
char *testChar = "abcd";
[self reverseString:testChar];
I received the error on line:
*str = *end;
Thread 1: EXC_BAD_ACCESS(code=2, address=0x2de4)
I don't really know understand what's wrong with the pointer here...Anyone has any idea?
You can't modify a string literal. Use a char array instead.
char testChar[] = "abcd";
Related
This question already has an answer here:
which is the correct specifier to use for long when calling stringWithFormat?
(1 answer)
Closed 2 years ago.
I try to convert long (value: 454555) to NSString. But everytime I had tried it, I got garbage value like #"-5026338884877204098".
How can I convert it same with 454555?
You can initialize a NSString by
NSString *a = #(454555).stringValue;
Here you can put all mathematical type value in the brackets,like
NSString *a = #(0.1).stringValue;//a float value
NSString *a = #(9223372036854775807).stringValue;//it's a longlong value
Try
long l = 454555;
NSString * s = [NSString stringWithFormat:#"%ld", l];
Note this is not locale aware ... but handy and sounds like the man you are looking for for your job. Here the %ld means a l=long d=decimal/int (ie long) value is next up in the parameters.
EDIT
If you like the #-way just execute the code below.
int main(int argc, const char * argv[]) {
#autoreleasepool
{
NSLog(#"Hello, World!");
for ( long i = 0; i < 1000000; i ++ )
{
// Direct ...
NSString * s = [NSString stringWithFormat:#"%ld", i ];
}
NSLog(#"1");
for ( long i = 0; i < 1000000; i ++ )
{
// Indirect via NSNumber ...
NSString * s = #(i).stringValue;
}
NSLog(#"2");
}
return 0;
}
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);
I need to convert an C-String into an NSString.
How do I do this?
I know how to convert it the OTHER WAY,
NSString *hello = #"Hello!";
const char *buffer;
buffer = [schoolName cStringUsingEncoding: NSUTF8StringEncoding];
NSLog(#"C-String is: %s", buffer);
However, how do I do it Objective-C string (NSString) into a NULL-TERMINATED string.
Thanks!
const char *buffer = [hello UTF8String]; will do what you're looking for.
Now to answer the new (and very different) question:
If you have, for example, const char *cstring = "hello world"; you can create an NSString * with it through: NSString *nsstring = [NSString stringWithFormat:#"%s", cstring];
There are, of course, other ways to accomplish the same thing.
NSString* str = [NSString stringWithUTF8String:(const char *)]
or
NSString* str = [NSString stringWithCString:(const char *) encoding:(NSStringEncoding)]
or
NSString* str = [NSString stringWithCharacters:(const unichar *) length:(NSUInteger)]
Try something like this:
- (wchar_t*)getWideString
{
const char* temp = [schoolName cStringUsingEncoding:NSUTF8StringEncoding];
int buflen = strlen(temp)+1; //including NULL terminating char
wchar_t* buffer = malloc(buflen * sizeof(wchar_t));
mbstowcs(buffer, temp, buflen);
return buffer;
};
For example, I need the NSString have at least 8 chars....instead of using a loop to add the left pad spaces on this, is there anyway to do it?
Examples:
Input: |Output:
Hello | Hello
Bye | Bye
Very Long |Very Long
abc | abc
Here is an example of how you can do it:
int main (int argc, const char * argv[]) {
NSString *str = #"Hello";
int add = 8-[str length];
if (add > 0) {
NSString *pad = [[NSString string] stringByPaddingToLength:add withString:#" " startingAtIndex:0];
str = [pad stringByAppendingString:str];
}
NSLog(#"'%#'", str);
return 0;
}
I just do something like this:
NSLog(#"%*c%#", 14 - theString.length, ' ', theString);
Moreover, 14is the width that you want.
You can use C language printf formatting with -[NSMutableString appendFormat:] and all other NSString "format" methods. It doesn't respect NSString (do formatting on %#), so you need to convert them to ASCII.
String Padding in C
- (NSString *)sample {
NSArray<NSString *> *input = #[#"Hello", #"Bye", #"Very Long", #"abc"];
NSMutableString *output = [[NSMutableString alloc] init];
for (NSString *string in input) {
[output appendFormat:#"%8s\n", string.UTF8String];
}
return output;
}
/*
Return value:
Hello
Bye
Very Long
abc
*/
if you need the same answer in a method, I had to create one for use in my projects. original code by dashblinkenlight
- (NSString *) LeftPadString: (NSString*) originalString LengthAfterPadding: (int)len paddingCharacter: (char) pad
{
int add = (int) (len - originalString.length);
NSString* paddingCharString = [NSString stringWithFormat:#"%c" , pad];
if (add > 0)
{
NSString *pad = [[NSString string] stringByPaddingToLength:add withString: paddingCharString startingAtIndex:0];
return [pad stringByAppendingString:originalString];
}
else
return originalString;
}
Ideally, I would like to make a function add objects in a NSMutableArray, and then do whatever I want with this array in another function.
Here is what I've tried to do lately, of course it doesn't work but it gives you an idea of what I want to do:
- (void)someThing
{
(...)
NSMutableArray *arrayOfThings = [[NSMutableArray alloc] init];
while (theObject = [aNSEnumerator nextObject]) {
const char *theObject_fixed = [theObject UTF8String];
function_something(theObject_fixed);
}
// do something with arrayOfThings
}
void function_something(const char *file)
{
(...)
unsigned int *p = memmem(buffer, fileLen, bytes, 4);
NSMutableString *aString = [[NSMutableString alloc] initWithCapacity:48];
unsigned long off_to_string = 0x10 + 4 + ((void *)p) - ((void *)buffer);
for (unsigned long c = off_to_string; c<off_to_string+0x30; c++)
{
[aString appendFormat:#"%.2x", (int)buffer[c]];
}
NSLog(#"%s: %#", file, aString);
[arrayOfThings addObject:[aString copy]];
free(buffer);
There are two ways to go about this:
The first requires only a slight modification to your code will allow you to do what you want:
In the funciton someThing pass the mutable array as an additional parameter.
function_something(theObject_fixed, arrayOfThings);
Then change function_something to accept that parameter.
void function_something(const char *file, NSMutableArray *arrayOfThings) {
// Code remains the same
}
The other and in my opinion better solution would be for the function_something to return the fixed string as an NSString object and let someThing do the adding to the mutable array.
So we get something like this in someThing:
...
NSString *aString = function_something(theObject_fixed);
[arrayOfThings addObject:aString];
And then a redefined *function_something*:
NSString* function_something(const char *file) {
...
return [aString autorelease];
}
By the way, your code is leaking memory. Be careful with you retain/release/autorelease.