Taking Command Line Input in Objective C - objective-c

Is there anyway we can take input from command line in Objective-C, the way we can take in C/C++?
int inputVariableName;
cin >> inputVariableName;

scanf("%i", userInput);
just as you would in c
To get Objective-C objects from the input, simple convert them after reading them in:
NSNumber * number = [nsnumber numberwithint:useriput];

Sure. Compile your code as Objective-C++.
This is typically as easy as renaming the file from having a .m suffix to a .mm suffix.
Documentation is included with the Xcode tools as to the details of Objective-C++.

As bbum mentioned, you can use NSFileHandle to get access to stdin. If you just want to read the command line arguments, you can get them from [[NSProcessInfo processInfo] arguments]. It's also worthwhile to know what else NSProcessInfo can tell you.

Command line input with spaces
char textInput[1000];
scanf("%[^\n]%*c", textInput);
NSString* userInput = [NSString stringWithUTF8String:textInput];
NSLog(#"\n%#\n%#", #"Hello, World.", userInput);
Input text with white spaces, 1000 is input character limit.

Related

How to display UTF8 string in OS X Terminal

I can't believe I couldn't find a solution to this very simple issue. I have a command line tool in Objective C, and need to display UTF8 strings (with non-English characters) in the console. I can't use NSLog as it also display process information, PID, timestamp etc. too. printf doesn't handle non-English characters well.
How can I print non-English characters in the Terminal, without any timestamps? Am I missing something really obvious here, or is such an extremely simple task really non-trivial in OS X?
I've tried:
printf: Doesn't display non-English characters.
NSLog: Displays PID/timestamp, which I don't want.
DLog (from https://stackoverflow.com/a/17311835/811405): Doesn't display non-English characters.
This works just fine:
printf("%s\n", [#"Can Poyrazoğlu" UTF8String]);
The macro you've tried to use depends on CFShow which doesn't print Unicode characters but only their escape codes. More information regarding this behaviour here.
So you could either use something else for your macro instead of CFShow to print to console without any timestamps or you could use an NSLog replacement library I wrote, Xcode Logger and use its XLog_NH logger which prints only the output without any other information.
Using stdio:
puts([#"Can Poyrazoğlu" UTF8String]);
Using write:
const char* example = [#"Can Poyrazoğlu" UTF8String];
write(STDOUT_FILENO, example, strlen(example));

Objective-C: What is the significance of the "#" (at) symbol for NSLog (#"abc");?

And also, why is it not necessary for, eg:
printf ("abc")
NSLog takes an NSString as argument. #"abc" denotes an NSString because of the # sign, so that is a valid argument for NSLog. printf is a normal C function that takes a C string, which is simply created using "".
UPDATE:
NSLog(#"%#",dictionary)
Tells the compiler that i got string to fulfill the requirement of string argument.
Update: Sorry I was supposed to write the "NSLog" instead of printf. my mistake!
Because it requires NSString. Adding #declares value as type of NSObject (simplification).

objective c UTF8String not working with japanese

I would like to show the NSString below on my UILabel:
NSString *strValue=#"你好";
but i can not show it on my UILabel i get strange characters!
I use this code to show the text:
[NSString stringWithCString:[strValue UTF8String] encoding:NSUTF8StringEncoding];
I tried [NSString stringWithCString:[strValue cStringUsingEncoding:NSISOLatin1StringEncoding] encoding:NSUTF8StringEncoding] and it worked
but i can not show emoticons with cStringUsingEncoding:NSISOLatin1StringEncoding so i have to use UTF8String.
Any help appreciated.
Your source file is in UTF-8, but the compiler you are using thinks it's ISO-Latin 1. What you think is the string #"你好" is actually the string #"你好". But when you ask NSString* to give you this back as ISO-Latin 1, and treat it as UTF-8, you've reversed the process the compiler took and you end up with the original string.
One solution that you can use here is to tell your compiler what encoding your source file is in. There is a compiler flag (for GCC it's -finput-charset=UTF-8, not sure about clang) that will tell the compiler what encoding to use. Curiously, UTF-8 should be the default already, but perhaps you're overriding this with a locale.
A more portable solution is to use only ASCII in your source file. You can accomplish this by replacing the non-ASCII chars with a string escape using \u1234 or \U12345678. In your case, you'd use
NSString *strValue=#"\u4F60\u597D";
Of course, once you get your string constant to be correct, you can ditch the whole encoding stuff and just use strValue directly.

How do I read a specific line from a large text file with Objective-C?

Say I have text file my.txt like this
this is line 1
this is line 2
....
this is line 999999
this is line 1000000
In Unix I can get the line of "this is line 1000" by issuing command like "head -1000 my.txt | tail -1". What is the corresponding way to get this in Objective-C?
If it's not too inefficient to have the whole thing in memory at once then the most compact sequence of calls (which I've expanded onto multiple lines for simpler exposition) would be:
NSError *error = nil;
NSString *sourceString = [NSString stringWithContentsOfFile:#"..."
encoding:NSUTF8StringEncoding error:&error];
NSArray *lines = [sourceString componentsSeparatedByCharactersInSet:
[NSCharacterSet newlineCharacterSet]];
NSString *relevantLine = [lines objectAtIndex:1000];
You should check the value of error and the count of lines for validation.
EDIT: to compare to Nathan's answer, the benefit of splitting by characters in set is that you'll accept any of the five unicode characters that can possibly delimit a line break, with anywhere where several of them sit next to each other counting as only one break (as per e.g. \r\n).
NSInputStream is probably what you're going to have to deal with if memory footprint is an issue, which is barely more evolved than C's stdio.h fopen/fread/etc so you're going to have to write your own little loop to dash through.
The answer does not explain how to read a file too LARGE to keep in memory. There is not nice solution in Objective-C for reading large text files without putting them into memory (which isn't always an option).
In these case I like to use the c methods:
FILE* file = fopen("path to my file", "r");
size_t length;
char *cLine = fgetln(file,&length);
while (length>0) {
char str[length+1];
strncpy(str, cLine, length);
str[length] = '\0';
NSString *line = [NSString stringWithFormat:#"%s",str];
% Do what you want here.
cLine = fgetln(file,&length);
}
Note that fgetln will not keep your newline character. Also, We +1 the length of the str because we want to make space for the NULL termination.
The simplest is to just load the file using one of the NSString file methods and then use the -[NSString componentsSeparatedByString:] method to get an array of every line.
Or you could use NSScanner, scan for newline/carriage return characters counting them until you get to you line of interest.
If you are really concerned about memory usage you could look at NSInputStream use that to read in the file, keeping count of the number of newlines. It a shame that NSScanner doesn't work with NSInputStream.
I don't think this is an exact duplicate, because it sounds like you want to skip some lines in the file, but you could easily use an approach like the one here:
Objective-C: Reading a file line by line (Specific answer that has some sample code)
Loop on the input file, reading in a chunk of data, and look for newlines. Count them up and when you hit the right number, output the data after that one and until the next.
Your example looks like you might have hundreds of thousands of lines, so definitely don't just read in the file into a NSString, and definitely don't convert it to an NSArray.
If you want to do it the fancier NSInputStream way (which has some key advantages in character set decoding), here is a great example that shows the basic idea of polling to consume all of the data from a stream source (in a file example, its somewhat overkill). Its for output, but the idea is fine for input too:
Polling versus Run Loop Scheduling

Question about #define statement in Objective-C project

I'm not experienced in C, so I'm not comfortable with this statement in this C / objective-C project.
#define CBLog(...) NSLog(#"%s [%ld]: %#", basename(__FILE__), __LINE__, [NSString stringWithFormat:__VA_ARGS__])
Questions:
the 3 dots (...) are used to indicate CBLog() is a method with parameters ? What do they mean ?
%ld stands for line format ? what's the d in %ld for ?
FILE , LINE and VA_ARGS are default replacement tokens for the C debugger ?
thanks
The ... means the macro accepts any number of arguments.
%ld is a string formatter meaning 'long decimal', where decimal really means integer.
__FILE__ expands to the current file name
__LINE__ expands to the current line number
__VA_ARGS__ expands to the arguments passed to the macro.
The debugger has nothing to do with it. All of this is the preprocessor, except %ld which is string formatting.
... means that any number of arguments can be given.
%ld means signed long, though it's a bit strange as I've never seen signed line numbers.
__FILE__ is the current source file's filename. __LINE__ is the current line number. __VA_ARGS__ are the arguments given to the macro.