I'm trying to figure out how to write a string to a file. The following gives me the error format argument must be a string literal:
use std::fs::File;
use std::io::{Error, Write};
fn main() -> Result<(), Error> {
let path = "results.txt";
let mut output = File::create(path)?;
let line = println!("{}", "hello");
write!(output, line);
}
How can I write to a file from a string variable? If I change the follow line it works, but I can't figure out how to write to a file if the string is in a variable.
write!(output, "foo,bar,baz");
write! is a macro, similar to print!. It expects 2 or more arguments, the first being a writer, the second a format string (which must be a string literal) and after that zero or more expressions which will be placed into the placeholders in the format string.
So, you could combine both your last two lines like this:
fn main() -> std::io::Result<()> {
let path = "results.txt";
let mut output = File::create(path)?;
let line = "hello";
write!(output, "{}", line)
}
Other methods to write to a Writer include calling std::io::Write::write_all, or to write a slice into a file directly you can use std::fs::write.
Another thing to note: the print! macro does not return the output in a string, it prints the output to stdout. If you want to get the formatted result in a string, use the format! macro:
let my_string = format!("Hello {}", "world");
Related
Now that I'm typing it, this seems like a very convoluted process that could definitely be solved easier. Ignoring that for the moment, I'm trying to take a string (from user input), separate the characters into an array, then call individual characters to make a new string. The issue I'm running into is that the "join" function doesn't like working with the "Vec" function (not sure if function is the right term, sorry). Here is my code so far:
use std::io;
fn main() {
println!("Enter P1:");
let mut mono = String::new();
io::stdin()
.read_line(&mut mono)
.expect("Failed to read line");
let mono: Vec<char> = mono.chars().collect();
let x = [mono[0],mono[1]].join("");
println!("Square 1: {x}");
}
I'm very new to Rust, so any suggestions are extremely helpful. Thank you!
You could always just slice the original string str[a..b].to_string().
If you need to work with char arrays, there's String::from_iter and collecting into a String. Example:
fn main() {
let string = "My String".to_string();
let substr1 = string[0..3].to_string();
let substr2 = string[3..].to_string();
println!("substr1 = {}", substr1);
println!("substr2 = {}", substr2);
let chars: Vec<_> = string.chars().collect();
let collected_substr1: String = chars.iter().take(2).collect();
let collected_substr2: String = chars.iter().skip(3).collect();
println!("collected_substr1 = {}", collected_substr1);
println!("collected_substr2 = {}", collected_substr2);
let from_iter_substr1 = String::from_iter([chars[0], chars[1]].iter());
let from_iter_substr2 = String::from_iter(chars.iter().skip(3));
println!("from_iter_substr1 = {}", from_iter_substr1);
println!("from_iter_substr2 = {}", from_iter_substr2);
}
Vec is a type, FYI.
join only works on string slices (&str), not chars. Assuming you are just trying to join two characters without a separator, you can do
let x: String = mono.chars().take(2).collect();
If the goal is only to extract a substring from the input it can be done much simpler
use std::io;
fn main() {
println!("Enter P1:");
let mut mono = String::new();
io::stdin()
.read_line(&mut mono)
.expect("Failed to read line");
let x = &mono[..2].to_string(); // get rhe slice you need and create a new string from it
println!("Square 1: {x}");
}
Edit
As pointed out in comments, note that in a real life use case you should check the length of your string before slicing in it with arbitrary indexes... this example could easily crash at runtime.
I tried find(), but it returns the position of the first character
This is my code
File: Main.rs
use std::fs;
fn main() {
let mut data = fs::read_to_string("./Text").expect("Unable to read file");
let g_index = data.find("g"); // 3
println!("{:?}",g_index)
}
File: Text (https://ars.els-cdn.com/content/image/1-s2.0-S0960982203005347-mmc6.txt)
You can get an iterator over the characters of a string via chars(), then use standard iterator methods filter() and count():
s.chars().filter(|&c| c == 'g').count();
So I have a code which constantly asks for input and then executes your input as a shell command. I understand that the output I am getting from the shell commands is in a buffer of some sort. Now, however, as there are many commands which output lots of lines, I would like to get all of the output into one single string.
extern crate subprocess;
use std::io;
use std::io::{BufRead, BufReader};
use subprocess::Exec;
fn main() {
loop {
let mut mycommand_string: String = String::new();
io::stdin()
.read_line(&mut mycommand_string)
.expect("Failed to read line");
let mycommand: &str = &*mycommand_string;
let x = Exec::shell(mycommand).stream_stdout().unwrap();
let br = BufReader::new(x);
let full: String = " ".to_string();
let string = for (i, line) in br.lines().enumerate() {
let string: String = line.unwrap().to_string();
let full = format!("{}{}", full, string);
println!("{}", full);
};
println!("{}", string);
}
}
This is my code. As you can see, the thing I am aiming for is to somehow iterate over br.lines() and for each line of output it contains, append or concatenate it to a string, so that all the output ends up in one single string, preferably with "\n" in between each line, but not neccesarilly.
Specifically I would like to iterate over the result of the variable br which has a type I dont understand and to concatenate all the strings together.
If you have an iterator of lines, then you can simply collect that into a string:
br.lines().collect();
Of course we should not ignore that there do not seem to be many possible reasons for ever doing that...
I'm trying to figure out how to write a string to a file. The following gives me the error format argument must be a string literal:
use std::fs::File;
use std::io::{Error, Write};
fn main() -> Result<(), Error> {
let path = "results.txt";
let mut output = File::create(path)?;
let line = println!("{}", "hello");
write!(output, line);
}
How can I write to a file from a string variable? If I change the follow line it works, but I can't figure out how to write to a file if the string is in a variable.
write!(output, "foo,bar,baz");
write! is a macro, similar to print!. It expects 2 or more arguments, the first being a writer, the second a format string (which must be a string literal) and after that zero or more expressions which will be placed into the placeholders in the format string.
So, you could combine both your last two lines like this:
fn main() -> std::io::Result<()> {
let path = "results.txt";
let mut output = File::create(path)?;
let line = "hello";
write!(output, "{}", line)
}
Other methods to write to a Writer include calling std::io::Write::write_all, or to write a slice into a file directly you can use std::fs::write.
Another thing to note: the print! macro does not return the output in a string, it prints the output to stdout. If you want to get the formatted result in a string, use the format! macro:
let my_string = format!("Hello {}", "world");
I know that I can read one line and convert it to number in one line, i.e.
let lines: u32 = io::stdin().read_line().ok().unwrap().trim().parse().unwrap();
How to do the same without parse and in one line? Right now I do this:
let line_u = io::stdin().read_line().ok().unwrap();
let line_t = line_u.as_slice().trim();
Edit: Explanation what's going on here:
pub fn stdin() -> StdinReader
fn read_line(&mut self) -> IoResult<String> // method of StdinReader
type IoResult<T> = Result<T, IoError>;
fn ok(self) -> Option<T> // method of Result
fn unwrap(self) -> T // method of Option
fn trim(&self) -> &str // method of str from trait StrExt
fn to_string(?) -> String // I don't know where is this located in documentation
We can use trim on String, because String is a str decoreated with pointer, an owned string.
parse(),
stdin(),
read_line(),
IoResult,
ok(),
unwrap(),
trim(),
str
trim() returns an &str view of the String returned by unwrap(). You can't store this object because the owning String will no longer exist at the end of the statement. So just use to_string() to convert the &str back to a String.
let line = io::stdin().read_line().ok().unwrap().trim().to_string();