在命令行应用程序中从键盘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切换到降价文档评论。 留下我对历史背景的原始答案。
为了完整readln
, readln
我一直使用的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中的Int8
是Int8
,而且当getchar()
返回UTF-8的一部分或者任何东西时,Swift根本不喜欢你添加到数组否则高于7位。
我正在使用一个UInt8
数组,而且它工作得很好, String.fromCString
将UInt8
转换为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。
劳尔