Search code examples
parsingrustreadfile

.next() method not found in `std::string::String`


I have a file containing something like:

144NFFFFL

I would like to be able to read each character and always converting the first 3 to an integer (i32) by parsing them. For some reason my .next() call does not compile.

fn main() {
    let mut test = Robot::new(0, 3, 4, Orientation::N, vec![Direction::F, Direction::F]);
    println!("id = {:#?} , x = {:#?} , y = {:#?} , ori = {:#?} , dir = {:#?} ,",test.id,test.x,test.y,test.orientation,test.direction);

    let mut file = File::open("instruction.txt").expect("Impossible d'ouvrire le fichier"); //ouverture du fichier instruction.txt et le stock dans la var mut
    let mut contenue = String::new();
    file.read_to_string(&mut contenue).expect("Impossible de lire le fichier");
    contenue = line!(.split_whitespace()).to_string();
    
    let mut tmp = (contenue.next()).to_string();
    test.id = tmp.parse::<i32>().unwarp();

    tmp = (contenue.next()).to_string();
    test.x = tmp.parse::<i32>().unwarp();

    tmp = (contenue.next()).to_string();
    test.y = tmp.parse::<i32>().unwarp();

    tmp = contenue.next();
    test.orientation = tmp;
}

the error =>

let mut tmp = (contenue.next()).to_string();
    |                             ^^^^ method not found in `std::string::String`

error[E0599]: no method named `next` found for struct `std::string::String` in the current scope
   --> src/main.rs:120:21
    |
120 |     tmp = (contenue.next()).to_string();
    |                     ^^^^ method not found in `std::string::String`

error[E0599]: no method named `next` found for struct `std::string::String` in the current scope
   --> src/main.rs:123:21
    |
123 |     tmp = (contenue.next()).to_string();
    |                     ^^^^ method not found in `std::string::String`

error[E0599]: no method named `next` found for struct `std::string::String` in the current scope
   --> src/main.rs:126:20
    |
126 |     tmp = contenue.next();
    |                    ^^^^ method not found in `std::string::String`

error[E0599]: no method named `next` found for struct `std::string::String` in the current scope
   --> src/main.rs:131:36
    |
131 |         let carac = match contenue.next()
    |                                    ^^^^ method not found in `std::string::String

Solution

  • next() is an iterator method. To use it, you need an iterator for your String. Usually that's chars().

    let iter = contenue.chars();
    

    Once you have an iterator of characters, you can iterate through only the first 3 characters with take(3). Then use collect() to join them together into a string. Then parse it.

    let id: u32 = iter
        .take(3)
        .collect::<String>()
        .parse::<u32>()
        .unwrap();
    println!("ID = {}", id);
    

    Since this is an iterator it will remember its position. The next call to iter.next() will be N. So we could print out the rest of the characters.

    for c in iter {
        println!("c = {}", c);
    } 
    
    error[E0382]: use of moved value: `iter`
      --> test.rs:12:14
       |
    3  |     let iter = contenue.chars();
       |         ---- move occurs because `iter` has type `std::str::Chars<'_>`, which does not implement the `Copy` trait
    4  |     
    5  |     let id: u32 = iter
       |                   ---- value moved here
    ...
    12 |     for c in iter {
       |              ^^^^ value used here after move
    

    The problem is iter.take() took ownership of the iterator. We need to use by_ref() to borrow it. And we need to make the iterator mutable.

    fn main() { 
        let contenue = "144NFFFFL";
        let mut iter = contenue.chars();
        
        let id: u32 = iter
            .by_ref()
            .take(3)
            .collect::<String>()
            .parse::<u32>()
            .unwrap();
        println!("ID = {}", id);   
        
        for c in iter {
            println!("c = {}", c);
        } 
    }