2019年12月30日月曜日

2019年12月13日金曜日

範囲for

配列やコンテナ内の全要素に対する処理は
普通の配列ならともかく
コンテナの場合はイテレータなどを用いて
記述が長くなりがちですがC++11以降では
次の様に書くこともできます。

        for (auto&& i : array)
        {
            i = …// iにアクセスできる
        }

iは、for内部で配列の各要素にアクセスするために
自由に設定できる変数名、
arrayは、事前に定義し要素を収納してある
配列やコンテナの名前です。



参考(外部サイト)

2019年3月30日土曜日

2017年4月27日木曜日

ファイル入出力

ファイル入出力って曲者だと思いませんか?
基本概念は分かっていても
昔どうやってたんだか分からんくなったり
昔の方法が使えなくなっていたり
きちんと調べ治すのも面倒だったりで
取り合えず場当たり的に色んなサイトを参考にして
最初にうまくいった方法をメモしておきます。
(環境はVC++2015でDXライブラリを使っている時)
参考にしたのはこのページとかここ

例を見てもらえば分かると思いますが、おおよそ、はじめC言語的にファイルを開いて
書き込みならfwrite()、読み込みならfread()を使うだけな感じです。
fwrite()の引数は

1:書き込みデータのポインタ
2:書き込みデータのバイトの長さ
3:書き込みデータの数(単数なら1、配列なら複数とか)
4:FILEポインタ
です。
書き込みと読み込みで違いは僅かです。

//-------------------------
//書き込みの例
//-------------------------

// ファイルを開く
FILE* fp;
fopen_s(&fp, "./filename.dat", "wb");//読み込みなら"rb"

//書き込み用の変数を用意
bool b = false;
int n = 9999;
char c = -100;
unsigned char uc = 200;
//構造体もOKだけど内部にポインタ使用してないかは注意
struct Stra
{
float f;
unsigned short us;
};
Stra stra;
stra.f = 3.14;
stra.us = 12345;

std::string st = "aiuあいう文字2017";
size_t stSize = st.size() + 1; //文字列のサイズも記録しておく(終端文字用に+1する)

//変数の書き込み
fwrite(&b, sizeof(b), 1, fp);
fwrite(&n, sizeof(n), 1, fp);
fwrite(&c, sizeof(c), 1, fp);
fwrite(&uc, sizeof(uc), 1, fp);
//構造体の書き込み
fwrite(&stra, sizeof(stra), 1, fp);
//テキストの書き込み
fwrite(&stSize, sizeof(size_t), 1, fp);//テキストchar(バイト)の数
fwrite(st.c_str(), sizeof(char), stSize, fp);//テキスト本体

// ファイルを閉じる
fclose(fp);


//------------------------
//読み込みの例
//------------------------

// ファイルを開く
FILE* fp;
// 読み込みでオープン
fopen_s(&fp, "./filename.dat", "rb");

//読み込み用の変数を用意
bool b;
int n;
char c;
unsigned char uc;
struct Stra
{
float f;
unsigned short us;
};
Stra stra;

//変数の読み込み
fread(&b, sizeof(b), 1, fp);
fread(&n, sizeof(n), 1, fp);
fread(&c, sizeof(c), 1, fp);
fread(&uc, sizeof(uc), 1, fp);
//構造体の読み込み
fread(&stra, sizeof(stra), 1, fp);
//テキストの読み込み
size_t stSize;
fread(&stSize, sizeof(size_t), 1, fp);//サイズ受け取り
 char *cTex = new char[stSize];//テキスト受け取り
fread(cTex, sizeof(char), stSize, fp);
std::string st = cTex; //stringに格納
delete[]cTex;
// ファイルを閉じる
fclose(fp);
-------------------------------
std::stringに直接文字列を読み込む方法もあるかもですが
とりあえずchar配列で受け取ってみました。

2016年9月26日月曜日

ビット演算によるフラグ管理





 ーーーーサンプル-----
// フラグ位置を表す定数
const unsigned int a = (1 << 0);
const unsigned int b = (1 << 1);
const unsigned int   c = (1 << 2);

//フラグ全体を持つ変数
unsigned int flag = 0;

//フラグaをオンにする
flag |= a;

// フラグ a, b, c をオンにする
flag |= a | b | c ;

//フラグaをオフにする.
flag &= ~a;

 // フラグa ,b, c をオフにする.
flag &= ~( a | b | c );


// フラグaがオンならtrue
if(flag & a)

// フラグa,b,cどれか一つでもオンならtrue
if(flag & ( a | b | c ) )

// フラグa,b,c 全てがオンならtrue
if( (flag & ( a | b | c ) ) == (a| b | c ) )


