명령줄 응용 프로그램의 키보드 입력
새로운 애플 프로그래밍 언어 스위프트의 명령줄 앱에 대한 키보드 입력을 시도하고 있습니다.
서류를 스캔해 보았으나 소용이 없었습니다.
import Foundation
println("What is your name?")
???
무슨 생각 있어요?
올바른 방법은 Swift Standard Library에서 사용하는 것입니다.
예:
let response = readLine()
입력한 텍스트를 포함하는 Optional 값을 제공합니다.
저는 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
}
C API와 상호 작용해야 하기 때문에 사실 쉽지 않습니다.에 대한 대안은 없습니다.scanf가 작은 제가 한 가지 예를 들어보겠습니다.
본심의
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);
일반적으로 readLine() 기능은 콘솔에서 입력을 스캔하는 데 사용됩니다.그러나 "명령줄 도구"를 추가하거나 추가하지 않는 한 일반 iOS 프로젝트에서는 작동하지 않습니다.
테스트에 가장 적합한 방법은 다음과 같습니다.
1. macOS 파일 만들기
2. readLine() 기능을 사용하여 콘솔에서 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
Swift 2.2 기준으로 편집 표준 라이브러리는 다음을 포함합니다.readLine가 의사 으로 바꿨다는 스위프트가 문서 의견을 축소하는 쪽으로 전환한 것도 주목하겠습니다.역사적 맥락에 대한 나의 원답을 남깁니다.
완성도를 높이기 위해 다음과 같이 Swift를 구현합니다.readln계속 써왔어요.읽을 최대 바이트 수(String의 길이일 수도 있고 아닐 수도 있음)를 나타내는 선택적 매개변수가 있습니다.
이는 swiftdoc 주석이 적절하게 사용되는지도 보여줍니다. Swiftdoc 파일은 <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을 연결하는 것입니다.저는 제가 시작하는 프로젝트를 위해 이것을 원했고 그것을 어떻게 설정했는지에 대한 기본적인 예를 만들었습니다.
swift에서 사용
let prompt: Prompt = Prompt(argv0: C_ARGV[0])
while (true) {
if let line = prompt.gets() {
print("You typed \(line)")
}
}
ObjC 포장지로 Libed it을 노출시킵니다.
#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
이 질문에 대한 시대에 뒤떨어진 답들이 많습니다.Swift 2+부터는 Swift Standard Library에 readline() 기능이 포함되어 있습니다.옵션이 반환되지만 EOF에 도달한 경우에만 0이 됩니다. 이는 키보드에서 입력을 받을 때 발생하지 않으므로 해당 시나리오에서 강제로 안전하게 포장을 풀 수 있습니다.사용자가 아무 것도 입력하지 않으면 (포장되지 않은) 값은 빈 문자열이 됩니다.최소 하나 이상의 문자를 입력할 때까지 재귀를 사용하여 사용자에게 메시지를 표시하는 작은 유틸리티 기능은 다음과 같습니다.
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)")
옵션 바인딩(입력 = readLine())을 사용하여 다른 답변에서 제안한 대로 입력되었는지 확인하면 키보드 입력을 수락할 때 영(0)이 되지 않고 적어도 ""이 되지 않기 때문에 원하는 효과를 얻을 수 없습니다.
이 기능은 Playground 또는 명령 프롬프트에 액세스할 수 없는 다른 환경에서는 작동하지 않습니다.명령줄 REPL에도 문제가 있는 것 같습니다.
콘솔 기반 응용 프로그램에서 사용자로부터 입력을 받는 간단한 예는 다음과 같습니다.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)
Swift 5 : 입력 스트림처럼 프로그램을 종료하지 않고 키보드에서 계속 입력을 원할 경우 아래 단계를 사용합니다.
새 프로젝트 유형의 커맨나드 선 도구 만들기
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:") }- 프로젝트를 실행하고 Xcode의 Products 폴더 아래에 있는 실행 파일을 클릭하고 finder에서 엽니다.
- 실행 파일을 두 번 클릭하여 엽니다.
- 이제 Inputs(입력)터미널은 다음과 같이 나타납니다.
이 문제에 대한 화려한 해결책이 없었기 때문에 스위프트의 표준 입력을 읽고 파싱하는 작은 클래스를 만들었습니다.여기에서 찾을 수 있습니다.
예
구문 분석 방법:
+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)")
Xcode에서 readLine() 함수를 실행하면 디버그 콘솔이 입력을 기다립니다.나머지 코드는 입력이 끝나면 다시 시작됩니다.
let inputStr = readLine()
if let inputStr = inputStr {
print(inputStr)
}
xenadu의 구현에 대해 언급하고 싶었을 뿐입니다. 왜냐하면,CChar는 OS X에서Int8, 그리고 스위프트는 당신이 배열에 추가할 때 전혀 좋아하지 않습니다.getchar()UTF-8의 일부 또는 7비트 이상의 다른 부분을 반환합니다.
나는 배열을 사용하고 있습니다.UInt8대신에, 잘 작동하고 그리고String.fromCString변환합니다.UInt8UTF-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)")
}
}
저는 이제 다음을 사용하여 스위프트에서 키보드 입력을 받을 수 있게 되었습니다.
main.swift 파일에서 변수 i를 선언하고 목표 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뿐만 아니라 c 표준 라이브러리 stdlib도 포함할 수 있습니다.h를 사용하면 Objective-C에서 C로 프로그래밍할 수 있으므로 user.c와 같은 실제 swift 파일을 포함할 필요가 없습니다.
내가 도울 수 있길 바라면서,
편집 : 스위프트가 아닌 C의 정수형인 CInt ->를 사용하고 있기 때문에 C를 통한 String 입력은 불가능합니다.Char*에 해당하는 Swift 유형이 없습니다.따라서 String은 string으로 변환할 수 없습니다.하지만 이 주변에는 String 입력을 받기에 충분한 솔루션이 있습니다.
라울
이 질문에 대한 상위 순위의 답변은 readLine() 메서드를 사용하여 명령줄에서 사용자 입력을 수신할 것을 제안합니다.그러나 이 메서드를 호출할 때 옵션 대신 문자열을 반환하려면 ! 연산자를 사용해야 합니다.
var response = readLine()!
var a;
scanf("%s\n", n);
ObjC에서 테스트해봤는데, 아마 유용할 것 같습니다.
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)
}
언급URL : https://stackoverflow.com/questions/24004776/input-from-the-keyboard-in-command-line-application
'programing' 카테고리의 다른 글
| 다중 및 단일 인덱스 (0) | 2023.10.19 |
|---|---|
| 인수를 인수로 하는 함수 전달? (0) | 2023.10.19 |
| PowerShell로 텍스트 파일 맨 위 줄 제거 (0) | 2023.10.19 |
| 입력 요소에는 자동 완성 속성이 있어야 합니다. (0) | 2023.10.14 |
| UIRepreshControl을 UIScrol View에서 사용할 수 있습니까? (0) | 2023.10.14 |




