env::args în Rust

Argumentele din linia de comandă cu care a fost pornit programul; primul este numele programului.

Sintaxă
use std::env;

pub fn args() -> Args   // Iterator<Item = String>

Ce face env::args

env::args() returnează un iterator peste argumentele programului, ca String-uri. Primul element este calea programului însuși, iar argumentele date de utilizator urmează după. Pentru cargo run -- Ana 3, iteratorul dă "target/debug/salut", "Ana", "3".

De obicei le aduni cu env::args().collect::<Vec<String>>() sau sari peste primul cu .skip(1). Dacă un argument nu este UTF-8 valid, args() intră în panică; varianta env::args_os() dă OsString și acceptă orice. Pentru opțiuni complicate (--ajutor, -v) se folosește de obicei crate-ul clap.

Ce returnează

Un iterator Args peste String.

Exemple

Exemplul 1: Program pornit fără argumente

Exemplul a rulat fără argumente, deci există doar numele programului (aici fișierul compilat se numește program) și se folosește valoarea implicită.

use std::env;
use std::path::Path;

fn main() {
    let argumente: Vec<String> = env::args().collect();
    println!("număr de argumente: {}", argumente.len());

    let program = Path::new(&argumente[0]).file_name().and_then(|n| n.to_str()).unwrap_or("?");
    println!("programul: {program}");

    let nume = env::args().nth(1).unwrap_or_else(|| String::from("vizitator"));
    println!("Salut, {nume}!");
}

Rezultat

număr de argumente: 1
programul: program
Salut, vizitator!

Exemplul 2: Argumente date de utilizator

Rezultatul este cel din terminal, după comanda cargo run -- Ana 3 (tot ce urmează după -- ajunge la program).

use std::env;

fn main() {
    let argumente: Vec<String> = env::args().collect();
    println!("argumente: {argumente:?}");

    let nume = argumente.get(1).map(String::as_str).unwrap_or("vizitator");
    let ori: u32 = argumente.get(2).and_then(|t| t.parse().ok()).unwrap_or(1);
    for _ in 0..ori {
        println!("Salut, {nume}!");
    }
}

Rezultat (cargo run – Ana 3)

argumente: ["target/debug/salut", "Ana", "3"]
Salut, Ana!
Salut, Ana!
Salut, Ana!

Exemplul 3: Funcție de procesare testabilă

Funcția primește orice iterator de texte. În main îi dăm argumentele reale, iar pentru test o listă scrisă în cod.

use std::env;

fn citeste_optiuni(args: impl Iterator<Item = String>) -> (bool, Vec<String>) {
    let mut detaliat = false;
    let mut fisiere = Vec::new();
    for a in args {
        if a == "-v" || a == "--detaliat" {
            detaliat = true;
        } else {
            fisiere.push(a);
        }
    }
    (detaliat, fisiere)
}

fn main() {
    println!("reale: {:?}", citeste_optiuni(env::args().skip(1)));

    let test = ["-v", "note.txt", "orar.csv"].map(String::from);
    println!("test:  {:?}", citeste_optiuni(test.into_iter()));
}

Rezultat

reale: (false, [])
test:  (true, ["note.txt", "orar.csv"])

Greșeli frecvente

  • Citești args[1] fără să verifici lungimea: dacă utilizatorul nu dă argumente, programul intră în panică (index out of bounds). Folosește args.get(1).
  • Rulezi cargo run Ana fără --: Cargo poate interpreta argumentele ca opțiuni proprii. Scrie cargo run -- Ana.
  • Uiți că primul argument este numele programului și numeri greșit argumentele.

Comenzi înrudite

  • env::var: Citește valoarea unei variabile de mediu (HOME, PATH, setări proprii); dă Err dacă nu există.
  • process::exit: Oprește imediat programul cu codul de ieșire dat (0 = succes, altceva = eroare), fără să mai ruleze restul codului.
  • Command: Pornește alt program (proces copil): new() alege programul, arg() și args() adaugă argumente.