Answers:
我设法弄清楚了,而没有陷入C:
我的解决方案如下:
func input() -> String {
var keyboard = NSFileHandle.fileHandleWithStandardInput()
var inputData = keyboard.availableData
return NSString(data: inputData, encoding:NSUTF8StringEncoding)!
}
较新的Xcode版本需要显式的类型转换(在Xcode 6.4中有效):
func input() -> String {
var keyboard = NSFileHandle.fileHandleWithStandardInput()
var inputData = keyboard.availableData
return NSString(data: inputData, encoding:NSUTF8StringEncoding)! as String
}
var input = NSString(data: NSFileHandle.fileHandleWithStandardInput().availableData, encoding:NSUTF8StringEncoding)
string.stringByTrimmingCharactersInSet(NSCharacterSet.newlineCharacterSet())
实际上并不是那么容易,您必须与C API进行交互。别无选择scanf
。我建立了一个小例子:
主Swift
import Foundation
var output: CInt = 0
getInput(&output)
println(output)
UserInput.c
#include <stdio.h>
void getInput(int *output) {
scanf("%i", output);
}
cliinput-Bridging-Header.h
void getInput(int *output);
编辑夫特2.2的作为标准库包括readLine
。我还将注意到Swift切换到markdown文档注释。保留我对历史背景的原始答案。
为了完整起见,这是readln
我一直在使用的Swift实现。它具有一个可选参数,用于指示您要读取的最大字节数(它可以是字符串的长度,也可以不是字符串的长度)。
这也说明了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) }
}
另一个选择是链接libedit以进行适当的行编辑(箭头键等)和可选的历史记录支持。我希望这个项目可以用于我正在启动的项目,并提供一个有关如何设置它的基本示例。
快速使用
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
通常,readLine()函数用于扫描来自控制台的输入。但是,除非您添加“命令行工具”,否则它将无法在普通的iOS项目中使用。
最好的测试方法是:
import Foundation
print("Please enter some input\n")
if let response = readLine() {
print("output :",response)
} else {
print("Nothing")
}
Please enter some input
Hello, World
output : Hello, World
Program ended with exit code: 0
这是在基于控制台的应用程序上从用户那里获取输入的简单示例:可以使用readLine()。从控制台输入第一个数字,然后按Enter。之后,输入第二个数字,如下图所示:
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)
我向上帝发誓.. 几年以来,对这个根本问题的解决方案一直困扰着我。太简单了 ..但是那里有太多模糊/不好的信息。希望我能救一个人从一些无底的兔子洞,我在结束了...
因此,让我们通过“控制台”,“通过”从“用户”获得“字符串” stdin
,可以吗?
[NSString.alloc initWithData:
[NSFileHandle.fileHandleWithStandardInput availableData]
encoding:NSUTF8StringEncoding];
如果您想要它而没有尾随换行符,只需添加...
[ ... stringByTrimmingCharactersInSet:
NSCharacterSet.newlineCharacterSet];
Ta Da!
♥ⱥᏪℯⅩ
这个问题有很多过时的答案。从Swift 2+开始,Swift标准库包含readline()函数。它会返回一个Optional,但只有在达到EOF时才为零,当从键盘获取输入时不会发生,因此在这些情况下可以安全地用力打开它。如果用户未输入任何内容,则其(未包装)值将为空字符串。这是一个小的实用程序函数,它使用递归来提示用户,直到输入至少一个字符为止:
func prompt(message: String) -> String {
print(message)
let input: String = readLine()!
if input == "" {
return prompt(message: message)
} else {
return input
}
}
let input = prompt(message: "Enter something!")
print("You entered \(input)")
请注意,使用可选绑定(如果让input = readLine())来检查是否按照其他答案中的建议输入了某些内容,将不会达到预期的效果,因为它永远不会为零,并且在接受键盘输入时至少为“”。
在无法访问命令提示符的Playground或任何其他环境中,这将不起作用。在命令行REPL中似乎也有问题。
由于没有解决这个问题的理想方法,因此我制作了一个小类来读取和解析Swift中的标准输入。你可以在这里找到。
例
解析:
+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"
}
如果要读取以空格分隔的字符串,并立即将字符串拆分为数组,则可以执行以下操作:
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()函数时,调试控制台将等待输入。输入完成后,其余代码将恢复。
let inputStr = readLine()
if let inputStr = inputStr {
print(inputStr)
}
该问题的最高答案建议使用readLine()方法从命令行接收用户输入。但是,我要注意,您需要使用!运算符,当调用此方法以返回字符串而不是可选字符串时:
var response = readLine()!
readLine()
返回可选参数(由于某种原因),因此强制展开是不安全的,并且实际上并未在示例中添加任何内容。
迅捷5:如果您持续希望通过键盘进行输入,而又不像输入流那样结束程序,请执行以下步骤:
我只是想评论xenadu的实现(我没有足够的代表),因为CChar
在OS X中是Int8
,而Swift在添加到数组时根本不喜欢getchar()
返回部分UTF-8或其他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中获取键盘输入:
在我的main.swift文件中,我声明了一个变量i,并为其分配了我在Objective C中定义的函数GetInt()。通过所谓的桥接头,在其中声明了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标准输出和输入stdio.h,以及c标准库stdlib.h,该库使您可以在Objective-C中使用C进行编程,这意味着不需要包含C。一个真正的快捷文件,例如user.c或类似的文件。
希望我能帮上忙,
编辑:不可能通过C获得String输入,因为在这里我使用的是CInt-> C而不是Swift的整数类型。C char *没有等效的Swift类型。因此,字符串不能转换为字符串。但是,这里有足够的解决方案来获取String输入。
劳尔