スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

かつて戦ったバグ 6

久しぶりにプログラミングでの失敗談を書いてみる。

で、includeの時などに使う くの字型のカッコは、どうやらくっつけて書くと
文字色の指定などを行うタグの一種として判別され表示がおかしくなる為、
両サイドに半角の空白を入れてます。

【例】#include< stdio.h >
('s'の左と、'h'の右)

【バグNO.16】STL (vector)
w-------ww-------ww-------w概略コードw-------ww-------ww-------w

#include< vector >
#include< stdio.h >
int main(void){
vector< int > test;
for(int i = 0; i < 5; i++)
test.push_back(i);

for(int i = 0; i < 5; i++)
printf("test[%d] = %d\n", i, test[i]);
}
w-------ww-------ww-------w概略コードw-------ww-------ww-------w
初めてvectorを使ってみたというプログラムです。
しかし実行しようとすると、
「 'vector' : 定義されていない識別子です。」みたいなエラーがでます。

何でかというと、using宣言を忘れてるからです。

using宣言と言うのは、
スコープ解決演算子(::)を使わずに、アクセス出来るようにするものです。
STLはstd名前空間に含まれる ので、

最初に、
using namespace std;
と記述する必要があります。


#include< vector >
#include< stdio.h >
using namespace std;

int main(void){
vector< int > test;
for(int i = 0; i < 5; i++)
test.push_back(i);

for(int i = 0; i < 5; i++)
printf("test[%d] = %d\n", i, test[i]);
}



もしくは、vectorの部分を、スコープ解決演算子を使って
std::vectorという風にしてもOKです。
(タイプ数が多くなるので、 自分はusing宣言を使ってます。

STLは、単純にヘッダをインクルードするだけで使おうとするとエラーになるので、
初めて使おうとした際に、
using宣言スコープ解決演算子を書き忘れてエラーを出した人は
それなりに居るんじゃないかと思う。
(自分だけかもしれない)


【バグNO.17】STL (string)
w-------ww-------ww-------w概略コードw-------ww-------ww-------w

#include< string >
using namespace std;

int main(void){
string test;
test = "Hello string!!";
printf("%s\n", test);

return(0);
}

【実行結果】
(NULL)

w-------ww-------ww-------w概略コードw-------ww-------ww-------w

今度はSTLのstringを使おうとした例です。
(文字列を簡単に代入できたり、比較できたりします。)

で、文字列を表示させようとしてみると、 実行結果は(NULL)。
「こんにちは」と挨拶したのに(NULL)とは何事か!!
と、憤慨していたところ、

表示する際には
メンバ関数であるc_str()を使わなければならない事が発覚。

なので、printf関数の部分を下記の様に修正したところ、無事表示されました。
printf("%s", test.c_str());

仕様を理解していないまま使おうとすると、大抵ロクでもない事が起こる例でした。


【バグNO.18】 文字列を判別してくれない
w-------ww-------ww-------w概略コードw-------ww-------ww-------w

char str[][25] = { "Frame",
"FrameTransformMatrix",
"Vertex"
"MeshNormals",
};
int flag;
char tstr[100] = "";

while(fscanf(fp, "%s", tstr) != EOF){
flag = -1;
for(int i = 0, count = sizeof(str) / sizeof(str[0]); i < count; i++){
if(strcmp(tstr, str[i]) == 0){
flag = i;
break;
}
}
switch(flag){
case 0: LoadFrame();break;
case 1: LoadMatrix();break;
case 2: LoadVertex();break;
case 3: LoadNormals();break;
default: break;
}
}


w-------ww-------ww-------w概略コードw-------ww-------ww-------w

これは、Xファイルのキーワードがあれば、
そのキーワードに応じた関数を呼び出すプログラムです。

ですが、テキストファイルに"Vertex"とか"MeshNormals"とか書いても、
LoadVertex()や、LoadNormals()の関数は実行されなかったんです。

調べてみたところ、
キーワードが一致した時点で flagに2や3が入り、
for文をbreak;で抜けるようになっているのですが、
"Vertex"と"MeshNormals"を読み込んだ時のflagは-1でした。

つまり、「キーワードと一致していない」と判断されてしまったんです。
もちろん、テキストファイルの方につづりミスなんかはありません。


原因は分かるでしょうか?
(自分はコレで散々な目に遭いました。


では答えです。



コンマが無い。


char型の2次元配列strを見てください。
"Vertex"の後にコンマが無いんです。

正しくはこうです。↓(赤字の部分に注目)

char str[][25] = { "Frame",
"FrameTransformMatrix",
"Vertex",
"MeshNormals",
};



「コンマが無い場合、何が起こっていたか?」というと、
文字列が連結されていたのです。

連続した文字列リテラルは、コンパイル時に連結される んですよ。

例えば下記の場合は
------------------------------------------------------
char test[] = "banana" "mikan";
------------------------------------------------------
testが"bananamikan"になります。くっつくんです。


同じように、2次元配列strも連結され、

char str[][25] = { "Frame",
"FrameTransformMatrix",
"VertexMeshNormals"
};


↑このようになっていたのです。

テキストファイルに、"VertexMeshNormals"なんていうキーワードは当然 存在しない ため、
「キーワードと一致した」とは判断されなかったわけです。

コンマ一つにここまで悩まされるとは・・・。
ちくしょう。
スポンサーサイト

テーマ : 日記 - ジャンル : 日記

コメント

No title

個人的にはusing namespaceの記述は嫌いです(^_^;)

コーディング量は増えますが、省かない方がどの名前空間のクラスを使用しているかが一目瞭然なので、デバッグの際に解析速度の向上に繋がると思うんですよね。

まぁ、この辺りは好みの問題だとは思いますが…

No title

あと、STLを利用するならば、printf関数よりもstd::coutを使用した方がらしいですよ。

std::string str("こんにちは");
std::cout << str << std::endl;

こんな感じかな?
慣れるまでは使いづらいかもしれませんけどね(苦笑)

No title

なるほどーv-293

たしかusing指令なんかはを使いどころを誤ると、気付きにくいエラーとか出たりするんですよねv-292
うーんどうしよう。

タイプ量は増えますが、その時々で明示的に示してやった方がいいかもしれませんね。v-293

そういえば、似たような機能で
VBのwithステートメントとかは使わないようにしていました。
(ドット演算子から書き始めるのが、なんか きもちわるかった

----------------------------------------------------------
サンプルコード見ても分かりますが、自分は未だにprintf関数ですね。e-260
coutの方が、 書式指定の対応関係ミス
例 printf("%cです。");
も無くなるので、そろそろ移行しようと頑張ってみますv-293
(慣れた関数から変更するのを面倒くさがってました)
コメントの投稿
管理者にだけ表示を許可する



上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。