【发布时间】:2015-10-13 09:14:54
【问题描述】:
在 C/C++ 标准库中是否有与 system 函数等效的 Rust?具体来说,我正在尝试使用cls 来清除命令行。
【问题讨论】:
标签: rust
在 C/C++ 标准库中是否有与 system 函数等效的 Rust?具体来说,我正在尝试使用cls 来清除命令行。
【问题讨论】:
标签: rust
上述方法对我不起作用
以下方法在windows cmd中有效
Cargo.toml
[dependencies]
winapi = "0.2.8"
kernel32-sys = "0.2.1"
代码
extern crate kernel32;
extern crate winapi;
use winapi::HANDLE;
use winapi::wincon::CONSOLE_SCREEN_BUFFER_INFO;
use winapi::wincon::COORD;
use winapi::wincon::SMALL_RECT;
use winapi::WORD;
use winapi::DWORD;
static mut CONSOLE_HANDLE: Option<HANDLE> = None;
fn get_output_handle() -> HANDLE {
unsafe {
if let Some(handle) = CONSOLE_HANDLE {
return handle;
} else {
let handle = kernel32::GetStdHandle(winapi::STD_OUTPUT_HANDLE);
CONSOLE_HANDLE = Some(handle);
return handle;
}
}
}
fn get_buffer_info() -> winapi::CONSOLE_SCREEN_BUFFER_INFO {
let handle = get_output_handle();
if handle == winapi::INVALID_HANDLE_VALUE {
panic!("NoConsole")
}
let mut buffer = CONSOLE_SCREEN_BUFFER_INFO {
dwSize: COORD { X: 0, Y: 0 },
dwCursorPosition: COORD { X: 0, Y: 0 },
wAttributes: 0 as WORD,
srWindow: SMALL_RECT {
Left: 0,
Top: 0,
Right: 0,
Bottom: 0,
},
dwMaximumWindowSize: COORD { X: 0, Y: 0 },
};
unsafe {
kernel32::GetConsoleScreenBufferInfo(handle, &mut buffer);
}
buffer
}
fn clear() {
let handle = get_output_handle();
if handle == winapi::INVALID_HANDLE_VALUE {
panic!("NoConsole")
}
let screen_buffer = get_buffer_info();
let console_size: DWORD = screen_buffer.dwSize.X as u32 * screen_buffer.dwSize.Y as u32;
let coord_screen = COORD { X: 0, Y: 0 };
let mut amount_chart_written: DWORD = 0;
unsafe {
kernel32::FillConsoleOutputCharacterW(
handle,
32 as winapi::WCHAR,
console_size,
coord_screen,
&mut amount_chart_written,
);
}
set_cursor_possition(0, 0);
}
fn set_cursor_possition(y: i16, x: i16) {
let handle = get_output_handle();
if handle == winapi::INVALID_HANDLE_VALUE {
panic!("NoConsole")
}
unsafe {
kernel32::SetConsoleCursorPosition(handle, COORD { X: x, Y: y });
}
}
示例
fn main() {
loop {
let mut input = String::new();
std::io::stdin()
.read_line(&mut input)
.expect("Failed to read line");
println!("You typed: {}", input);
if input.trim() == "clear" {
clear();
}
}
}
【讨论】:
let coord_screen = COORD { X: 0, Y: 0 }; 之后执行类似for _ in 0..screen_buffer.dwSize.Y { println!(""); } 的操作。为什么?因为这个发布的方法并不总是清除所有内容,但如果你输出换行符,它肯定会清除所有内容。我有特殊的颜色块没有被这种方法清除,虽然 ascii 文本是
您可以通过libc crate 使用C's system function。但幸运的是有一个更好的方法:std::process::Command。
调用cls 的一种快速而肮脏的方式是
if std::process::Command::new("cls").status().unwrap().success() {
println!("screen successfully cleared");
}
【讨论】:
cls 仅存在于 Windows 上。在 *nix 中,命令是 clear。通常,不建议为此使用系统命令。这需要做很多工作:查找命令、启动进程、绑定标准输出等。在这种情况下,我会尽量坚持使用 libc。
Result 类型来保证你检查它是否有效。即使你只是简单地将程序带到 linux 上,至少你会得到一个很好的失败。如果你想要一个在所有系统上运行的单线,你可以开始链接命令:assert!(Command::new("cls").status().or_else(|_| Command::new("clear")).unwrap().success())
oli_obk,实际上我认为这是正确的 - 它适用于我在 Linux 上的 Rust:
assert!( std::process::Command::new("cls").status().or_else(|_| std::process::Command::new("clear").status()).unwrap().success() );
status() 必须使用两次。
(将上面的代码行放在 main 之类的函数中。)
【讨论】: