在命令行应用程序中从键盘input

我正试图获得新的苹果编程语言Swift的命令行应用程序的键盘input。

我扫描了文档无济于事。

import Foundation println("What is your name?") ??? 

有任何想法吗?

执行此操作的正确方法是使用Swift标准库中的readLine

例:

 let response = readLine() 

会给你一个包含input文本的可选值。

我设法弄清楚了,没有下到C:

我的解决scheme如下:

 func input() -> String { var keyboard = NSFileHandle.fileHandleWithStandardInput() var inputData = keyboard.availableData return NSString(data: inputData, encoding:NSUTF8StringEncoding) } 

更新的Xcode版本需要一个明确的types转换(在Xcode 6.4中有效):

 func input() -> String { var keyboard = NSFileHandle.fileHandleWithStandardInput() var inputData = keyboard.availableData return NSString(data: inputData, encoding:NSUTF8StringEncoding) as! String } 

其实并不那么容易,你必须与C API交互。 scanf没有其他select。 我已经build立了一个小例子:

main.swift

 import Foundation var output: CInt = 0 getInput(&output) println(output) 

UserInput.c

 #include <stdio.h> void getInput(int *output) { scanf("%i", output); } 

cliinput桥接,Header.h

 void getInput(int *output); 

编辑从Swift 2.2开始,标准库包含readLine 。 我也会注意到Swift切换到降价文档评论。 留下我对历史背景的原始答案。

为了完整readlnreadln我一直使用的readln的Swift实现。 它有一个可选参数来表示你想要读取的最大字节数(可能不是string的长度)。

这也certificate了正确使用swiftdoc注释 – Swift将生成一个<project> .swiftdoc文件,Xcode将使用它。

 ///reads a line from standard input /// ///:param: max specifies the number of bytes to read /// ///:returns: the string, or nil if an error was encountered trying to read Stdin public func readln(max:Int = 8192) -> String? { assert(max > 0, "max must be between 1 and Int.max") var buf:Array<CChar> = [] var c = getchar() while c != EOF && c != 10 && buf.count < max { buf.append(CChar(c)) c = getchar() } //always null terminate buf.append(CChar(0)) return buf.withUnsafeBufferPointer { String.fromCString($0.baseAddress) } } 

另一种select是链接libedit进行正确的行编辑(箭头键等)和可选的历史logging支持。 我想要一个项目,我要开始,并为我如何设置一个基本的例子 。

从swift中使用

 let prompt: Prompt = Prompt(argv0: C_ARGV[0]) while (true) { if let line = prompt.gets() { print("You typed \(line)") } } 

ObjC包装来暴露libedit

 #import <histedit.h> char* prompt(EditLine *e) { return "> "; } @implementation Prompt EditLine* _el; History* _hist; HistEvent _ev; - (instancetype) initWithArgv0:(const char*)argv0 { if (self = [super init]) { // Setup the editor _el = el_init(argv0, stdin, stdout, stderr); el_set(_el, EL_PROMPT, &prompt); el_set(_el, EL_EDITOR, "emacs"); // With support for history _hist = history_init(); history(_hist, &_ev, H_SETSIZE, 800); el_set(_el, EL_HIST, history, _hist); } return self; } - (void) dealloc { if (_hist != NULL) { history_end(_hist); _hist = NULL; } if (_el != NULL) { el_end(_el); _el = NULL; } } - (NSString*) gets { // line includes the trailing newline int count; const char* line = el_gets(_el, &count); if (count > 0) { history(_hist, &_ev, H_ENTER, line); return [NSString stringWithCString:line encoding:NSUTF8StringEncoding]; } return nil; } @end 

下面是从基于控制台的应用程序的用户inputinput的简单示例:您可以使用readLine()。 从控制台input第一个数字然后按回车。 之后,input第二个数字,如下图所示:

 func solveMefirst(firstNo: Int , secondNo: Int) -> Int { return firstNo + secondNo } let num1 = readLine() let num2 = readLine() var IntNum1 = Int(num1!) var IntNum2 = Int(num2!) let sum = solveMefirst(IntNum1!, secondNo: IntNum2!) print(sum) 

产量

之前

在这里输入图像说明

*******************。

更正

在这里输入图像说明

