Reputation: 1118
I'm new to Rust and looking to understand concepts like borrowing. I'm trying to create a simple two dimensional array using standard input. The code:
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;
}
}
}
This won't compile because the outputs
variable lifetime is not long enough:
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
How can I get the iterated values out of the block into values array?
Upvotes: 5
Views: 2283
Reputation: 430310
This answer was moved from the question, where it solved the OPs needs.
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;
}
}
}
Upvotes: 1
Reputation: 13752
split()
gives you substrings (string slices) borrowed from the original string, and the original string is outputs
from line 6.
outputs
: when a loop iteration ends, outputs
is deallocated.
Since values
is longer lived, the slices can't be stored there.outputs
across a modification of outputs
. So even if the String
outputs
itself was defined before values
, we couldn't easily put the string slices from .split()
into values
; modifying the string (reading into it) invalidates the slices.A solution needs to either
String
, and when you assign an element from the split iterator, make a String
from the &str
using .to_string()
. I would recommend this solution. (However an array of String
is not at as easy to work with, maybe already this requires using Vec
instead.) 1&str
that borrows from the input String
. This is good if the nested array is something that you only need temporarily.1: You can use something like vec![vec![String::new(); 6]; 6]
instead
Upvotes: 7