Text 如何使用格式!无标准环境中的宏?

Text 如何使用格式!无标准环境中的宏?,text,macros,formatting,rust,embedded,Text,Macros,Formatting,Rust,Embedded,我如何在不使用std的情况下实现以下示例 let text = format!("example {:.1} test {:x} words {}", num1, num2, num3); text具有类型&str和num1,num2和num3具有任何数字类型 我曾尝试使用numtoa和itoa/dtoa显示数字,但numtoa不支持浮点数,itoa不支持no\u std。我觉得在一个字符串中显示一个数字是很常见的,而且我可能遗漏了一些明显的东西。一般来说,你不会格式分配字符串,而no_std

我如何在不使用std的情况下实现以下示例

let text = format!("example {:.1} test {:x} words {}", num1, num2, num3);
text
具有类型
&str
num1
num2
num3
具有任何数字类型

我曾尝试使用
numtoa
itoa/dtoa
显示数字,但
numtoa
不支持浮点数,
itoa
不支持
no\u std
。我觉得在一个字符串中显示一个数字是很常见的,而且我可能遗漏了一些明显的东西。

一般来说,你不会<代码>格式分配
字符串
,而
no_std
环境没有分配器

如果您确实有分配器,则可以使用。此板条箱包含宏

另见:

除此之外,您还可以在不使用分配器的情况下格式化字符串

在这种情况下,您只需实现
write_str
,然后就可以免费获得
write_fmt

使用(与相同的语法)可以准备一个值,该值可以传递给

见:

#![板条箱类型=“dylib”]
#![无标准]
发布mod write_到{
使用core::cmp::min;
使用core::fmt;
pub结构WriteTo{
pub fn new(缓冲区:&'a mut[u8])->Self{
写入{缓冲区,已使用:0}
}

pub fn as_str(self)->Option fmt::Write for WriteTo(buffer:&'a mut[u8],args:fmt::Arguments)->Result您还可以组合使用
numtoa
arrayvec
板条箱。示例:

#![no_std]

use numtoa::NumToA;
use arrayvec::ArrayString;

fn main() -> ! {
    let mut num_buffer = [0u8; 20];
    let mut text = ArrayString::<[_; 100]>::new();

    let num1 = 123;
    let num2 = 456;
    let num3 = 789;

    // text.clear(); (on subsequent usages)
    text.push_str("example ");
    text.push_str(num1.numtoa_str(10, &mut num_buffer));

    text.push_str(" test ");
    text.push_str(num2.numtoa_str(10, &mut num_buffer));

    text.push_str(" words ");
    text.push_str(num3.numtoa_str(10, &mut num_buffer));
}
写一个格式化程序

使用core::fmt::{self,Write};
使用core::str;
fn main(){
//对于LCD 160/8=20个字符
设mut buf=[0u8;20];
让mut buf=ByteMutWriter::new(&mut buf[…]);
buf.clear();
写!(&mutbuf,“Hello{}!”,“Rust”).unwrap();
//buf.as_str()
}
pub结构ByteMutWriter{
新发布(buf:&a mut[u8])->Self{
ByteMutWriter{buf,游标:0}
}
发布fn as_str(&self)->&str{
str::from_utf8(&self.buf[0..self.cursor]).unwrap()
}
#[内联]
发布fn容量(和自身)->使用{
self.buf.len()
}
发布fn清除(&M自我){
self.cursor=0;
}
pub fn len(&self)->使用{
自动光标
}
pub fn empty(&self)->bool{
self.cursor==0
}
pub fn full(&self)->bool{
self.capacity()==self.cursor
}
}

impl fmt::为ByteMutWriterI编写我的目标是STM32F103,japaric会工作吗?我有更安全的选择吗?非常感谢!@FerdiaMcKeogh我不知道你说的“更安全”是什么意思在这种情况下,但这似乎是一个合理的选择。对不起,我的意思是用一种稳定/广泛接受的方法更安全。
alloc-cortex-m
工作得很好!谢谢!为什么不
let mut w=write_=WriteTo::WriteTo::new(&mut buf);write!(&mut w,“caf”)。unwrap();
?@Shepmaster您将需要另一个步骤来提取结果,可能还需要
使用core::fmt::Write;
(范围内需要
Write_fmt
方法)…但是,是的,您也可以这样使用。可能需要
格式化_buf!(&mut buf,“…”,…)
macro将是一种更舒适的方式,但我认为这项练习可以留给读者:)
#![crate_type = "dylib"]
#![no_std]

pub mod write_to {
    use core::cmp::min;
    use core::fmt;

    pub struct WriteTo<'a> {
        buffer: &'a mut [u8],
        // on write error (i.e. not enough space in buffer) this grows beyond
        // `buffer.len()`.
        used: usize,
    }

    impl<'a> WriteTo<'a> {
        pub fn new(buffer: &'a mut [u8]) -> Self {
            WriteTo { buffer, used: 0 }
        }

        pub fn as_str(self) -> Option<&'a str> {
            if self.used <= self.buffer.len() {
                // only successful concats of str - must be a valid str.
                use core::str::from_utf8_unchecked;
                Some(unsafe { from_utf8_unchecked(&self.buffer[..self.used]) })
            } else {
                None
            }
        }
    }

    impl<'a> fmt::Write for WriteTo<'a> {
        fn write_str(&mut self, s: &str) -> fmt::Result {
            if self.used > self.buffer.len() {
                return Err(fmt::Error);
            }
            let remaining_buf = &mut self.buffer[self.used..];
            let raw_s = s.as_bytes();
            let write_num = min(raw_s.len(), remaining_buf.len());
            remaining_buf[..write_num].copy_from_slice(&raw_s[..write_num]);
            self.used += raw_s.len();
            if write_num < raw_s.len() {
                Err(fmt::Error)
            } else {
                Ok(())
            }
        }
    }

    pub fn show<'a>(buffer: &'a mut [u8], args: fmt::Arguments) -> Result<&'a str, fmt::Error> {
        let mut w = WriteTo::new(buffer);
        fmt::write(&mut w, args)?;
        w.as_str().ok_or(fmt::Error)
    }
}

pub fn test() {
    let mut buf = [0u8; 64];
    let _s: &str = write_to::show(
        &mut buf,
        format_args!("write some stuff {:?}: {}", "foo", 42),
    ).unwrap();
}
#![no_std]

use numtoa::NumToA;
use arrayvec::ArrayString;

fn main() -> ! {
    let mut num_buffer = [0u8; 20];
    let mut text = ArrayString::<[_; 100]>::new();

    let num1 = 123;
    let num2 = 456;
    let num3 = 789;

    // text.clear(); (on subsequent usages)
    text.push_str("example ");
    text.push_str(num1.numtoa_str(10, &mut num_buffer));

    text.push_str(" test ");
    text.push_str(num2.numtoa_str(10, &mut num_buffer));

    text.push_str(" words ");
    text.push_str(num3.numtoa_str(10, &mut num_buffer));
}
 [dependencies]
 arrayvec = { version = "0.5", default-features = false }
 numtoa = "0.2"