Programing

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

crosscheck 2020. 9. 7. 07:40
반응형

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


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

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

import Foundation

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

어떤 아이디어?


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

예:

let response = readLine()

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


나는 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
}

실제로 그렇게 쉽지는 않습니다. 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);

편집 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) }
}

또 다른 대안은 적절한 행 편집 (화살표 키 등) 및 선택적 히스토리 지원을 위해 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

일반적으로 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

여기에 이미지 설명 입력


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

산출


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

var response = readLine()!

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

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

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

[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
}

공백으로 구분 된 문자열을 읽고 즉시 문자열을 배열로 분할하려면 다음과 같이 할 수 있습니다.

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

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

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

이 질문에 대한 오래된 답변이 많이 있습니다. 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에도 문제가있는 것 같습니다.


난 그냥 때문에, xenadu의 구현에 (I 충분하지 담당자가) 코멘트에 원하는 CCharOS X에 Int8, 당신은 배열에 추가 할 때 스위프트는 전혀 좋아하지 않는 경우 getchar()UTF-8 또는 7 비트 위의 아무것도의 반환 부분.

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

이제 다음을 사용하여 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 유형은 없습니다. 따라서 문자열은 문자열로 변환 할 수 없습니다. 그러나 여기에는 문자열 입력을 얻기에 충분한 솔루션이 있습니다.

라울

참고 URL : https://stackoverflow.com/questions/24004776/input-from-the-keyboard-in-command-line-application

반응형