Home New Help Edit

C++ memo

2008年1月30日
Suns & Moon Laboratory

はじめに

C++の勉強中です
C言語も勉強中です。


typedef


参考:typedef enumの使い方を教えてください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 <iostream> 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++)

インターフェース

インターフェース実装の例。わかりやすい。
一週間で身につくC++言語の基本 - 第6日目:virtualと仮想関数


テンプレートを使った関数

template <class T> 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<w;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<BYTE>(Image,sx,sy,w,h); }else if(Image.BitsPerPixel() == 16){ Color = GET_PIXELS<WORD>(Image,sx,sy,w,h); }else{ throw "Error! not supported pixel format"; } }

無名の名前空間

参考:msdn→Deep C++ 無名の名前空間

文字列と戻り値

参考:どう書く?C++

例外

#include <iostream> 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 <queue> std::queue<bool> queue_press;

vector

バッファとしての使用

結論を先に言うと、メモリ上の配置が連続する事は、仕様で規定されている...そうです。
ネットでそういう裏付けをさがしていたのですが、見つからなくて困っていました。
その疑問の答えが下記リンクにあります。(教えてくれてありがとう>某氏)
参考:テンポラリ・バッファとしての std::vector の利用

基本

insertよりもpush_backを使う。insertはメモリーの再確保を行うので遅い

#include <vector> #include <iostream> int main() { using namespace std; vector<int> 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<int>::iterator it = arr.begin();it != arr.end();it++) cout << *it << endl; return 0; }

イテレータで移動

vector<double> v; v.resize(10); vector<double>::iterator it = v.begin(); advance(v,5);

コンテナの初期化

fill(),fill_n()を使う。
vector<double> v; v.resize(100); fill(v.begin(),v.end(),0);//すべて0にする

map

#include <map> #include <string> using namespace std; map<string,string> data; data.insert(map<string,string>::value_type("square","enix")); data.insert(map<string,string>::value_type("bandai","namco")); data.insert(map<string,string>::value_type("sega","summy")); //要素数 cout << "要素数 = " << (unsigned int)data.size() << endl; //全要素出力 map<string,string>::const_iterator it = data.begin(); while(it != data.end()){ cout << "key=" << it->first << " val=" << it->second << endl; it++; } //keyで検索 { map<string,string>::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 <iostream> #include <fstream> 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;
参考 静的データメンバ

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/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 <stdio.h> 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 カンマ演算子

ワーニング対策


未使用の引数

void ttvm_dbgout(char* /*str*/=0)

参考

●C++編(標準ライブラリ) トップページ
書籍:C++ Coding Standards

Home New Help Edit
2023-05-10 09:40:01 32400