ぬの部屋(仮)
nu-no-he-ya
  •   12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728     
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28      
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
    1234567
    891011121314
    15161718192021
    22232425262728
           
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
         12
    3456789
    10111213141516
    17181920212223
    242526272829 
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
        123
    45678910
    11121314151617
    18192021222324
    25262728   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    15161718192021
    293031    
           
         12
    3456789
    10111213141516
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728     
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
          1
    2345678
    9101112131415
    16171819202122
    232425262728 
           
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
  • Rustやってみる(9)関数でGenericsを使ってみる

    1.自分で実装する場合

    まず以下のように定義する。

    struct IntValue      … TraitMyDisp と TraitMyPow 実装

    struct FloatValue  … TraitMyPow のみ実装

    // これをimplementしているときは表示できる
    trait TraitMyDisp{
      fn disp(&self);
    }
    
    // これをimplementしているときは値を二乗する
    trait TraitMyPow{
      fn get_pow2(&self)->f32;
    }
    
    //////////////////////////////////////////
    //////////////////////////////////////////
    
    struct IntValue{ value: i32 }
    
    impl TraitMyDisp for IntValue{
      fn disp(&self){
        println!("{}",self.value);
      }
    }
    impl TraitMyPow for IntValue{
      fn get_pow2(&self)->f32{
        ( self.value*self.value ) as f32
      }
    }
    //////////////////////////////////////////
    //////////////////////////////////////////
    
    struct FloatValue{ value:f32 }
    
    impl TraitMyPow for FloatValue{
      fn get_pow2(&self)->f32{
        ( self.value*self.value ) as f32
      }
    }
    

    例1

    失敗例1

    まず、以下のようにただ<T>を渡してもコンパイルは通らない。

    // C++だと T に get_pos2があればビルドが通るが
    // Rustでは valueに対して何をできるのかを指定しなければならない
    fn call<T>(value:T){
      println!("call {}",value.get_pow2()); // NG   T にget_pow2が必要なんて聞いてない 
    }
    

    fn main(){ // TraitMyDisp , TraitMyPow の両方が実装済み let i_val = IntValue{value:2}; // TraitMyPow のみが実装済み let f_val = FloatValue{value:2.0}; call(i_val); }

    修正1

    「型Tを取る」ではなく、「get_pow2()を持つ型Tを取る」と記述しなければいけない。

    // T は TraitMyPow を実装していなければならない
    fn call< T : TraitMyPow >(value:T){
      println!("call {}",value.get_pow2());
    }
    

    例2

    トレイトは + で複数指定できる。

    T は+で指定されたすべてのトレイトに対応していなければならない。

    たとえその関数の中で使っていなくても、実装だけはしていなければならない。

    // <T:トレイト + トレイト> のように+で複数指定できる 
    fn call_both<T:TraitMyPow + TraitMyDisp>(value:&T){
    
      // TraitMyDisp::dispは使っていないが、トレイト境界を指定しているので
      // Tがdispに対応していないならコンパイルできない(たとえ使っていなくても)
      println!("call {}",value.get_pow2());
    }
    
    
    fn main(){
    
      // TraitMyDisp , TraitMyPow の両方が実装済み
      let i_val = IntValue{value:2};
    
      // TraitMyPow のみが実装済み
      let f_val = FloatValue{value:2.0};
    
      call_both(&i_val); // OK
      // call_both(&f_val); // NG FloatValueのためのTraitMyDispはimplしていない
    
    }
    

    2.operatorを使用可能にする

    Tに渡される型が + 演算できるかどうかはわからない。

    したがって、例え自分がプリミティブな数値型しか与えるつもりがなくても、コンパイラはそんなことは知らないので「TはAddが可能である」ことを教えなければいけない。

    // Addモジュールを使う
    use std::ops::Add;
    
    /////////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////
    
    
    // add関数の定義
    // Tの必須の振る舞いとしてAddを指定。これで operator + が使える
    fn add< T : Add<Output=T> >( v1:T , v2:T ) -> T
    {
      
    v1 + v2
    
    }
    fn main(){
    
      let val:i32 = add( 3,4);
    
    }
    

    Rustやってみる(8) traitでポリモーフィズムを書いてみる

    Rustには継承はないがポリモーフィズムはある。C++やJavaのようなオブジェクト指向ではポリモーフィズムの実現のために継承があるようなイメージがあるので、この関係が奇妙に見える。

    継承とは「鷹も燕も”鳥”の特性をすべて持ち、その他に若干の差異がある同種のモノである」という考え方をする。だからどうしても子クラスが肥大化していく。そのあたりを嫌った結果らしい。

    // 振る舞い
    trait Flying{
      fn fly(&self);
    }
    

    // 構造体 鷹
    struct Hawk{
      weight:f32,
      speed:f32,
    }
    
    // トレイトのR実装
    impl Flying for Hawk{
    
      // メソッド 
      fn fly(&self){
        println!("鷹が飛ぶ {} km/h \n",self.speed );
      }
    
    }
    

    // 構造体 ハチドリ
    struct Hummingbird{
      weight:f32,
      speed:f32,
    }
    
    // トレイトのR実装
    impl Flying for Hummingbird{
      // メソッド 
      fn fly(&self){
        println!("ハチドリが飛ぶ {} km/h\n", self.speed);
      }
    }
    

    fn main() {
      
      // スタック上に確保する固定長配列は [T;N]の形をしている
      // T ... Type , N ... 個数
      let ary:[ Box<dyn Flying> ; 2 ] =
      [
        // Boxはヒープにメモリを確保する。
        Box::new(Hawk{weight:1100.0,speed:190.0}), // アカオノスリ
        Box::new(Hummingbird{weight:20.0,speed:98.0}) // ハチドリ
      ];
    
      ary[0].fly();
      ary[1].fly();
    
    }
    

    C++の継承が「Birdの特性を持った鷹を実装」という形であるのに対し、

    Rustのtraitは「Flyという振る舞いを、鷹や燕の特性に付与する」というような発想をすると、現時点ではとらえている(下図、現時点の解釈

    C++のオブジェクト指向だと飛べないはずのペンギンもflyを持たざるを得ないが、Rustのtraitであればペンギンにはflyを付与しなければよいだけの話だということになる。

    Rustやってみる(7) 配列を使ってみる

    配列にはいくつか種類があるらしい。

    ・[T;N] … スタック上に固定長配列

    ・Vec<T> ヒープ上の可変長配列

    ・Box<[T;N]>ヒープ上に固定長配列

    注意点として、基本的に配列の要素は全て初期化しなければならない。可変長配列でcapacityを指定できるVecはともかく、それ以外をメモリ確保だけして初期化したくない場合には、std::mem::MaybeUninitを使わなければならない。これはunsafeで囲まなければならない。

    fn main() {
    
      ////////////////////////////////////////////
      // 固定長配列(スタック)
    
      let mut ary1:[i32;5]=[1,2,3,4,5];
    
      for a1 in ary1{
        print!("{} ",a1);
      }
      println!("");

      // 初期化しないバージョン
      let mut ary2:[i32;5]  = unsafe { std::mem::MaybeUninit::uninit().assume_init() };
      for a2 in ary2{
        println!("* {} ",a2);
      }
      println!("\n");
    

    //////////////////////////////////////////// // 可変長配列
      let mut vec1:Vec<&str> = vec!["a", "b", "c"];
      vec1.push("d");
      for v1 in vec1{
        print!("{} ",v1);
      }
      println!("");

      // 初期化しないバージョン
      let mut vec2:Vec<&str> = vec![];
      vec2.push("d");
      for v2 in vec2{
        print!("* {} ",v2);
      }
      println!("\n");

      ////////////////////////////////////////////
      // 固定長配列(ヒープ)
    
      let mut box1:Box<[f32;5]> = Box::new([10.5 , 11.5 , 12.5 , 13.5 , 14.5]);
      for b1 in box1.iter(){
        print!("{} ",b1);
      }
      println!("");

      // 初期化しないバージョン
      let mut box2:Box<[f32;5]> = Box::new(unsafe { std::mem::MaybeUninit::uninit().assume_init() } );
      for b2 in box2.iter(){
        println!("* {} ",b2);
      }
    }
    

    実行例

    初期化しなければ不正な値が入っていることを確認できた。

     

    1 2 3 4 5
    * 112
    * 0
    * -580595040
    * 367
    * -580614544


    a b c d
    * d

    10.5 11.5 12.5 13.5 14.5
    * 2
    * 0
    * -1030514000000000000
    * 0.000000000000000000000000000000000000000000514
    * 0.000000000000000000000000000000000000000000006

     

    Rustやってみる(6)struct , impl , trait

    構造体関連で、struct,impl,trait の役割は以下(だと考えられる)

    • struct … 構造体を定義
    • impl … メソッドを定義
    • trait … structのメソッドに制約をつける

    本当はポリモーフィズムをやりたかったがどうしても理解が追い付かなかったので省略。

    構造体の定義とインスタンス生成

    // #[derive(Debug)] をつけるとprintln!でそのまま表示できるようになる
    #[derive(Debug)]
    // 構造体の定義。
    struct Rectangle{
      width:i32,
      height:i32,
    }
    
          
    fn main() {
      
      // 初期化なしでは定義できない
      //let mut rr = Rectangle{};  
      let mut rr = Rectangle{width:0,height:0};
    
      // mut をつけているので代入できる
      rr.width = 20;
      rr.height = 20;
    
      // #[derive(Debug)] をつけているので {:?} で表示できる
      println!("{:?}",rr);
    
    }
    

    構造体にメソッドを定義

    // 構造体の定義
    struct Rectangle{
      width:i32,
      height:i32,
    }
    
    // implの中でメソッドや関連関数を定義 impl Rectangle{ // Rectangleのメソッドを定義 メソッドはselfをとる。 selfがないなら関連関数 fn area(&self)->i32{ return self.width * self.height; } }
    fn main() {
      
      // インスタンス生成
      let mut rr = Rectangle{width:0,height:0};
    
      rr.width = 20;
      rr.height = 20;
    
      // メソッド呼び出し 
      println!("{}",rr.area() );
    
    }
    

    構造体に関連関数を定義

    implの中に&selfをとらない関数を定義すると関連関数になる。

    新規インスタンスを作成する関連関数を定義する場合、名前をnewにするのが一般的らしい。

    呼び出しは 構造体名::関連関数名() となる。

    // 構造体の定義
    struct Rectangle{
      width:i32,
      height:i32,
    }
    
    impl Rectangle{
    
      // 関連関数。 &selfをとらない。
      // Rectangle::new で呼び出す。
      // 新規インスタンス生成関連関数は「new」にする習慣がある
      fn new()->Rectangle{
    
        return Rectangle{width:20,height:30};
    
      }
    
      // メソッド
      fn area(&self)->i32{return self.width * self.height;}
    
    }
    

    fn main() {
      
      // 関連関数でインスタンス生成
      let mut rr = Rectangle::new();
    
      println!("{}",rr.area() );
    
    }
    

    traitで振る舞いを定義

    implをbehavior_calc_areaの実装とすることで、areaメソッドの実装を強制することができる。

    // 振舞いの定義
    trait behavior_calc_area{
      fn area(&self)->f32;
    }
    

    // 構造体の定義
    struct Rectangle{
      width:i32,
      height:i32,
    }
    
    // トレイトのR実装
    impl behavior_calc_area for Rectangle{
    
      // メソッド 
      fn area(&self)->f32{
        return (self.width * self.height) as f32;
      }
    
    }
    

    struct Triangle{
      width:i32,
      height:i32,
    }
    
    // トレイトのR実装
    impl behavior_calc_area for Triangle{
      // メソッド 
      fn area(&self)->f32{
        return (self.width * self.height) as f32 / 2.0 ;
      }
    }
    
    fn main() {
      
      // インスタンス生成
      let t:Triangle = Triangle{width:10,height:5};
      let r:Rectangle = Rectangle{width:10,height:5};
    
      println!("{}\n",t.area() );
      println!("{}\n",r.area() );
    
    }
    

    Rustやってみる(5)関数を定義・呼び出し

    基本はそんなに複雑ではないのだが、呼び出すときに暗黙型変換してくれないらしく、明示的型変換(as f32) を入れないといけないらしい。

    // 関数定義
    // 値渡し
    fn add(a:f32,b:f32)->f32{
      return a+b;
    }
    
    fn main()  {
    
      // 関数呼び出し
      // 引数に整数を入れてもaddのf32に暗黙変換できないらしいので
      // as f32 で実数に型変換する
      let k = add(3 as f32,5 as f32);
    
      println!("k= {}",k);
    
    }
    

    不変参照で渡すときは渡す側と受ける側で&をつける。

    // デフォルトで不変参照。C++でいうところのconst。kの内容を変更できない
    fn add2(k: &i32)->f64{
    
      // &mutでないときは *k としなくていいらしい
      return (k + 2) as f64;
    }
    

    fn main() { let a:i32=3; // mutがついていないので変更不可 println!(" {}", add2(&a) ); // aの定義時にmutをつけていないのでここもただの& }

    可変参照は型名の前に&mut をつける。

    呼び出す側でも&mutが必要。

    さらにこの値を使うときは参照外しとして*をつけなければならない。もっとほかの記号はなかったのか。

    // &mut で可変参照
    fn swap(i:&mut i32,j:&mut i32){
      let k:i32;
    
      // &mutの時は頭に*をつけて *i とする
      k = *i;
      *i = *j;
      *j = k;
    }
    
    fn main() {
      let mut a:i32=3;
      let mut b:i32=8;
      swap(&mut a,&mut b);
      println!("{} {}",a,b);
    }
    

    genericsをやりたいが。

    C++のテンプレートのようなgenericsという機能があるが、ただ<T>としただけでは動かない。printlnすらできない。いずれ詳しく調べる。

    https://www.koderhq.com/tutorial/rust/generics/

    use std::ops::Mul;
    fn square<T: Mul<Output = T> + Copy >(val:T)->T{
    
      return val*val;
    
    }
    
          
    
    use std::fmt::Display;
    fn console_log<T: Display> (x: T) {  
    
      println!("{}", x);
    
    }
    
    fn main() {
      
      println!("{}",  square(3) );
    
      console_log( 3 );
    
    }
    

    Rustやってみる(4)分岐や反復など

    ループ

    fn main() {
      for x in 1..=9{
        for y in 1..=9{
            print!("{} ",x*y);
        }
        println!("");
      }
    }
    
    1 2 3 4 5 6 7 8 9
    2 4 6 8 10 12 14 16 18
    3 6 9 12 15 18 21 24 27
    4 8 12 16 20 24 28 32 36
    5 10 15 20 25 30 35 40 45
    6 12 18 24 30 36 42 48 54
    7 14 21 28 35 42 49 56 63
    8 16 24 32 40 48 56 64 72
    9 18 27 36 45 54 63 72 81

    なんとRustのforにはCのforのようにカウンタを使う記述法がない。その手のものが必要な時はwhileを使う。さらにRustにはインクリメント演算子++がない。+=はあるのでそれを使う。

    なぜ++がないのかよくわからないが、コンパイラが進化した今inc命令とadd命令をプログラマが区別する必要はないのでそのために言語仕様を複雑にする必要はないとかそんな感じではないだろうか(適当)。

    fn main() {
      let mut k = 0;// 変数はデフォルトで変更不可なのでmutをつける
      while k < 10{
        println!("k=={}",k);
        k+=1; // Rustには++がない
      }
    
    }
    

    分岐

    if

    ifはCとかなり近い。ただし()で囲う必要がない。

    fn main()  {
    
      let k = 3;
    
      if k == 1{
        println!("k==1");
      }
      else if k==2{
        println!("k==2");
      }
      else{
        println!("other k");
      }
    
    }
    

    特に違うものとして、Cの三項演算子に該当するものがifで表記するようになっている。

    fn main()  {
    
      let k = 2;
    
      let msg = if k%2!=0 {"odd"}else{"even"};
     
      println!("{}",msg);
     
    }
    

    match

    いろいろとCのswitchに近いがbreakしないところが特に違う。あとカンマ区切り。

    fn main()  {
    
      let i = 2;
    
      // switchに近い。
      // ただし、matchの中で、「取りうるすべての可能性について」処理する必要がある
      match i{
    
        // Cと違いbreakしなくてもいい。ほかの式が実行されることはない
        3 => println!("three"),
    
        // 複数の指揮を実行するときは{}で括る
        4 => {
          println!("four");
          println!("FOUR")
        },
    
        // 取りうるすべての可能性を記述しなければいけないため
        // ワイルドカード _ を使ってCのdefaultと同じことをする。
        _ => println!("others"),
      };
     
    }
    

    matchの結果をそのまま変数に渡すこともできる。

    fn main()  {
    
      let i = 3;
    
      let msg:&str =   match i{
    
        3 => "three",
    
        4 => "four",
    
        _ => "others",
      };
    
      println!("{}",msg);
    
    }
    

    Rustやってみる(3)標準入力・ファイル入出力・あと文字列→数値

    キーボード入力

    // 入出力を使う
    use std::io;
    
    fn main() {
    
      // 変数 buffer を定義
      let mut buffer = String::new();
    
      // bufferへ文字列入力
      io::stdin().read_line(&mut buffer);
    
      // bufferを表示
      println!("{}",buffer);
    
    }
    

    文字列→数値

    // 入出力を使う
    use std::io;
    
    fn main() {
    
      // 変数 buffer を定義
      let mut buffer = String::new();
    
      io::stdin().read_line(&mut buffer); //標準入力から入力
    
      // 型指定 :i32 が必要
      // read_lineから読み込んだ文字列に対してはtrim()が必要
      let val:i32 = buffer.trim().parse().unwrap();
    
      // bufferを表示
      println!("{}",val);
    
    }
    

    ファイル入力

    // ファイル入力を使う
    use std::{fs::File, io::Read};
    
    fn main() {
    
      let filename = "test.txt";
     
    // ファイル入力を使う let mut file = File::open(filename).expect("file not found"); // 変数 buffer を定義 let mut buffer = String::new(); // ファイルから入力 file.read_to_string(&mut buffer).expect("something went wrong reading the file"); // ファイルを閉じる方法 // 方法1 スコープを抜けるとdropが呼ばれる(C++のデストラクタのようなもの) // 方法2 明示的にdropを呼び出す drop(file); // 明示的にdropを呼び出す // bufferを表示 println!("{}",buffer); }

    ファイル出力

    use std::fs::File;
    
    // write!やwrite_allを使うのに必要
    use std::io::Write;
    
    // 戻り値は std::io::Result<()> 型
    // 最後に OK(()) を返す。
    // これを入れないとwrite_allなどが使えない
    fn main()-> std::io::Result<()> {
    
      let filename = "test.txt";
     
      // ファイル入力を使う
      let mut file = File::create(filename)?;
      // 末尾の ? は例外処理のようなもの関連
      // ただしRustには例外がないのであくまでそれっぽく振る舞うだけ。
    
      // 変数 buffer を定義
      let _buffer = "hello".to_string();
    
      // ファイルへ書き出し
      file.write_all(_buffer.as_bytes())?;
    
      // こっちも使える
      // write!(file,"hello2")?;
    
      // ファイルを閉じる
      drop(file);
    
      // std::io::Result<()> 型の場合
      Ok(())
    
    }
    

    Rustやってみる(2)cargoコマンド

    Cargo

    CargoはRustのビルドシステム及びパッケージマネージャ。

    新規プロジェクト作成

    cargo new myproj

    ビルド

    cargo buildはカレントディレクトリにsrcディレクトリがあることを想定する。

    デバッグビルド

    cargo build

    リリースビルド

    cargo build –release

    パッケージを使う

    Rustではパッケージのことを「クレート」というらしい。Cargo.tomlの[dependencies]にモジュール名とバージョンを記述する。

    [package]
    name = “myproj”
    version = “0.1.0”
    edition = “2021”

    [dependencies]
    regex = “1.6.0”

    use regex::Regex;
    
    fn main() {
        let re = Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap();
        println!("Did our date match? {}", re.is_match("2014-01-01"));
    }
    
    cargo build

    cargo buildすると勝手にcrates.ioからクレートを取得するので上記の記述以外にすることはない。

    デバッグ(VSCode)

    VSCodeでデバッグできるのだが、私の環境では、クレートを使っているとVSCode関連で失敗する。

    細かく検証していないが上記regexを使った場合VSCodeからは実行すらできない。PowerShellからは動く。

    Error: Os { code: 10061, kind: ConnectionRefused, message: “対象のコンピューターによって拒否され
    たため、接続できませんでした。” }

    どれだけ検索しても対策が見つからなかったがcodelldbのバージョンによっては起こる?らしい。

    Rustやってみる(1)環境構築

    プログラミング言語Rustをやってみる。

    Windowsでは、

    https://learn.microsoft.com/ja-jp/windows/dev-environment/rust/setup

    のいうとおりにやればビルドできるようになる。以下要約。

    インストール

    1.VC++をインストール(必須環境)

    2.Rustをインストール(本体)
       https://www.rust-lang.org/tools/install

    3.VSCodeをインストール(エディタ・開発環境)
       https://code.visualstudio.com/

    4.VSCodeの拡張機能をインストール
       rust-analyzer
       CodeLLDB

    プロジェクト生成

    プロジェクト生成にはGUIがないのでコマンドラインからcargoコマンドを叩く。

    まずはプロジェクトを作成するディレクトリへ行き、

    cd D:\myDevelop\Rust

    cargoコマンドでプロジェクトを作成する。「cargo new プロジェクト名」

    cargo new first_rust_project

    プロジェクトを開く

    作成したプロジェクトのディレクトリを引数にVSCodeを起動するか、VSCodeを開きディレクトリをドラッグ&ドロップする。

    コマンドラインから開く場合(VSCodeのパスが通っている場合)

    code first_rust_project

    VSCodeにD&Dしてもいい

    内容確認

    src\main.rs … ソースコード本体
    Cargo.toml … プロジェクトの設定ファイル

    実行

    VSCodeで、 [実行]>[デバッグの開始] 。

    初回のみエラーメッセージのようなものが出るが、「OK」「はい」として、launch.jsonが出たら何もせず閉じてもう一度デバッグの開始。

    以下引用:

    CodeLLDB 拡張機能とデバッガーで初めてアプリを実行すると、”起動構成が提供されていないため、デバッグを開始できません” というダイアログ ボックスが表示されます。 [OK] をクリックすると、”このワークスペースで Cargo.toml が検出されました。 ターゲットの起動構成を生成しますか?” という 2 番目のダイアログ ボックスが表示されます。 [はい] をクリックします。 次に、launch.json ファイルを閉じて、もう一度デバッグを開始します。

    gl_PointSize を使って頂点ごとにサイズ指定。カメラに迫る点群を疑似的に表現する

    近い点をより大きく描画することで頂点がカメラに近づく表現をする。

    #pragma warning(disable:4996)
    
    #pragma comment(lib,"glew32.lib")
    
    
    #include <gl/glew.h>
    #include <GL/glut.h>
    
    #include <fstream>
    #include <sstream>
    #include <vector>
    #include <algorithm>
    #include <array>
    
    typedef std::array<GLfloat,3> point_t; //モデルの座標用 x y z
    typedef std::array<GLfloat,4> color_t;//テクスチャ座標用 r g b a
    
    //////////////////////////////////////////
    //////////////////////////////////////////
    //////////////////////////////////////////
    
    
    const char* vshader_program = R"(
    #version 460 core
    
    layout(location = 0) in vec3 vtx;
    layout(location = 1) in vec4 color;
    
    out vec4 vColor;
    
    uniform mat4 ModelViewMatrix;
    uniform mat4 ProjectionMatrix;
    
    // カメラ座標
    uniform vec4 campos;
    
    void main()
    {
      gl_Position = ProjectionMatrix * ModelViewMatrix * vec4(vtx, 1.0);
    
      // 近いものほど大きく見せる
      float size = 50 / distance(campos,gl_Position);
    
      vColor = color;
      gl_PointSize = size; // 頂点のサイズ(ピクセル)
    }
    
    )";
    //////////////////////////////////////////
    //////////////////////////////////////////
    //////////////////////////////////////////
    
    
    const char* fshader_program = R"(
    #version 460 core
    
    out vec4 FragColor;
    
    in vec4 vColor;
    
    void main()
    {
      FragColor = vColor;
    
    }
    )";
    /////////////////////////////////
    //バッファとデータ
    GLuint vertexbufferName;
    GLuint colorbufferName;
    const GLuint v_count=100;
    
    GLuint VertexShaderID;
    void prepare_vertex_shader();
    
    GLuint FragmentShaderID;
    void prepare_fragment_shader();
    
    GLuint ProgramID;
    void link_program();
    
    
    void init(void);
    void display(void);
    
    void timer(int value) {
      // 再描画
      glutPostRedisplay();
    
      // 100ミリ秒後にtimer関数を引数0で自分自身を呼び出す
      glutTimerFunc(100, timer, 0);
    }
    
    int
    main(int argc, char* argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA); glutCreateWindow(argv[0]); glutDisplayFunc(display); glutReshapeWindow(300, 300); glewInit(); // glewの初期化 init(); glutTimerFunc(100, timer, 0); glutMainLoop(); return 0; } void prepare_buffers(); void init(void) { //頂点データと色情報の作成 prepare_buffers(); //頂点シェーダの準備 prepare_vertex_shader(); //フラグメントシェーダの準備 prepare_fragment_shader(); //プログラムのリンク link_program(); } //////////////////////////////////////////////////
    void prepare_buffers() {
      //////////////////////////////////////////
      //////////////////////////////////////////
      std::vector< point_t > vertex;
      std::vector< color_t > color;
    
      float scale=50000.0f;
      for (size_t i = 0; i < v_count; i++){
        float x = (rand() % (int)scale) * (1.0f / scale) - 0.5;
        float y = (rand() % (int)scale) * (1.0f / scale) - 0.5;
        float z = (rand() % (int)scale) * (1.0f / scale) - 0.5;
        vertex.emplace_back(point_t{ x*1.5f,y*1.5f,z*50 });
    
        float r = (rand() % (int)scale) * (1.0f / scale);
        float g = (rand() % (int)scale) * (1.0f / scale);
        float b = (rand() % (int)scale) * (1.0f / scale);
        color.emplace_back(color_t{ r,g,b,1 });
      }
    
      //////////////////////////////////////////
      //////////////////////////////////////////
    
      glGenBuffers(1, &vertexbufferName);
      glBindBuffer(GL_ARRAY_BUFFER, vertexbufferName);
      glBufferData(GL_ARRAY_BUFFER, 3 * v_count * sizeof(GLfloat), vertex.data(), GL_STATIC_DRAW);
    
      glGenBuffers(1, &colorbufferName);
      glBindBuffer(GL_ARRAY_BUFFER, colorbufferName);
      glBufferData(GL_ARRAY_BUFFER, 4 * v_count * sizeof(GLfloat), color.data(), GL_STATIC_DRAW);
    
    }
          
          
    void prepare_vertex_shader() {
    
      //////////////////////////////////////////////
        // シェーダを作ります
        // (作るといっても宣言みたいなもの)
      VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
    
      ////////////////////////////////////////////
      // ファイルから頂点シェーダを読み込みます。
      // 注意 ここはSTLのifstreamとかstringstreamの使い方の話で、
      // OpenGL命令は一つも無い。
      std::string VertexShaderCode = vshader_program;
      ////////////////////////////////////////////
      // 頂点シェーダをコンパイルします。
      //printf("Compiling shader : %s\n", vertex_file_path);
      char const* VertexSourcePointer = VertexShaderCode.c_str();
      glShaderSource(VertexShaderID, 1, &VertexSourcePointer, NULL);
      glCompileShader(VertexShaderID);
    
      ////////////////////////////////////////////
      // エラーチェック
      GLint Result = GL_FALSE;
      int InfoLogLength;
    
      // 頂点シェーダをチェックします。
      glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
      glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
      if (Result == FALSE) {
        std::vector<char> VertexShaderErrorMessage(InfoLogLength);
        glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
        fprintf(stdout, "%s\n", &VertexShaderErrorMessage[0]);
      }
    
    }
    
          
          
    void prepare_fragment_shader() {
    
      /////////////////////////////////////////////
      // シェーダを作ります。
      FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
    
      /////////////////////////////////////////////
      // ファイルからフラグメントシェーダを読み込みます。
      std::string FragmentShaderCode = fshader_program;
      /////////////////////////////////////////////
      // フラグメントシェーダをコンパイルします。
      //printf("Compiling shader : %s\n", fragment_file_path);
      char const* FragmentSourcePointer = FragmentShaderCode.c_str();
      glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer, NULL);
      glCompileShader(FragmentShaderID);
    
      GLint Result = GL_FALSE;
      int InfoLogLength;
    
      /////////////////////////////////////////////
      // フラグメントシェーダをチェックします。
      glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
      glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
      if (Result == GL_FALSE) {
        std::vector<char> FragmentShaderErrorMessage(InfoLogLength);
        glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
        fprintf(stdout, "%s\n", &FragmentShaderErrorMessage[0]);
      }
    }
    
          
    void link_program() {
    
      GLint Result = GL_FALSE;
      int InfoLogLength;
    
      ////////////////////////////////////////
      // プログラムをリンクします。
      fprintf(stdout, "Linking program\n");
      ProgramID = glCreateProgram();
      glAttachShader(ProgramID, VertexShaderID);
      glAttachShader(ProgramID, FragmentShaderID);
      glLinkProgram(ProgramID);
    
      ////////////////////////////////////////
      // プログラムをチェックします。
      glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
      glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
      std::vector<char> ProgramErrorMessage((std::max)(InfoLogLength, int(1)));
      glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
      fprintf(stdout, "%s\n", &ProgramErrorMessage[0]);
    
    }
    void display(void)
    {
    
      glClearColor(0, 0, 0, 1);
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
      glEnable(GL_DEPTH_TEST);
    
      glLoadIdentity();
      //glTranslated(0.5, 0.0, 0.0);//平行移動
    
      glUseProgram(ProgramID);
    
      GLfloat mfproj[16];
      GLfloat mftran[16];
    
      mfproj[0] = 2.26961231;
      mfproj[1] = 0.0;
      mfproj[2] = 0.0;
      mfproj[3] = 0.0;
      mfproj[4] = 0.0;
      mfproj[5] = 2.41421366;
      mfproj[6] = 0.0;
      mfproj[7] = 0.0;
      mfproj[8] = 0.0;
      mfproj[9] = 0.0;
      mfproj[10] = -1.00020003;
      mfproj[11] = -1.00000000;
      mfproj[12] = 0.0;
      mfproj[13] = 0.0;
      mfproj[14] = -0.0200020000;
      mfproj[15] = 0.0;
    
    
      static float z = -10.0;
    
      z += 0.2;
      mftran[0] = 1.0;
      mftran[1] = 0.0;
      mftran[2] = 0.0;
      mftran[3] = 0.0;
      mftran[4] = 0.0;
      mftran[5] = 1.0;
      mftran[6] = 0.0;
      mftran[7] = 0.0;
      mftran[8] = 0.0;
      mftran[9] = 0.0;
      mftran[10] = 1.0;
      mftran[11] = 0.0;
      mftran[12] = 0.0;//x
      mftran[13] = 0.0;//y
      mftran[14] = z;//z
      mftran[15] = 1.0;
      GLint proj = glGetUniformLocation(ProgramID, "ProjectionMatrix");
      GLint modl = glGetUniformLocation(ProgramID, "ModelViewMatrix");
      glUniformMatrix4fv(proj, 1, GL_FALSE, mfproj);
      glUniformMatrix4fv(modl, 1, GL_FALSE, mftran);
    
      GLint campos = glGetUniformLocation(ProgramID, "campos");
      GLfloat fcp[4] = { 0,0,z };
      glUniform3fv(campos,1, fcp);
    
    
      //gl_PointSizeを有効にする
      glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
    
      // 頂点バッファ
      glEnableVertexAttribArray(0);
      glBindBuffer(GL_ARRAY_BUFFER, vertexbufferName);
      glVertexAttribPointer(
        0,                  // 属性0
        3,                  // 1要素の要素数 x y z
        GL_FLOAT,           // タイプ
        GL_FALSE,           // 正規化しない(データが整数型の時)
        0,                  // ストライド
        (void*)0            // 配列バッファオフセット
      );
    
      // カラーバッファ
      glEnableVertexAttribArray(1);
      glBindBuffer(GL_ARRAY_BUFFER, colorbufferName);
      glVertexAttribPointer(
        1,                  // 属性1
        4,                  // 1要素の要素数 r g b a
        GL_FLOAT,           // タイプ
        GL_FALSE,           // 正規化しない(データが整数型の時)
        0,                  // ストライド
        (void*)0            // 配列バッファオフセット
      );
    
      // 5頂点を描く
      glDrawArrays(GL_POINTS, 0, v_count);
    
      glDisableVertexAttribArray(0);
      glDisableVertexAttribArray(1);
      glDisableVertexAttribArray(2);
    
      ////////////////////////////////////////
      ////////////////////////////////////////
      glFlush();
    
    
    }