2016-01-07 12 views
5

Sono nuovo di Rust e cerco di capire concetti come il prestito. Sto cercando di creare un semplice array bidimensionale usando l'input standard. Il codice:Come iterare ed estrarre valori da un ciclo for in Rust

use std::io; 

fn main() { 
    let mut values = [["0"; 6]; 6]; // 6 * 6 array 

    // iterate 6 times for user input 
    for i in 0..6 { 
     let mut outputs = String::new(); 
     io::stdin().read_line(&mut outputs).expect(
      "failed to read line", 
     ); 

     // read space separated list 6 numbers. Eg: 5 7 8 4 3 9 
     let values_itr = outputs.trim().split(' '); 
     let mut j = 0; 
     for (_, value) in values_itr.enumerate() { 
      values[i][j] = value; 
      j += 1; 
     } 
    } 
} 

Questo non compilato perché la durata variabile outputs non è abbastanza lungo:

error[E0597]: `outputs` does not live long enough 
    --> src/main.rs:20:5 
    | 
14 |   let values_itr = outputs.trim().split(' '); 
    |       ------- borrow occurs here 
... 
20 |  } 
    | ^`outputs` dropped here while still borrowed 
21 | } 
    | - borrowed value needs to live until here 

Come posso ottenere i valori ripetuti fuori dal blocco in valori array?

risposta

6

split() si dà sottostringhe (fette stringa) mutuati dalla stringa originale, e la stringa originale è outputs dalla linea 6.

  1. La stringa fette non può sopravvivere alla portata di outputs: quando un ciclo di iterazione termina, outputs è deallocato. Poiché values è più lungo, le sezioni non possono essere memorizzate lì.
  2. Non possiamo prendere in prestito fette di outputs attraverso una modifica di outputs. Pertanto, anche se lo outputs è stato definito prima dello values, non è stato possibile inserire facilmente le sezioni di stringa da .split() in values; modificando la stringa (leggendo in essa) invalida le sezioni.

Una soluzione deve sia

  • utilizzare una matrice nidificata di String, e quando si assegna un elemento del iteratore scissione, fare una String dal &str utilizzando .to_string(). Consiglierei questa soluzione. (Tuttavia un array di String non è facile da lavorare, magari già questo richiede l'uso Vec invece.)
  • leggere tutte ingresso prima di costruire una matrice nidificata di &str che attinge ingresso String. Questo è buono se l'array nidificato è qualcosa che è necessario solo temporaneamente.

: Si può usare qualcosa di simile vec![vec![String::new(); 6]; 6] invece

+0

Sarebbe l'ideale se posso risolvere questo utilizzando gli array. Ma sembra che non ci sia modo di creare una serie di stringhe in Rust. Non è vero? Il primo metodo funziona bene con i vettori. Grazie per la risposta .. (compreso il tuo ultimo commento su IRC) "valore è un & str, una sottostringa da output. Così .to_string() alloca lo spazio per una stringa e copia la sottostringa in quel valore. riferimento) ma viene trasformato in una stringa, poiché non è un riferimento, non è limitato dal controllo del prestito o dalla durata delle "uscite". " – vimukthi

+0

Non esiste un * bel * modo per creare una serie di stringhe. '[[String :: new(), String :: new(), String :: new(), String :: new(), String :: new(), String :: new()], [String :: new(), String :: new(), String :: new(), String :: new(), String :: new(), String :: new()], ...] 'sicuramente non è bello . – bluss

1

Questa risposta è stata spostata dalla domanda, in cui ha risolto i bisogni PO.

use std::io; 

fn main() { 
    let mut values = vec![vec![String::new(); 6]; 6]; 
    for i in 0..6 { 
     let mut outputs = String::new(); 
     io::stdin().read_line(&mut outputs) 
       .expect("failed to read line"); 

     let values_itr = outputs.trim().split(' '); 
     let mut j = 0; 
     for (_, value) in values_itr.enumerate() { 
      values[i][j] = value.to_string(); 
      j += 1; 
     } 
    } 
}