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?
Keyword break When associated with loop , a break expression may be used to return a value from that loop. This is only valid with loop and not with any other type of loop. If no value is specified, break; returns () .
One of the uses of a loop is to retry an operation until it succeeds. If the operation returns a value though, you might need to pass it to the rest of the code: put it after the break , and it will be returned by the loop expression.
You cannot return a value from a for loop in java. Only methods have the privilege of returning values. for loop is a control flow statement whose purpose is to iterate through the number of times till the condition is true. While iterating, you can define statements which needs to be executed.
Loops. Rust supports four loop expressions: A loop expression denotes an infinite loop. A while expression loops until a predicate is false.
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
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;
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With