명령 줄 응용 프로그램에서 키보드로 입력


92

새로운 Apple 프로그래밍 언어 Swift에 대한 명령 줄 앱의 키보드 입력을 얻으려고합니다.

문서를 스캔하여 아무 소용이 없습니다.

import Foundation

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

어떤 아이디어?

답변:


136

이를 수행하는 올바른 방법 readLine은 Swift Standard Library에서 를 사용하는 것 입니다.

예:

let response = readLine()

입력 한 텍스트가 포함 된 선택적 값을 제공합니다.


2
감사. 암호 종류를 입력하는 방법이 있습니까?
Abhijit Gaikwad

나를 위해, response = nil로이 줄을 통과합니다. 문제가 무엇인지 아십니까?
피터 웹의

4
@PeterWebb는 - :) 놀이터를 통해 폭포, 엑스 코드 터미널에서 잘 작동
aprofromindia

2
readLine은 대부분의 원래 답변 뒤에 추가되었으므로 태도는 약간 부당합니다 IMHO
russbishop

2
Swift 3, SlimJim 수정
Ezekiel Elin

62

나는 C로 떨어지지 않고 그것을 알아낼 수 있었다.

내 솔루션은 다음과 같습니다.

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

최신 버전의 Xcode에는 명시적인 typecast가 필요합니다 (Xcode 6.4에서 작동).

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

5
저는이 기능을 좋아합니다. 또한 프로그램에서 입력을 한 번만 받아야하는 경우와 같이 함수를 정의하지 않으려면 한 줄로 압축 할 수 있습니다.var input = NSString(data: NSFileHandle.fileHandleWithStandardInput().availableData, encoding:NSUTF8StringEncoding)
jcmiller11

3
플레이 그라운드에서 이것을 사용하여 사용자 입력을 즉석에서 받아들이는 방법이 있습니까?
Rob Cameron

5
놀이터에서는 사용할 수 없습니다. 거기에서 변수를 사용해야합니다.
Chalkers

8
이것으로 문자열에 줄 바꿈을 얻을 수 있습니다. 그들을 밖으로 스트립string.stringByTrimmingCharactersInSet(NSCharacterSet.newlineCharacterSet())
PK-NB

3
또한 사용자가 문자를 삭제하거나 화살표 키 등을 사용하면 이상한 문자가 표시됩니다. AAAGGGGGHHHH WHY, Swift, Why?
ybakos 2015-04-15

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-Bridging-Header.h

void getInput(int *output);

오 이런-이보다 더 사소한 것이 있었으면 좋겠다! 문자열에 적용하기가 어렵습니다.
Chalkers

1
함수 정의를 저장하기 위해 "UserInput.h"를 생성하고 "cliinput-Bridging-Header.h"에이 파일을 포함하는 것이 좋습니다.
Alan Zhiliang Feng

7

편집 Swift 2.2부터 표준 라이브러리에는 readLine. 또한 Swift가 문서 주석을 마크 다운으로 전환 한 것에 주목할 것입니다. 역사적 맥락에 대한 나의 원래 대답을 남겨 둡니다.

완전성을 위해 여기에 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) }
}

나는 swiftdoc 주석과 "공용"액세스 수정자를 좋아합니다. 이전에는 Swift에서 그런 종류를 본 적이 없었지만 CChar와 C-String은 C 및 8 비트 문자 세트와 Swift에 대한 후퇴 인 것 같습니다. 유니 코드 텍스트에 관한 것입니다 ... 또는 명령 줄 도구가 모두 ASCII입니까 ??
Kaydell

2
getchar ()가 ASCII를 반환한다고 생각합니다. 유니 코드 단자는 내가 :)에 들어갈 싶지 않았다 전체 일
russbishop

6

일반적으로 readLine () 함수는 콘솔에서 입력을 스캔하는 데 사용됩니다. 그러나 "명령 줄 도구" 를 추가하거나 추가하지 않는 한 일반 iOS 프로젝트에서는 작동하지 않습니다 .

테스트를위한 가장 좋은 방법은 다음과 같습니다.

1. macOS 파일 생성

여기에 이미지 설명 입력

2. readLine () func를 사용하여 콘솔에서 선택적 문자열을 스캔합니다.

 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

여기에 이미지 설명 입력


5

또 다른 대안은 적절한 행 편집 (화살표 키 등) 및 선택적 히스토리 지원을 위해 libedit 를 링크 하는 것입니다. 나는 내가 시작하는 프로젝트를 위해 이것을 원했고 그것을 설정하는 방법에 대한 기본 예제를 모았 습니다 .

신속한 사용

let prompt: Prompt = Prompt(argv0: C_ARGV[0])

while (true) {
    if let line = prompt.gets() {
        print("You typed \(line)")
    }
}

libedit를 노출하는 ObjC 래퍼

#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

3

다음은 콘솔 기반 애플리케이션에서 사용자로부터 입력을받는 간단한 예입니다. 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)

산출


2

이 질문에 대한 오래된 답변이 많이 있습니다. Swift 2+부터 Swift Standard Library에는 readline () 함수 가 포함되어 있습니다 . Optional을 반환하지만 EOF에 도달 한 경우에만 nil이됩니다. 이는 키보드에서 입력을받을 때 발생하지 않으므로 이러한 시나리오에서 강제로 안전하게 풀 수 있습니다. 사용자가 아무것도 입력하지 않으면 (래핑되지 않은) 값은 빈 문자열이됩니다. 다음은 적어도 하나의 문자가 입력 될 때까지 사용자에게 메시지를 표시하기 위해 재귀를 사용하는 작은 유틸리티 함수입니다.

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

