有没有办法在 Rust 中获取 C99 数组指示符或替代方案?

Sir*_*ir 6 c arrays mapping initialization rust

我刚刚完成了关于 C 和 Rust元音计数的 CodeWars kata。示例代码简单明了。数组可以用作快速映射。在这里,我将字符映射到逻辑值(0 或 1)。

C实现:

#include <stddef.h>
#include <stdint.h>

// :) This const array design looks smart & IMO-readable. Use of C99 feature.
const uint8_t areVowels[256]= {['a']=1, ['e']=1, ['i']=1, ['o']=1,  ['u']=1};

size_t get_count(const unsigned char *s)
{
  auto size_t count= 0;
  for (;*s!='\0';s++){
    count+= areVowels[*s];
  }
  return count;
}
Run Code Online (Sandbox Code Playgroud)

Rust 实现:

// :( Here is me pain. Unreadable, python3-generated array content.
const ARE_VOWELS:[u8;256]= [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];

fn get_count(s: &str) -> usize {
  let mut vowels_count: usize = 0;

  for c in s.bytes(){
      vowels_count+= ARE_VOWELS[c as usize] as usize;
  }
  
  return vowels_count;
}
Run Code Online (Sandbox Code Playgroud)

我希望我知道 Rust 中数组指示符的替代方案,这是一个有用的 C99 功能。在我的 Rust 代码中,相同字节数组的初始化要尴尬得多。

Ian*_* S. 10

static mut这里是不必要的(也是不好的做法)。您可以将常量的值分配给能够在上下文中计算的代码块的const

const ARE_VOWELS: [u8;256] = {
    let mut data = [0u8; 256];
    data['a' as usize] = 1;
    data['e' as usize] = 1;
    data['i' as usize] = 1;
    data['o' as usize] = 1;
    data['u' as usize] = 1;
    data
};
Run Code Online (Sandbox Code Playgroud)

请参阅此答案以使用宏来美化它。


kmd*_*eko 7

另一种选择是提供您想要的语法的宏,实际上制作通用实现并不难:

macro_rules! array {
    ($def:expr; $len:expr; $([$idx:expr]=$val:expr),* $(,)?) => { {
        let mut a = [$def; $len];
        $(a[$idx] = $val;)*
        a
    } }
}
Run Code Online (Sandbox Code Playgroud)
let data = array![0; 256; ['a' as usize]=1, ['e' as usize]=1];
Run Code Online (Sandbox Code Playgroud)

如果您愿意,当然可以将其移至as usize宏中。

  • 哦,嘿,看,有一个板条箱可以执行此操作以及更多操作:[array-lit](https://docs.rs/array-lit/latest/array_lit/) (2认同)

Sir*_*ir 0

我发现一些(不安全的 \xe2\x87\x92 有趣的)解决方案可以解决“mut static value running optimization”。

\n
const VOWELS:&[u8;5]= b"aeiou";\nstatic mut ARE_VOWELS:[u8;256]= [0;256];\n\nfn init(){\n    unsafe{\n        let ptr: *mut u8= &mut ARE_VOWELS[0];\n        for b in VOWELS{\n            *(ptr.offset(*b as isize))= 1;\n        }\n    }\n}\n\nfn get_count(s: &str) -> usize {\n    init();\n    \n    let mut vowels_count: usize = 0;\n\n    for c in s.bytes(){\n        unsafe{\n            vowels_count+= ARE_VOWELS[c as usize] as usize;\n        }\n    }\n  \n    return vowels_count;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

尽管我对这段代码的性能和可维护性抱有严重怀疑。

\n