cpp
*C++ memo 2008年1月30日 [[index]] #contents **はじめに C++の勉強中です C言語も勉強中です。 **typedef 参考:[[typedef enumの使い方を教えてください>https://oshiete.goo.ne.jp/qa/856772.html]]No.3 >enumについては5種類の書き方があり、 > >1) enum E { e1, e2 }; >2) enum E { e1, e2 } v; >3) enum { e1, e2 } v; >4) typedef enum E { e1, e2 } Ea; >5) typedef enum { e1, e2 } Ea; >というものです。 >(1)は標準的な"型定義のみの"記法です。 >(2)は(1)の効果に加えて、変数宣言も同時に行うものです。このときvの型はEです。 >(3)は変数宣言を行う記法です。このときはvの型は"無名"になり、プログラム中でvの型を記述することはできません。 >(4)は型定義と型の別名宣言を同時に行う書式です。Eの別名Eaを宣言しています。これはenum Eと書かずにE2に書けるようにするためで、単に記述がしやすくなることを狙ったものです。 >(5)は(4)から型の名前を除いたものです。enumのオリジナルの型は無名になってしまいますが、(3)と違い、E2として型名を参照できるので、プログラム中で無名型をE2として再利用することが出来ます。 ***typedef enum >typedef enum >{ > ROTARY_SEQ_IDLE, > ROTARY_SEQ_CHG, > ROTARY_SEQ_DOWN, >} ROTARY_SEQ_STATE; ***typedef struct >typedef struct struct_pattern{ > unsigned short PatternStart; > unsigned short PatternEnd; >}PATTERN_t; **CとC++の混在時名前解決 >#ifdef __cplusplus >extern "C" { >#endif > > >#ifdef __cplusplus >} >#endif **最大値 limits.hに定義されている。 **coutを手っ取り早く使う >#include
>using namespace std; >void sample() >{ > cout << "Hello" << endl; >} **継承 >class IxTest{ > private: > protected: > public: > virtual void Init(); //IxTestで実装、継承して実装可能。 > virtual void Test() = 0; //純粋仮想関数。IxTestでは実装しない。この場合IxTestクラスはインスタンス化できない。 >}; > >class IxTestCustom : public IxTest{ > public Test();//純粋仮想関数を実装したので、IxTestCustomはインスタンス化出来る >}; [[抽象クラス (C++)>https://docs.microsoft.com/ja-jp/cpp/cpp/abstract-classes-cpp?view=msvc-170]] ***インターフェース インターフェース実装の例。わかりやすい。 [[一週間で身につくC++言語の基本 - 第6日目:virtualと仮想関数>https://cpp-lang.sevendays-study.com/ex-day6.html]] **テンプレートを使った関数 > template
double GET_PIXELS(IkImage &Image,const int sx,const int sy,const int w,const int h){ > double result = 0; > > int line_bytes = Image.get_line_bytes(Image.Width(),Image.BitsPerPixel()); > > for(int y=sy;y<(sy+h);y++){ > T *ptr; > ptr = (T *)(Image.PixelData + (sx * sizeof(T)) + (line_bytes * y)); > for(int xc=0;xc
result += *ptr; > ptr++; > } > } > > return result / (w * h); > } > > void IkImageManiGetPixels::Execute(IkImage &Image,const int sx,const int sy,const int w,const int h) > { > if(Image.BitsPerPixel() == 8){ > Color = GET_PIXELS
(Image,sx,sy,w,h); > }else if(Image.BitsPerPixel() == 16){ > Color = GET_PIXELS
(Image,sx,sy,w,h); > }else{ > throw "Error! not supported pixel format"; > } > } **無名の名前空間 参考:[[msdn→Deep C++ 無名の名前空間>http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/jpdndeepc/htm/deep04062000.asp]] **文字列と戻り値 参考:[[どう書く?C++>http://tech.sinby.com/wiki_ja/index.php?%A4%C9%A4%A6%BD%F1%A4%AF%A1%A9C%2B%2B]] **例外 >#include
>using namespace std; > >void func1(void) >{ > cout << "func1 start" << endl; > try{ > throw "throw func1\n"; > } > catch(...){ > cout << "func1 catch" << endl; > throw;//ここで例外を再生成すれば、mainでも例外を受け取れる。 > } > cout << "func1 end" << endl;//例外再生成すると、ここにはこない >} > > >void main(int argc,char *argv[]) >{ > try{ > cout << "main start" << endl; > func1(); > cout << "main called func1" << endl;//例外によってここには来ない > } > catch(...){ > cout << "main catch" << endl; > } > cout << "main end" << endl;//catchした後に、ここは実行される >} **string 文字列の追加はappend()か+=を使う。 ***string::erase > src = "0123456789"; > src.erase(0,3); > cout << "erase(0,3) " << src << endl;//No.0から3個削除 -> 3456789 > > src = "0123456789"; > src.erase(1,3); > cout << "erase(1,3) " << src << endl;//No.1から3個削除 -> 0456789 > > src = "0123456789"; > src.erase(2,5); > cout << "erase(2,5) " << src << endl;//No.2から5個削除 -> 01789 > > src = "0123456789"; > src.erase(3); > cout << "erase(3) " << src << endl;//No.3以降を削除 -> 012 **std::queue push() pop() empty() front() >#include
>std::queue
queue_press; **vector ***バッファとしての使用 結論を先に言うと、メモリ上の配置が連続する事は、仕様で規定されている...そうです。 ネットでそういう裏付けをさがしていたのですが、見つからなくて困っていました。 その疑問の答えが下記リンクにあります。(教えてくれてありがとう>某氏) 参考:[[テンポラリ・バッファとしての std::vector の利用>http://www.s34.co.jp/cpptechdoc/article/vectorastemp/index.html]] ***基本 insertよりもpush_backを使う。insertはメモリーの再確保を行うので遅い >#include
>#include
> >int main() >{ > using namespace std; > vector
arr; > > // 要素追加 > for(int i = 0; i < 10; ++i ) > arr.push_back( i ); > > cout << "配列の添え字でアクセス" << endl; > for(unsigned int i = 0; i < arr.size(); ++i ) > cout << arr[i] << endl; > > cout << "イテレータでアクセス" << endl; > for(vector
::iterator it = arr.begin();it != arr.end();it++) > cout << *it << endl; > > return 0; >} ***イテレータで移動 >vector
v; >v.resize(10); >vector
::iterator it = v.begin(); >advance(v,5); ***コンテナの初期化 fill(),fill_n()を使う。 >vector
v; >v.resize(100); >fill(v.begin(),v.end(),0);//すべて0にする **map >#include
>#include
>using namespace std; > map
data; > > data.insert(map
::value_type("square","enix")); > data.insert(map
::value_type("bandai","namco")); > data.insert(map
::value_type("sega","summy")); > > //要素数 > cout << "要素数 = " << (unsigned int)data.size() << endl; > > //全要素出力 > map
::const_iterator it = data.begin(); > while(it != data.end()){ > cout << "key=" << it->first << " val=" << it->second << endl; > it++; > } > > > //keyで検索 > { > map
::const_iterator it = data.find("square"); > if (it != data.end()){//成功失敗はendと比較 > cout << it->second.c_str() << endl; > } > } > > //全て削除 > data.clear(); > > //空? > if(data.empty()){ > cout << "空です。" << endl; > } 出力はこう >要素数 = 3 >key=bandai val=namco >key=sega val=summy >key=square val=enix >enix >空です。 **ifstream >#include
>#include
> >int main(int argc,char *argv[]) >{ > using namespace std; > ifstream ifs(argv[1],ios::in | ios::binary); > > while(!ifs.eof()){ > char buf[256]; > ifs.getline(buf,sizeof(buf),'\n'); > cout << "> " << buf << endl; > } > > return 0; >} ***seekg >seekg(移動量,std::ios::beg); **静的データメンバ(静的クラスメンバ) データメンバを静的(static)宣言すると、生成されたオブジェクトで共有するデータメンバが出来る。 で、実体は宣言されないので、別途実体を宣言すると。 >class SampleClass{ > static int device_counter; >} > >int SampleClass::device_counter; 参考 [[静的データメンバ>http://cppemb.blog17.fc2.com/blog-entry-79.html]] **printf書式 longを出したいときは、l付けるの忘れない。 >sprintf(buf,"%08lX",val); **関数ポインタとtypedef >typedef void (*UART_SETUP)(void); > >UART_SETUP uart_setup; > >void uart_a0_setup(void) >{ >... >} > >uart_setup = uart_a0_setup; //初期化 >uart_setup(); //呼び出し **関数ポインタと構造体の初期化 よく忘れるのでメモ。 >void cmd_ver(void){ > //処理 >} > >typedef struct{ > const char *name; > void (*function)(void); >} name_func_st; > >const name_func_st name_func_list[]={ > {"VER" ,cmd_ver } >,{"CTL" ,cmd_ctl } >}; ***関数ポインタ配列例 >typedef struct >{ > const char *name; > void (*function)(void); >} name_func_st; > >const name_func_st name_func_list[] = >{ >{ "KEY", sterm_cmd_key }, >{ "VER", sterm_cmd_ver }, >{ "HELP", sterm_cmd_help }, >{ "H", sterm_cmd_help }, >{ "?", sterm_cmd_help }, >{ 0, 0 } }; > > int index = 0; > while (name_func_list[index].function != 0) > { > if (strcmp(name_func_list[index].name, params[0]) == 0) > { > name_func_list[index].function(); > return; > } > index++; > } ***クラスメンバ関数の配列呼び出し [[クラス内での関数ポインタの配列を作る>https://rarara.org/community/programming/%E3%82%AF%E3%83%A9%E3%82%B9%E5%86%85%E3%81%A7%E3%81%AE%E9%96%A2%E6%95%B0%E3%83%9D%E3%82%A4%E3%83%B3%E3%82%BF%E3%81%AE%E9%85%8D%E5%88%97%E3%82%92%E4%BD%9C%E3%82%8B/]] [[https://rarara.org/community/postid/41475/]] Blueさんの投稿 >class Foo >{ > public: > int func(int n, int m) > { > static int (Foo::*f[2])(int) = { funcA, funcB }; > return (this->*f[n])(m); > } > > int funcA(int){return 1;} > int funcB(int){return 2;} >}; > >int main() >{ > Foo foo; > int n = foo.func(0, 0); // n = 1 > return 0; >} **文字列ポインタの配列 >#include
>int main() >{ > const char* onof_text[] = { "On","Off" }; > char** texts; > > texts = (char**)&onof_text[0];//どっちでも一緒 > texts = (char**)onof_text;//どっちでも一緒 > > printf("%s\r\n", texts[0]); > printf("%s\r\n", texts[1]); >} **文字列の二次元配列 >static const char* str_arr[3][4] = { > {"A1","A2","A3","A4"} > ,{"B1","B2","B3","B4"} > ,{"L1","C2","C3","C4"} >}; > > char* ptr = (char*)str_arr[alpha_index][num_index]; **デフォルト引数 引数省略 >void func(int a,int b=5){return a+b;} **カンマ演算子 カンマで複数の式を1つの式にまとめる事が出来る。 評価結果は右端の式の結果。 下記の場合は、2が返ってくる。 > return 1,2; [[expressionとstatement カンマ演算子>https://days-of-programming.blogspot.com/2016/02/expressionstatement.html]] **ワーニング対策 ***未使用の引数 >void ttvm_dbgout(char* /*str*/=0) **参考 [[●C++編(標準ライブラリ) トップページ>http://www.geocities.jp/ky_webid/cpp/library/index.html]] 書籍:C++ Coding Standards
2024-11-21 19:18:07 32400