// フラグaのオンオフ切り替え
flag ^= a

ーーーー解説-----
メモリの量と情報量で述べた様に
変数はビットの状態の組み合わせによって状態を表す事が出来ます。

従って、例えばある人が3つの果物のうち
どれを持っていてどれを持っていないのかは

bool型を用いて

bool apple = true; //リンゴは持っている
bool banana = false; //バナナは持っていない
bool cherry = false; //サクランボは持っていない

という風に表せるのは勿論ですが

int fruit = 1;

という風に書いておき、

fruit = 0 なら何も持っていない
fruit = 1 ならリンゴだけを持っている
fruit = 2 ならバナナだけ持っている
fruit = 3ならサクランボだけ持っている
fruit = 4 ならリンゴとバナナは持っている
fruit = 5 ならバナナとサクランボは持っている
fruit = 6 なら リンゴとサクランボは持っている
fruit = 7なら全てのフルーツを持っている

みたいな解釈をする事で
一つの変数で複数の状態の設定が出来る事になります。

ただしこの場合、メモリの量は節約できるかも知れませんが
可読性が下がり兼ねないので
ビット演算によるフラグ管理(状態管理)が便利になってきます。

ビット演算を用いるとメモリの節約だけでなく
可読性や操作性においても効力を期待できます。

(勿論、規模や用途や様々な理由で不要に感じられる
場合も多いと思います。必要に応じて読んでください。)


ビット演算をすると変数中のメモリに対して
ビット単位で0か1の状態を指定できるため、
リンゴを持っているかいないか等を
そのまま特定のメモリの状態で表現できます。

以下はリンゴを a, バナナをb, サクランボをcとして
フラグ管理をする例です。

 サンプルを見れば使い方は分かるはずですが
「&」や 「|」 などのビット演算子の意味を理解しようとする場合は
次の事に注意してください。

・ビット演算は見た目としては二つの変数に対して行われるが
 実際は各変数を表すビット配列中の各ビット位置ごとに
 演算が適用される。
 つまり変数(ビット配列)同士の集団戦という見た目だが
 実際は1ビット対1ビットの個人戦がビットの数だけ行われる。

・優先順位が同じ演算が複数並んでいれば左から行われる。
 したがって 例えば
   A |  B |  C
とあれば AとBを |(or演算)した後に
その結果に対して Cと | (or演算)する。



ではいくつか例を見ながら考えてみましょう。

const unsigned int a = 1;  //リンゴを持っている
const unsigned int b = 2;  //バナナを持っている
const unsigned int   c = 4;  //サクランボを持っている

unsigned int flag = 0; //何も持っていない
 
現時点で各変数は下3桁のビットが以下の様になっています。

a = 001
b = 010
c = 100
flag = 000

constが付いているa,b,cはビット配列中、
どの部分が1かによってどのビット位置に注目するかを
表すための変数なので変更する必要がない
ため定数となっています。

一方、flag は、ある人が現在どの様な果物を
持っているか等、変更し得る状態を表すための
変数だとします。
ビット配列中、どの位置が1かで
どの果物を持っているかのフラグにしたいので
現在flagに0が入っているという事は
二進数でも000000…となるので
全てのビットが0になっているので
何も持っていない事を意味します。

なお、これらの定義は

const unsigned int a = (1 << 0);
const unsigned int b = (1 << 1);
const unsigned int c = (1 << 2);

という様にビットシフトで書く事も出来ます。

さてflagがリンゴを持っている事にしたいなら

or演算「 | 」が使えます。
「 | 」の効果は
 「二つのビットのうちどちらかが1なら結果が1になる」
 というものです。

これによりflagのリンゴの位置のビットが
0(持っていない)だとしても
1(すでに持っている)だとしても
リンゴと同じ1(持っている状態)
に変える事が出来ます。

筆算で表すと一目瞭然です。

  000(何も持っていないflag)
  001  (a)
-------- |
  001  (結果)


  001(リンゴを持っているflag)
  001  (a)
-------- |
  001  (結果)


flag |= a と書くと
flag = flag |  a と同じ意味なので
flag | a の演算結果をflagに代入する事が出来ます。

//フラグaをオンにする
flag |= a;
// フラグa,b,cをオンにする
flag |= a | b | c ;

--------------------------------------------
現在のフラグの確認は&で出来ます。

// flag中のaのビットがオンならtrue
if(flag & a)
 
&は「両方とも1なら1, それ以外は0にする」演算子です。


001 (flag)
001 (a)
--------&
001  = true


000 (flag)
001 (a)
---------&
000  = false


110 (flag)
001 (a)
-------&
000 = false


011 (flag)
001 (a)
-------&
001 = true