由于这个问题没有特别的解决scheme,所以我编写了一个小小的类来读取和parsingSwift中的标准input。 你可以在这里find它。

parsing:

 +42 st_ring! -0.987654321 12345678900 .42 

你做:

 let stdin = StreamScanner.standardInput if let i: Int = stdin.read(), let s: String = stdin.read(), let d: Double = stdin.read(), let i64: Int64 = stdin.read(), let f: Float = stdin.read() { print("\(i) \(s) \(d) \(i64) \(f)") //prints "42 st_ring! -0.987654321 12345678900 0.42" } 

我向上帝发誓..这个完全基本的问题的解决scheme躲过了我年。 这很简单 ..但是那里有太多含糊不清的信息。 希望我能从一些无底洞的兔子中拯救出一些我最终在…

那么,让我们通过“控制台”,通过stdin ,从“用户”获得一个“string”, 我们呢?

 [NSString.alloc initWithData: [NSFileHandle.fileHandleWithStandardInput availableData] encoding:NSUTF8StringEncoding]; 

如果你想在没有结尾的换行符,只需添加…

 [ ... stringByTrimmingCharactersInSet: NSCharacterSet.newlineCharacterSet]; 

Ta Da! ♥ⱥᏪℯⅩ

这工作在xCode v6.2,我认为这是Swift v1.2

 func input() -> String { var keyboard = NSFileHandle.fileHandleWithStandardInput() var inputData = keyboard.availableData return NSString(data: inputData, encoding:NSUTF8StringEncoding)! as String } 

如果你想读取空格分隔的string,并立即将string拆分成数组,你可以这样做:

var arr = readLine()!.characters.split(" ").map(String.init)

例如。

 print("What is your full name?") var arr = readLine()!.characters.split(" ").map(String.init) var firstName = "" var middleName = "" var lastName = "" if arr.count > 0 { firstName = arr[0] } if arr.count > 2 { middleName = arr[1] lastName = arr[2] } else if arr.count > 1 { lastName = arr[1] } print("First Name: \(firstName)") print("Middle Name: \(middleName)") print("Last Name: \(lastName)") 

当在Xcode上运行readLine()函数时,debugging控制台等待input。 input完成后,其余的代码将被恢复。

  let inputStr = readLine() if let inputStr = inputStr { print(inputStr) } 

我只想对xenadu的实现发表评论(因为我没有足够的代码),因为OS X中的Int8Int8 ,而且当getchar()返回UTF-8的一部分或者任何东西时,Swift根本不喜欢你添加到数组否则高于7位。

我正在使用一个UInt8数组,而且它工作得很好, String.fromCStringUInt8转换为UTF-8就好了。

但是,这是我做到的

 func readln() -> (str: String?, hadError: Bool) { var cstr: [UInt8] = [] var c: Int32 = 0 while c != EOF { c = getchar() if (c == 10 || c == 13) || c > 255 { break } cstr.append(UInt8(c)) } cstr.append(0) return String.fromCStringRepairingIllFormedUTF8(UnsafePointer<CChar>(cstr)) } while true { if let mystring = readln().str { println(" > \(mystring)") } } 

我现在已经能够通过使用下面的Swift获取键盘input:

在我的main.swift文件中,我声明了一个variablesi,并将其赋值给我在Objective C中定义的函数GetInt()。通过一个所谓的Bridging Header,我声明了GetInt的函数原型,我可以链接到main.swift。 这里是文件:

main.swift:

 var i: CInt = GetInt() println("Your input is \(i) "); 

桥接标题:

 #include "obj.m" int GetInt(); 

obj.m:

 #import <Foundation/Foundation.h> #import <stdio.h> #import <stdlib.h> int GetInt() { int i; scanf("%i", &i); return i; } 

在obj.m中,可以包含c标准输出和inputstdio.h以及c标准库stdlib.h,使您能够在Objective-C中用C语言编程,这意味着不需要包含一个真正的swift文件,像user.c或类似的东西。

希望我能帮上忙,

编辑:这是不可能通过C获得stringinput,因为在这里我使用CInt – >整数types的C而不是Swift。 C char *没有等价的Swifttypes。 所以String不能转换为string。 但是在这里有足够的解决scheme来获得stringinput。

劳尔