Why my code went wrong?

I am working with Cses-repetitions exercise.

use std::io;

fn main() {
    let dna = input().trim().to_string();
    println!("{}", dna);
    let mut n = 0;
    let mut longest = 0;
    let mut last_c = '_';
    for c in dna.chars() {
        if c != last_c {
            if n > longest {
                longest = n;
                println!("longest in if {}", longest);
            }
            last_c = c;
            n = 1;
            println!("n in if: {}", n);
        } else {
            n += 1;
            println!("n in else: {}", n);
        }
        println!("{}", longest);
    }
}

fn input() -> String {
    let mut input = String::new();
    io::stdin()
        .read_line(&mut input)
        .expect("Fail when readline");
    input
}

Two things I don't know what happen in here:

  1. When remove trim().to_string() the code works
  2. When the code works, here is the output, I used println marco to help debug easier:

I was thought the statement longest in if <num> must print every single iter but it was printed after the outer if done. Please explain how the code work, especially nested if inside for loop

Thank you very much!!!

The code seems to operate based on

  • counting up n while the current character doesn’t change
  • whenever it does change
    • see if current n is the longest (so far) and save it (overwriting the previous longest) if that’s the case
    • reset n to start counting the next sequence of repeated characters

The “longest in if ” line is only reached whenever the character changes, and longest is improved.

The input (without the trim) is aaaaa\n (the newline / line break at the end is relevant)

The first character change is the initial change from the stand-in _ to the first character a. In this case longest and n are both 0, so the “longest in if ”-printing line is not reached.

The second character change is from the last a to the trailing \n (line break). In this case, the number of as is considered and longest is updated, the “longest in if ”-printing line is reached.

On windows, there’s probably even “aaaaa\r\n” with a carriage return. This would explain why you see two occurrences of “n in if: 1” after the “longest in if 5”.

This should answer both questions

More on the first question:

If you do want to trim the string, then you need to properly handle the end of the string. Every character count is currently only considered and compared to longest when the next character that follows its last occurrence in a row is handled. I.e. in a string aabbbcccc, the number of a's is only handled on the first b, the number of b's on the first c, but the number of c's is never really considered if there’s no character like the \n following them. You can fix that by inserting an additional

    if n > longest {
        longest = n;
        println!("longest in if {}", longest);
    }

after the end of the whole loop.

Your answer is really helpful, I fixed my problem.

I have one more question. How to print the line have a trailing character from user like
"aaaabbbcc\r\n"

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.