if文の中の評価は
0は偽だけどそれ以外は全て真になるんで
ビット演算した結果、全てが0にならないと
変数として0にならないので
論理値としては真なのだという事に
注意してください。


 従って
// フラグa,b,cのどれか一つでもオンならtrueになる
if(flag & ( a | b | c ) )

---------------------------

// フラグa,b,c 全てがオンならtrue
if( (flag & ( a | b | c ) ) == (a| b | c ) )

flagを0111とした時の計算順序は
以下の様になります。

0001 a
0010 b
0100 c
-------|
0111 (a|b|c)
0111 flag
--------&
0111 flag
0111 (a|b|c)
---------- =
   true


次はflagを1111で考えてみましょう。

0001 a
0010 b
0100 c
-------|
0111 (a|b|c)
1111 flag
--------&
0111 flag
0111 (a|b|c)
--------=
  true

---------------------------------------
//a のビットをオフにする.
flag &= ~a;

~を使えばビットを反転できるため
変数全体がそのフラグと真逆の状態となります。
例えば
a (001)は~を付けて~aにすると
110になります。これは
bやcのフラグが立ってしまう訳ですが
この状態で&演算すると

000(flag)
110(~a)
------&
000

001 (flag)
110 (~a)
-----&
000

111 (flag)
110 (~a)
-----&
110

という風にaの位置を確実にオフにし、
他のフラグはそのままにする効果が得られます。

従ってaのビットをオフにする処理は
flag &= ~a;
で出来ます。

--------------------------------------------
 // a と b のビットをオフにする.flag &= ~(a | b);


これは3つの演算が行われています。

まず
(a | b)で
001
010
-----
011

それを~で反転し
100になり、

それを&演算で
100 (~(a|b))
111(flag)
-----&
100

という風に目的の場所は
オフにするけどそれ以外は
そのまま残す様な処理が出来ます。
---------------------------------------------
フラグaのオンオフを切り替えたい場合は

flag ^= a

で出来ます。
^は「両方のビットが同じなら0、異なるなら1にする」演算子です。
これを筆算で見ると

001 (flag)
001 (a)
---- ^
000 (aの位置は同じなので0)


100 (flag)
001 (a)
---- ^
101 (aの位置は異なるので1)

という風にflagがどちらの状態でも
結果は反転し、
かつフラグと無関係の位置は
そのまま残ります。

2012年11月18日日曜日

Direct3D10.1の概要と導入

Direct3Dのバージョン10.1は、バージョン10にこんな機能 が追加されています。また、Direct2Dとの連携が出来ます(Direct2D と GDI の相互運用性の概要)。
対応OSはVistaのサービスパック1適用以降みたいです。つまり、ほとんどDirect3D10の要件と同じです。ただし以前のビデオカードには、10までしか対応していないものがあるので、少し動作環境が狭まります。

APIの扱い方は10時代とほとんど変わりません。Direct3D10のチュートリアルを以下の様に変更すれば使えます。

・「d3d10.h」の代わりに「d3d10_1.h」をインクルードします。
・ リンクするライブラリは「D3D10.lib」ではなく「D3D10_1.lib」です。
(プロパティー→リンカー→入力の追加の依存ファイルを変えましょう。)
・ID3D10DeviceではなくID3D10Device1を使います。
そしてD3D10CreateDeviceAndSwapChain()ではなく、最後に1が付く
D3D10CreateDeviceAndSwapChain1()を使って初期化します。
これは10時代のメソッドと違い、第5引数に
D3D10_FEATURE_LEVEL1   HardwareLevel,
が加わっています。ここには
D3D10_FEATURE_LEVEL_10_1
を入れましょう。
またその次の第6引数はSDKのバージョンなのですが、
  D3D10_1_SDK_VERSION,
を入れましょう。

2012年10月25日木曜日

C++のご案内

このサイトではC++の解説を網羅していません。入門書的な役割すら果たしていません。いくらか、私が気の向いたトピックを書いただけであり、他にも重要な話題が沢山あります。
Webや書店を探せば入門的な内容は沢山あるので、探してみて下さい。
このサイトにもいくらかリンクを貼っておきます。

C++は、C言語をベースに構築されたプログラミング言語です。そのためC++の解説と言ってもC言語の理解を前提としている場合と、C言語すら知らない人のために書かれている場合のどちらもあり得ます。C++の解説だけ見ても意味が判らんわという人はC言語入門的な解説で基礎を固めるのが良いかも知れません。
また、C入門や、C++入門的な解説の中にも、プログラミング自体が初心者だという人に向けた解説と、プログラミング自体は歴戦の猛者だけどCやC++は初めてという人に向けた解説というのもあり得ますので、そこはご注意を。