First Program
1. Git fork....
Go to here and fork the follow repo :
Working together we play with the initial code.
2. Rust Lab: Mocking Text Input
2.1 Importing Modules
Modify src/main.rs
by importing the following modules at the top of script:
std::io
: Provides tools for input/output operations, such as reading user input.std::env
: Gives access to environment variables and command-line arguments.::
: operator is used to access an item inside a module
2.2 Main Function
Continue into the main
block, removing the println!
macro.
main
: Entry point of the program.input
: A mutableString
variable to store user or argument input.mock
: A mutableString
to build the "mocked" output.
2.3 Getting Command-Line Arguments
Now on a new line after the above variables, add a Vec
with type String
, that collects the the arguments passed to the program via the command line
- Collects command-line arguments into a
Vec<String>
. args[0]
is always the name of the program, so we check for additional arguments.
2.4 Handling Input
Now that there is functionality to collect the arguments to the program into a vector of strings. We want to create functionality to read the arguments directly when the program is invoked via the CLI, or if not present then request input from the user.
#![allow(unused)] fn main() { input = match args.get(1) { Some(value) => value.to_string(), None => { println!("What would you like to mock?"); io::stdin().read_line(&mut input) .expect("fAiLeD tO rEaD LiNe"); input }, }; }
- If argument exists: Assign it to
input
. - If argument doesn't exist: Prompt the user for input and read it from standard input.
expect
: Halts the program with a custom error message if reading input fails.match
is a powerful pattern matching construct in Rust. It allows you tomatch
a value against different patterns and execute corresponding code blocks based on which pattern matches. It's similar to a switch statement in other languages but more flexible.Some(value)
is a variant of theOption
enum
in Rust, which represents the presence of a value. In this case, ifargs.get(1)
returnsSome(value)
, it means a command-line argument was passedNone
is another variant of theOption
enum
, representing the absence of a value. If no command-line argument was passed (i.e.,args.get(1)
returnsNone
), the code inside theNone
branch will be executed. In this case, it will ask the user for input.expect()
is a method onResult
that either returns theOk
value orpanics
with the provided message if it encounters anErr
variant. This method is used here to ensure that if reading from stdin fails (for example, due to an I/O error), the program will panic with the message"fAiLeD tO rEaD LiNe"
. This is a somewhat humorous or exaggerated way of indicating an error
2.5 Normalizing Input
To normalize the the inputted string, we can set the string to all lowercase.
trim
: Removes leading and trailing whitespace.to_ascii_lowercase
: Converts the string to lowercase.
2.6 Setting Up State Variable
To keep track of the the type of letter case we are using at anyone time we have a boolean
2.7 Transforming Input
Underneath the code above add the functionality to loop over every letter in the vector input
and change it to upper or keep as lower case. We need to check if the index value of the string input
is of type alpha, rather than numeric in order to convert the value to upper case too.
#![allow(unused)] fn main() { for c in input.chars() { if c.is_alphabetic() & is_uppercase { mock.push(c.to_uppercase().collect::<Vec<_>>()[0]); is_uppercase = false; } else { mock.push(c); if c.is_alphabetic() { is_uppercase = true; } } } }
- Loop through each character (
c
) ininput
:- If
c
is alphabetic andis_uppercase
istrue
:- Convert to uppercase and append to
mock
. - Reset
is_uppercase
tofalse
.
- Convert to uppercase and append to
- Otherwise, append
c
as-is and toggleis_uppercase
if it's alphabetic.
- If
- Purpose: Alternate between uppercase and lowercase letters for alphabetic characters.
2.8 Output the Result
Once all conversions have happened the program should return the output to the user via standard out.
- Print the transformed
mock
string. println!
is a macro used to print text to the console.
3. Compile
To compile the code:
4. Example Execution
4.1 Case 1: With Argument
4.2 Case 2: Without Argument
5.Concepts Covered
- Command-line arguments.
- Reading user input.
- String manipulation.
- Control flow with
match
andfor
loops. - Rust's ownership and mutability rules.
Full Code
Full Code
use std::io; use std::env; fn main() { let mut input = String::new(); let mut mock = String::new(); let args: Vec<String> = env::args().collect(); input = match args.get(1) { Some(value) => value.to_string(), None => { println!("What would you like to mock?"); io::stdin().read_line(&mut input) .expect("fAiLeD tO rEaD LiNe"); input }, }; let input = input.trim().to_ascii_lowercase(); let mut is_uppercase = false; for c in input.chars() { if c.is_alphabetic() & is_uppercase { mock.push(c.to_uppercase().collect::<Vec<_>>()[0]); is_uppercase = false; } else { mock.push(c); if c.is_alphabetic() { is_uppercase = true; } } } println!("{}", mock) }
-
Modify the code to toggle letters only for vowels.
-
Change the code to handle multiple command-line arguments.
-
You can explore further concepts via rust doc: