You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'd like to help close this. What kinds of exercises would we like to see? With @calvinbrown085 's work we have reading from a file (files1). I could see adding something like:
Files: files2, writing/amending
Stdio: stdio1, capturing user input from stdin and writing it out to stdout
I'd be happy to commit to creating these exercises (as well as any others you folks suggest).
I think that we can have 3 small exercises about dealing with files:
Opening and reading a file. Maybe just count the number of lines? The solution should show both manually opening and reading the file and using fs::read_to_string.
Creating a file and writing to it. The file should be truncated if it already exists. The solution should show both manually opening and writing the file and using fs::write.
Appending to an existing (log) file. It should be created if it doesn't already exist. No truncation.
In all of these exercises, the user should complete the body of a function which takes a path as argument. Input files should be created in tests and the path is then passed to the user function.
In the last exercise with appending, we can teach about the Write trait by letting the user use the file with a function that expects something implementing Write. We can test that function with a buffer of bytes then to demonstrate the Write abstraction.
I think that an exercise about stdin would be too confusing because the user can't test it with some input in the terminal. Rustlings captures the whole output and shows it after the exercise terminates. We could write a test that calls the exercise and passes some input as stdin, but the user can't really test it in the terminal. So I will skip stdin.
stdout and stderr are easy with print(ln)! and eprint(ln)!. No need for an exercise for that. Using std::io::stdout and maybe locking manually is too advanced. Out of the scope of Rustlings.
I'm a little confused as to what is meant by manually opening/reading the files manually.
I wrote a little sample, please tell me if it meets expectations.
fnmain(){}#[cfg(test)]mod test {use fs;#[test]fncan_you_read_in_rust(){let content = fs::read("./ferris.txt").unwrap();// let _ = fs::???("./ferris.txt").unwrap();let expect:Vec<u8> = vec![102,101,114,114,105,115,10,];assert_eq!(expect, content)}#[test]fnread_a_string_directly(){// you might've noticed in the previous test, that the file// reads in a Vec<u8>, hey! that doesn't look like a string// No, no it doesn't, afterall evrything in a computer is bits// and bytes, but, Rust provides us with a convienient method// to read strings directlylet content = fs::read_to_string("./ferris.txt").unwrap();assert_eq!("ferris", content)}}
The alternative is to use the specialized, but less flexible functions from std::fs:
let content = fs::read_to_string("Cargo.toml")?;println!("{content}");
Some points:
I don't think that we need to teach how to read bytes. It is not that different from reading strings.
Always add a TODO: … where a user needs to do something.
Try to avoid syntax errors in the exercise. So no fs::???(). Instead, I prefer to write a comment describing what the user should do. In this case, something like "TODO: Use a function from std::fs to read the file ferris.txt".
Hey, @mo8it sorry school has been super busy lately, didn't get much free time.
fnmain(){}#[cfg(test)]mod test {use std::io::prelude::*;use std::fs::File;#[test]fncan_you_read_in_rust(){// the user enters the name of the file to open// the unwrap will be missing for the File::openletmut file = File::open("ferris.txt").unwrap();letmut content = String::new();// the user will fill in the read_to_string method
file.read_to_string(&mut content).unwrap();assert_eq!(content.len(),10);}#[test]fncan_you_write_in_rust(){let msg = "hello world!";// here the user will enter the path of the filelet path = "ferris.txt";// the user will fill the create methodletmut file = File::create(path).unwrap();// the unwrap will be missing here
file.write_all(msg.as_bytes()).unwrap();}#[test]fncan_you_append_in_rust(){todo!()}}
I did have a question, how would we verify that a file called ferris.txt would exist when testing read or how do we verify that the user created a file. The obvious thing is when the test start create the necessary file and in the assert check if the file exists for the writing test.
I was wondering if there were better, more elegant or more idiomatic ways to deal with this.
Activity
calvinbrown085 commentedon Sep 21, 2020
I can try and take files if that would be okay!
seeplusplus commentedon Nov 5, 2020
I'd like to help close this. What kinds of exercises would we like to see? With @calvinbrown085 's work we have reading from a file (files1). I could see adding something like:
I'd be happy to commit to creating these exercises (as well as any others you folks suggest).
calvinbrown085 commentedon Nov 15, 2020
IMO, writing a new file would be a good exercise, I also agree that your stdio ones would be good too!
samusz commentedon Feb 20, 2022
May be also these common use case :
mo8it commentedon Jul 10, 2024
I think that we can add a whole IO section with at least 2 exercises :)
Open to pull requests :D
frroossst commentedon Sep 3, 2024
I can try and work on a new io section if this is still wanted
mo8it commentedon Sep 3, 2024
@frroossst Go ahead!
I think that we can have 3 small exercises about dealing with files:
fs::read_to_string
.fs::write
.In all of these exercises, the user should complete the body of a function which takes a path as argument. Input files should be created in tests and the path is then passed to the user function.
In the last exercise with appending, we can teach about the
Write
trait by letting the user use the file with a function that expects something implementingWrite
. We can test that function with a buffer of bytes then to demonstrate theWrite
abstraction.I think that an exercise about
stdin
would be too confusing because the user can't test it with some input in the terminal. Rustlings captures the whole output and shows it after the exercise terminates. We could write a test that calls the exercise and passes some input asstdin
, but the user can't really test it in the terminal. So I will skipstdin
.stdout
andstderr
are easy withprint(ln)!
andeprint(ln)!
. No need for an exercise for that. Usingstd::io::stdout
and maybe locking manually is too advanced. Out of the scope of Rustlings.frroossst commentedon Sep 5, 2024
I'm a little confused as to what is meant by manually opening/reading the files manually.
I wrote a little sample, please tell me if it meets expectations.
mo8it commentedon Sep 16, 2024
@frroossst
With manually opening and then reading a file, I mean something like this:
The alternative is to use the specialized, but less flexible functions from
std::fs
:Some points:
TODO: …
where a user needs to do something.fs::???()
. Instead, I prefer to write a comment describing what the user should do. In this case, something like "TODO: Use a function fromstd::fs
to read the fileferris.txt
".frroossst commentedon Oct 13, 2024
Hey, @mo8it sorry school has been super busy lately, didn't get much free time.
I did have a question, how would we verify that a file called ferris.txt would exist when testing read or how do we verify that the user created a file. The obvious thing is when the test start create the necessary file and in the assert check if the file exists for the writing test.
I was wondering if there were better, more elegant or more idiomatic ways to deal with this.
3 remaining items