선택적 바인딩 (if let input = readLine ())을 사용하여 다른 답변에서 제안 된대로 입력되었는지 확인하면 키보드 입력을 수락 할 때 nil이 아니고 ""이상이되지 않으므로 원하는 효과가 없습니다.

플레이 그라운드 또는 명령 프롬프트에 액세스 할 수없는 기타 환경에서는 작동하지 않습니다. 명령 줄 REPL에도 문제가있는 것 같습니다.


1

나는 신에게 맹세한다.이 근본적인 문제에 대한 해결책 은 몇 년 동안 나를 피했다. 그건 너무 간단 ...하지만 훨씬 막연한 / 잘못된 정보가 부족하므로이있다; 다행스럽게도 필자는 절약 할 수 있는 사람 에서 약간 밑의 토끼 구멍 난에서 끝냈다을 ...

그럼,를 통해,의는 "콘솔"을 통해 "사용자"에서 "문자열"을 얻을 수 있습니다 stdin, 우리는해야 ?

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

후행 개행 없이 원하는 경우 추가하십시오 ...

[ ... stringByTrimmingCharactersInSet:
                       NSCharacterSet.newlineCharacterSet];

Ta Da! ♥ ⱥ ᏪℯⅩ


4
Swift, OP는 Swift를 말합니다.
HenryRootTwo

1
그는 osx라고 말했습니다. 그것은 모두 같은 것으로 컴파일됩니다! 내면의 ObjC를 받아들이세요!
Alex Gray

2
Swift로 작성하고 Objective C를 결코 배우지 않을 사람들이 있습니다. 이것은 그것이 컴파일되는 것에 관한 것이 아닙니다.
HenryRootTwo

0

이 문제에 대한 멋진 해결책이 없었기 때문에 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"
}

StreamScanner 클래스를 가져 오는 방법은 무엇입니까?
Timothy Swan

Readme의 설치 섹션 ( github.com/shoumikhin/StreamScanner#installation )에 설명 된대로 @TimothySwan . 따라서 기본적으로 StreamScanner.swift 파일을 프로젝트에 추가 할 수 있습니다.
shoumikhin


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
}

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

0

readLine () 함수가 Xcode에서 실행되면 디버그 콘솔이 입력을 기다립니다. 나머지 코드는 입력이 완료된 후 다시 시작됩니다.

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

0

이 질문에 대한 최상위 답변은 readLine () 메서드를 사용하여 명령 줄에서 사용자 입력을받는 것을 제안합니다. 그러나 나는 당신이! 선택적 대신 문자열을 반환하기 위해이 메서드를 호출 할 때 연산자 :

var response = readLine()!

force-unwrap readLine()이 이유 때문에 선택 사항을 반환하는 이유는 force-unwrap이 안전하지 않으며 실제로 예제에 아무것도 추가하지 않습니다.
Camsoft

0

Swift 5 : 입력 스트림과 같이 프로그램을 종료하지 않고 키보드에서 계속 입력하려면 아래 단계를 사용하십시오.

  1. comnnad line tool 유형의 새 프로젝트 만들기 명령 줄 프로젝트

    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. 프로젝트를 실행하고 Xcode의 Products 폴더에서 실행 파일을 클릭하고 Finder에서 엽니 다.
    3. 실행 파일을 두 번 클릭하여 엽니 다.
    4. 이제 입력을 입력하십시오. 터미널은 다음과 같습니다. 여기에 이미지 설명 입력

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

ObjC에서 이것을 테스트했으며 아마도 이것이 유용 할 것입니다.


-1

나는 xenadu의 구현에 대해 언급하고 싶었습니다 (나는 충분한 담당자가 없습니다). 왜냐하면 CCharOS X에서는이고 Int8, getchar()UTF-8의 일부를 반환하거나 7 비트 이상의 다른 것을 반환 할 때 배열에 추가 할 때 Swift는 전혀 좋아하지 않기 때문 입니다 .

UInt8대신 배열을 사용하고 있으며 잘 작동하며 UTF-8로 잘 String.fromCString변환 UInt8됩니다.

그러나 이것이 내가 한 방법입니다.

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

-1

이제 다음을 사용하여 Swift에서 키보드 입력을 얻을 수 있습니다.

내 main.swift 파일에서 나는 변수 i를 선언하고 Objective C에서 정의한 GetInt () 함수를 할당했습니다. GetInt에 대한 함수 프로토 타입을 선언 한 소위 Bridging Header를 통해 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뿐만 아니라 Objective-C에서 C로 프로그래밍 할 수있는 c 표준 라이브러리 stdlib.h를 포함 할 수 있습니다. 이는 포함 할 필요가 없음을 의미합니다. user.c 또는 이와 유사한 실제 빠른 파일.

내가 도울 수 있기를 바랍니다.

편집 : 여기에서는 CInt-> Swift가 아닌 C의 정수 유형을 사용하고 있기 때문에 C를 통해 문자열 입력을 얻을 수 없습니다. C char *에 해당하는 Swift 유형은 없습니다. 따라서 문자열은 문자열로 변환 할 수 없습니다. 그러나 여기에는 문자열 입력을 얻기에 충분한 솔루션이 있습니다.

라울

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.