ฉันพยายามรับข้อมูลแป้นพิมพ์สำหรับแอปบรรทัดคำสั่งสำหรับภาษาโปรแกรม Apple ใหม่ Swift
ฉันสแกนเอกสารแล้วก็ไม่มีประโยชน์
import Foundation
println("What is your name?")
???
ความคิดใด ๆ ?
ฉันพยายามรับข้อมูลแป้นพิมพ์สำหรับแอปบรรทัดคำสั่งสำหรับภาษาโปรแกรม 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 เวอร์ชันล่าสุดต้องการตัวพิมพ์ที่ชัดเจน (ทำงานใน 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
มีทางเลือกที่จะไม่เป็น ฉันสร้างตัวอย่างเล็กน้อย:
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);
แก้ไขในฐานะของสวิฟท์ 2.2 readLine
ห้องสมุดมาตรฐานรวมถึง ฉันจะสังเกตด้วยว่า Swift เปลี่ยนไปใช้ความคิดเห็นเอกสาร markdown ทิ้งคำตอบเดิมของฉันไว้สำหรับบริบททางประวัติศาสตร์
เพื่อความสมบูรณ์นี่คือการใช้งาน Swift ที่readln
ฉันเคยใช้ มีพารามิเตอร์ที่เป็นทางเลือกเพื่อระบุจำนวนไบต์สูงสุดที่คุณต้องการอ่าน (ซึ่งอาจเป็นความยาวของ String หรือไม่ก็ได้)
นอกจากนี้ยังแสดงให้เห็นถึงการใช้ความคิดเห็น 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) }
}
โดยทั่วไปแล้วฟังก์ชั่น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
อีกทางเลือกหนึ่งคือการเชื่อมโยงlibeditสำหรับการแก้ไขบรรทัดที่เหมาะสม (ปุ่มลูกศร ฯลฯ ) และการสนับสนุนประวัติเสริม ผมอยากนี้สำหรับโครงการฉันเริ่มและใส่กันตัวอย่างเช่นขั้นพื้นฐานสำหรับวิธีการที่ผมตั้งขึ้น
การใช้งานจากรวดเร็ว
let prompt: Prompt = Prompt(argv0: C_ARGV[0])
while (true) {
if let line = prompt.gets() {
print("You typed \(line)")
}
}
ObjC wrapper เพื่อแสดง 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 () รับอินพุตจากคอนโซลสำหรับหมายเลขแรกจากนั้นกด 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 2+ ไลบรารีมาตรฐานของ Swift มีฟังก์ชันreadline () มันจะส่งคืนตัวเลือก แต่จะเป็นศูนย์ก็ต่อเมื่อถึง 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 ของบรรทัดคำสั่งเช่นกัน
ฉันขอสาบานต่อพระเจ้า .. การแก้ปัญหาพื้นฐานนี้ทำให้ฉันหายไปนานหลายปี มันง่ายมาก .. แต่มีข้อมูลที่คลุมเครือ / ไม่ดีอยู่มากมาย หวังว่าฉันสามารถบันทึกคนจากบางส่วนของก้นหลุมกระต่ายที่ผมสิ้นสุดลงใน ...
ดังนั้นแล้วช่วยให้ของได้รับ "สตริง" จาก "ผู้ใช้" ผ่าน "คอนโซล" ผ่านstdin
,เราจะ ?
[NSString.alloc initWithData:
[NSFileHandle.fileHandleWithStandardInput availableData]
encoding:NSUTF8StringEncoding];
หากคุณต้องการโดยไม่ต้องขึ้นบรรทัดใหม่เพียงเพิ่ม ...
[ ... stringByTrimmingCharactersInSet:
NSCharacterSet.newlineCharacterSet];
Ta Da!
♥ⱥᏪℯⅩ
Swift 5: หากคุณต้องการป้อนข้อมูลจากแป้นพิมพ์อย่างต่อเนื่องโดยไม่สิ้นสุดโปรแกรมเช่นสตรีมอินพุตให้ใช้ขั้นตอนด้านล่าง:
สร้างโปรเจ็กต์ใหม่ของประเภท comnnad line tool
เพิ่มโค้ดด้านล่างในไฟล์ 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:")
}
เนื่องจากไม่มีวิธีแก้ปัญหาที่แปลกใหม่สำหรับปัญหานี้ฉันจึงสร้างคลาสเล็ก ๆ เพื่ออ่านและแยกวิเคราะห์อินพุตมาตรฐานใน 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"
}
สิ่งนี้ใช้ได้ใน 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)
}
คำตอบอันดับต้น ๆ สำหรับคำถามนี้แนะนำให้ใช้เมธอด readLine () เพื่อป้อนข้อมูลผู้ใช้จากบรรทัดคำสั่ง อย่างไรก็ตามฉันต้องการทราบว่าคุณต้องใช้! ตัวดำเนินการเมื่อเรียกวิธีนี้เพื่อส่งคืนสตริงแทนที่จะเป็นทางเลือก:
var response = readLine()!
readLine()
ส่งคืนตัวเลือกด้วยเหตุผลดังนั้นจึงไม่ปลอดภัยที่จะบังคับแกะและไม่ได้เพิ่มอะไรลงไปในตัวอย่าง
var a;
scanf("%s\n", n);
ฉันทดสอบสิ่งนี้ใน ObjC และอาจเป็นประโยชน์
ฉันแค่อยากจะแสดงความคิดเห็น (ฉันมีตัวแทนไม่เพียงพอ) ในการใช้งานของ 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 และกำหนดให้มันเป็นฟังก์ชัน GetInt () ซึ่งฉันกำหนดไว้ใน Objective C ผ่านสิ่งที่เรียกว่า Bridging Header ซึ่งฉันได้ประกาศต้นแบบฟังก์ชันสำหรับ 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 ซึ่งช่วยให้คุณสามารถเขียนโปรแกรมใน C ใน Objective-C ซึ่งหมายความว่าไม่จำเป็นต้องรวม ไฟล์ที่รวดเร็วจริงเช่น user.c หรืออะไรทำนองนั้น
หวังว่าฉันจะช่วยได้
แก้ไข: ไม่สามารถรับอินพุตสตริงผ่าน C ได้เนื่องจากที่นี่ฉันใช้ CInt -> ประเภทจำนวนเต็มของ C ไม่ใช่ Swift ไม่มีประเภท Swift ที่เทียบเท่าสำหรับถ่าน C * ดังนั้น String จึงไม่สามารถแปลงเป็นสตริงได้ แต่มีวิธีแก้ปัญหาที่เพียงพอในการรับอินพุตสตริง
ราอูล