2014-10-23 17 views
7

मैं STDIN पर संख्या की एक स्ट्रिंग (उदाहरण के लिए "4 10 से 30 232,312") लिख रहा हूँ में कन्वर्ट करने के लिए किसी सरणी ints की वेक्टर और मुझे लगता है कि पढ़ सकते हैं और पूर्णांक की एक सरणी में कनवर्ट (करना चाहते हैं या एक सदिश) जंग में, सही तरीके से नहीं मिल रहा है अब तक मेरे पास है:नंबर की एक स्ट्रिंग/जंग

use std::io; 

fn main() { 
    let mut reader = io::stdin(); 
    let numbers = reader.read_line().unwrap(); 
} 

अग्रिम

उत्तर

8

जंग 1.5.x पर, एक काम कर समाधान है:

fn main() {  
    let mut numbers = String::new(); 

    io::stdin().read_line(&mut numbers).ok().expect("read error"); 

    let numbers: Vec<i32> = numbers 
     .split_whitespace() 
     .map(|s| s.parse().unwrap()) 
     .collect(); 

    for num in numbers { 
     println!("{}", num); 
    } 
} 
12

जंग 1.x के लिए अपडेट किया गया धन्यवाद

आप क्या कर सकते हैं इस तरह कुछ:

use std::io::{self, BufRead};     // (a) 

fn main() { 
    let reader = io::stdin(); 
    let numbers: Vec<i32> = 
     reader.lock()       // (0) 
       .lines().next().unwrap().unwrap() // (1) 
       .split(' ').map(|s| s.trim())  // (2) 
       .filter(|s| !s.is_empty())  // (3) 
       .map(|s| s.parse().unwrap())  // (4) 
       .collect();      // (5) 
    println!("{:?}", numbers); 
} 

सबसे पहले, हम stdin का एक ताला लेते हैं जो आपको एक buffered पाठक के रूप में stdin के साथ काम करने देता है (डिफ़ॉल्ट रूप से जंग में stdin unbuffered है; आप उस पर lock() विधि कॉल करने के इसके बारे में एक बफ़र संस्करण प्राप्त करने की आवश्यकता है, लेकिन इस बफ़र संस्करण केवल अपने कार्यक्रम में सभी धागे के लिए एक इसलिए यह करने के लिए उपयोग सिंक्रनाइज़ किया जाना चाहिए है,)।

इसके बाद, हम अगली पंक्ति को पढ़ने (1); मैं lines() इटरेटर जिसका next() विधि रिटर्न Option<io::Result<String>> उपयोग कर रहा हूँ, इसलिए केवल String आप दो बार unwrap() की जरूरत प्राप्त करने के लिए।

तो हम अतिरिक्त व्हाइट से रिक्त स्थान और ट्रिम जिसके परिणामस्वरूप हिस्सा द्वारा इसे विभाजित (2), खाली हिस्सा जो i32 रों (4) को तार (3), कन्वर्ट ट्रिमिंग के बाद छोड़ दिया गया हटाने और (एक वेक्टर के लिए परिणाम इकट्ठा 5)।

हमें lines() विधि का उपयोग करने के लिए std::io::BufRead विशेषता (ए) आयात करने की भी आवश्यकता है।

आप पहले कि आपके इनपुट संख्या के बीच एक से अधिक स्थान नहीं होगा में जानते हैं, आप कदम को छोड़ सकते हैं (3) और ले जाने से trim() कॉल (2) (1):

let numbers: Vec<i32> = 
    reader.lock() 
      .lines().next().unwrap().unwrap() 
      .trim().split(' ') 
      .map(|s| s.parse().unwrap()) 
      .collect(); 

let numbers: Vec<i32> = 
    reader.read_line().unwrap().as_slice() 
     .split_whitespace() 
     .map(|s| s.parse().unwrap()) 
     .collect() 
: अद्यतन

जंग, हालांकि, पहले से ही एक विधि खाली स्थान के द्वारा अलग किए गए शब्दों का एक दृश्य में एक स्ट्रिंग को विभाजित करने के प्रदान करता है, split_whitespace() बुलाया

split_whitespace() सिर्फ अपने मूल उदाहरण की तरह split() और filter() का सिर्फ एक संयोजन है, वास्तव में है। यह split() तर्क में एक फ़ंक्शन का उपयोग करता है, हालांकि विभिन्न प्रकार के व्हाइटस्पेस के लिए जांच करता है, न केवल अंतरिक्ष वर्ण। आप इसका स्रोत here पा सकते हैं।

+0

धन्यवाद व्लादिमीर, आपने दिन बचाया। एक तरफ ध्यान दें, वाह, जंग वास्तव में गहन है! –

+1

मनमानी सफेद जगहों से विभाजित करने के लिए नियमित अभिव्यक्तियों का उपयोग करने का एक तरीका भी है। यह शायद टर्सर कोड देगा, लेकिन इसे गैर-मानक क्रेट्स का उपयोग करने की आवश्यकता है (हालांकि इसे वितरण में शामिल किया गया है)। उदाहरण [यहां] (http://doc.rust-lang.org/regex/enum.Regex.html#method.split) लगभग वही है जो आप चाहते हैं। –

+4

आप बस ['.words()'] (http://doc.rust-lang.org/nightly/std/str/trait.UnicodeStrSlice.html#tymethod.words) का उपयोग कर सकते हैं (केवल रिक्त स्थान से थोड़ा अधिक सामान्य , हालांकि)। – huon

1

सुरक्षित संस्करण। यह एक विफल पार्स को छोड़ देता है ताकि असफल असफल हो। एकल लाइन पढ़ने के लिए read_line का उपयोग करें।

let mut buf = String::new(); 

// use read_line for reading single line 
std::io::stdin().read_to_string(&mut buf).expect(""); 

// this one skips failed parses so that failed unwrap doesn't panic 
let v: Vec<i32> = buf.split_whitespace().filter_map(|w| w.parse().ok()).collect(); 

आप इस तरह के वेक्टरों के वेक्टर भी पढ़ सकते हैं।

let stdin = io::stdin(); 
let locked = stdin.lock(); 
let vv: Vec<Vec<i32>> = locked.lines() 
    .filter_map(
     |l| l.ok().map(
      |s| s.split_whitespace() 
       .filter_map(|word| word.parse().ok()) 
       .collect())) 
    .collect(); 

एक से ऊपर

2 424 -42 124 
42 242 23 22 241 
24 12 3 232 445 

तरह आदानों के लिए काम करता है तो उन्हें यह

[[2, 424, -42, 124], 
[42, 242, 23, 22, 241], 
[24, 12, 3, 232, 445]] 

filter_map में बदल जाता है को बंद करने कि Option<T> वापस आती है और सब None रों बाहर फिल्टर स्वीकार करता है।

ok()Result<R,E> से Option<R> बदलता है ताकि इस मामले में त्रुटियों को फ़िल्टर किया जा सके।

संबंधित मुद्दे