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

时间:2014-06-02 23:15:53

标签: swift macos cocoa command-line

我正在尝试获取新Apple编程语言Swift的命令行应用程序的键盘输入。

我扫描过这些文档无济于事。

import Foundation

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

有什么想法吗?

20 个答案:

答案 0 :(得分:124)

正确的方法是使用Swift标准库中的readLine

示例:

let response = readLine()

将为您提供包含输入文本的可选值。

答案 1 :(得分:59)

我设法解决了这个问题而没有进入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
}

答案 2 :(得分:13)

实际上并不那么容易,您必须与C API进行交互。除scanf之外别无选择。我构建了一个小例子:

<强> 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);

答案 3 :(得分:6)

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

为了完整起见,这是我一直在使用的readln的Swift实现。它有一个可选参数,用于指示要读取的最大字节数(可能是也可能不是字符串的长度)。

这也证明了正确使用swiftdoc注释 - Swift将生成一个&lt; project&gt; .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) }
}

答案 4 :(得分:5)

另一种方法是链接libedit以进行正确的行编辑(箭头键等)和可选的历史记录支持。我希望这是一个项目,我开始并组建一个basic example for how I set it up

来自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

答案 5 :(得分:5)

一般来说, readLine()功能用于从控制台扫描输入。但是除非你添加&#34;命令行工具&#34; ,否则它在普通的iOS项目中不起作用。

最好的测试方法,你可以这样做:

1。创建一个macOS文件

enter image description here

2。使用readLine()func从控制台

扫描可选的String
 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

enter image description here

答案 6 :(得分:2)

以下是在基于控制台的应用程序上从用户获取输入的简单示例: 您可以使用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)

Output

答案 7 :(得分:1)

快捷键5:如果您持续希望从键盘进行输入而不结束程序(如输入流),请执行以下步骤:

  1. 创建comnnad线工具类型的新项目 Command line project

    1. 在main.swift文件中添加以下代码:

      var inputArray = [String]()
      
      while let input = readLine() {
      
      guard input != "quit" else {
      
      break
      
      }
      
      inputArray.append(input)
      
      print("You entered: \(input)")
      
      print(inputArray)
      
      print("Enter a word:")
      }   
      
    2. 运行项目,然后单击Xco​​de中Products文件夹下的可执行文件,然后在finder中打开
    3. 双击可执行文件将其打开。
    4. 现在输入您的输入。终端看起来像这样: enter image description here

答案 8 :(得分:1)

此问题排名靠前的答案建议使用readLine()方法从命令行接收用户输入。但是,我想要注意你需要使用!调用此方法以返回字符串而不是可选的运算符:

var response = readLine()!

答案 9 :(得分:0)

import Foundation
print("Enter a number")
let number : Int = Int(readLine(strippingNewline: true)!) ?? 0
if(number < 5)
{
    print("Small")
}else{
    print("Big")
}
for i in 0...number{
    print(i)
}

答案 10 :(得分:0)

var a;
scanf("%s\n", n);

我在ObjC中进行了测试,也许这会很有用。

答案 11 :(得分:0)

该问题有很多过时的答案。从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中似乎也有问题。

答案 12 :(得分:0)

当在Xcode上运行readLine()函数时,调试控制台等待输入。输入完成后,其余代码将恢复。

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

答案 13 :(得分:0)

如果要读取空格分隔的字符串,并立即将字符串拆分为数组,则可以执行以下操作:

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)")

答案 14 :(得分:0)

这适用于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
}

答案 15 :(得分:0)

<强>之前

enter image description here

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

<强>校正

enter image description here

答案 16 :(得分:0)

由于这个问题没有花哨的解决方案,我创建了一个小类来读取和解析Swift中的标准输入。你可以找到它here

示例

解析:

+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"
}

答案 17 :(得分:0)

我向上帝发誓..这个完全基本的问题的解决方案在我看来已经没有了。它的很简单 ..但是那里有太多模糊/不好的信息;希望我可以保存某人 某些来自我最终的无底rabbit holes ......

那么,让我们得到一个&#34;字符串&#34;来自&#34;用户&#34;通过&#34;控制台&#34;,通过stdin我们

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

如果你想要没有尾随换行符,只需添加...

[ ... stringByTrimmingCharactersInSet:
                       NSCharacterSet.newlineCharacterSet];

Ta Da! ♥ⱥᏪℯⅩ

答案 18 :(得分:-1)

我现在可以使用以下内容在Swift中获取键盘输入:

在我的main.swift文件中,我声明了一个变量i并为其分配了我在Objective C中定义的函数GetInt()。通过所谓的Bridging Header,我在其中声明了GetInt的函数原型,我可以链接到main。迅速。以下是文件:

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编程,这意味着没有需要包含一个真正的swift文件,如user.c或类似的东西。

希望我能提供帮助,

编辑:无法通过C获取字符串输入,因为我在这里使用CInt - &gt; C的整数类型而不是Swift的整数类型。 C char *没有等效的Swift类型。因此String不能转换为字符串。但是这里有足够的解决方案来获取String输入。

劳尔

答案 19 :(得分:-1)

我只是想对xenadu的实现发表评论(我没有足够的代表),因为OS X中的CCharInt8,而当你在{添加到数组时'时,Swift根本不喜欢{1}}返回UTF-8的部分或7位以上的任何其他内容。

我使用的是getchar()数组,而且效果很好,UInt8String.fromCString转换为UTF-8就好了。

然而,这就是我做的方式

UInt8