【初心者歓迎】C/C++室 Ver.27【環境依存OK】
897 :
デフォルトの名無しさん:
クラス名・変数名に迷ったら書き込むスレ。Part7
http://pc8.2ch.net/test/read.cgi/tech/1144978008/369-376n から、スレ違いになりそうなので移動してきました。
>悪いことは言わん
>趣味(納期なし)ならもっと時間をかけて勉強しろ
>仕事(納期あり)なら先輩なり、同僚なりに聞け
>そして設計を含めて考え直せ
とおっしゃっていたので、何かヒントをいただけませんでしょうか。
ちなみにアマグラマです。
【開発環境】
C言語前提ですが、場合によってはC++でもOK。
開発環境はWin2000 + VS.NET 2003、ターゲットマシンもWin2000あたり。
なるべく環境依存にはしたくない。
【要求】
ユーザに、「処理」内容を選択させ、かつ複数の「パラメータ」の入力を求める必要がある。
「処理内容」は、1つの関数に相当する。
内部的には、どの関数を呼び出すかを選択させているのと同じ。
「パラメータ」は、「処理」に必要なデータである。
ただし、選択された「処理」内容によって、その「パラメータ」の扱い方が変わる。
具体的には、入力が必須だったり、無効だったり、空欄時はデフォルト値を使用したりする。
同じ「処理」内容でも「パラメータ」の有無によって該当する関数を変える可能性も考えられる。
898 :
デフォルトの名無しさん:2006/06/06(火) 08:00:38
【目的】
ユーザが選択したた「処理」により、実行する関数を変えるとき、
if (処理内容==処理1) Function01( 引数1, 引数2, 引数3 ) ;
のような条件分岐を何十個も並べるのは、あまり良くないのでは?と考えた。
ゆえに、もっとスマートな方法(for文で一括処理とか)で記述したい。
【自分の考え】
以下のような構造体を配列として用意した。
struct
{
関数ポインタ
パラメータ1の扱い方(enum)
パラメータ2の扱い方(enum)
パラメータ3の扱い方(enum)
}
「パラメータ」の扱い方について、内部で保持しておきたい。
enumで保持しておけば「パラメータ」の入力状態によって内部で関数を切り替えることができるはず。
関数ポインタと併用すれば、for文などで一括的な処理が出来るのでは?と考えた。
また、「パラメータ」の扱い方を予め内部で持っておくことにより
ユーザインターフェイスに反映させたり、「処理」の各関数を呼び出す前に「パラメータ」チェックが出来ると考えた。
899 :
886:2006/06/06(火) 08:21:32
>>887 >>888 >>896 ありがとうございます。
確かに、計測もせず fwrite を繰り返すとパフォーマンスが下がると思い込んでいた点で、
>>887 の言うとおりでした。
バイナリで吐き出す件は大丈夫です。
>>897 具体性がなさ過ぎて、何をやりたいんだかよく分からんが
・パラメータの数が3個限定で
・パラメータの型が全ての処理で共通で
・パラメータの条件がenumで記述可能(値の範囲指定などが必要ない)
のならば、それでいいんじゃないの。
ただ、
> 空欄時はデフォルト値を使用したりする。
このデフォルト値はどこに保持しているんだ?
> enumで保持しておけば「パラメータ」の入力状態によって内部で関数を切り替えることができるはず。
enumで保持しておくことと、処理関数を切り替えることは全く関係ない気がするぞ?
901 :
897:2006/06/06(火) 08:54:07
>>900さん
レスありがとうございます。
>・パラメータの数が3個限定で
>・パラメータの型が全ての処理で共通で
>・パラメータの条件がenumで記述可能(値の範囲指定などが必要ない)
これは大丈夫。
>デフォルト値
外部ファイル……と言いたいところですが、
面倒だし呼び出された関数の内部でいいかな〜とか思ってる自分が。
>enumで保持しておくことと、処理関数を切り替えることは全く関係ない
ユーザの入力(1)
処理:Hoge / パラメータ1:(空欄) / パラメータ2:foo
処理:Hoge / パラメータ1:bar / パラメータ2:foo
という2つのパターンがあったとして、
FunctionHoge01 パラメータ1:不要 パラメータ2:必要 ← パターン1で呼び出される関数
FunctionHoge02 パラメータ1:必要 パラメータ2:不要 ← パターン2で呼び出される関数
と、切り替えられたらいいなと思いました。
まあ、呼び出された関数の中で条件分岐すればいいのですが……。
誤植発見。
2番目の入力のパラメータ2は「空欄」です。
(誤)
ユーザの入力(1)
処理:Hoge / パラメータ1:(空欄) / パラメータ2:foo
処理:Hoge / パラメータ1:bar / パラメータ2:foo
(正)
ユーザの入力(1)
パターン1 処理:Hoge / パラメータ1:(空欄) / パラメータ2:foo
パターン2 処理:Hoge / パラメータ1:bar / パラメータ2:(空欄)
>>897 > 悪いことは言わん
> 趣味(納期なし)ならもっと時間をかけて勉強しろ
> 仕事(納期あり)なら先輩なり、同僚なりに聞け
> そして設計を含めて考え直せ
まあ拡張性や汎用性を犠牲にした上で、
C++を使わずに実装するなら最良の選択肢だとは思うけどな。
>>901 つまりC++で言う関数オーバーロードのようなことがしたいわけね。
そもそも設計が間違っているのかどうかは、何に使うか分からない以上何とも言えないが、
その形で実装するなら、デフォルト値の扱いにはルールを設けるのを忘れずに。
例えば
FunctionHoge01 パラメータ1:必要 パラメータ2:省略時はデフォルト値
FunctionHoge02 パラメータ1:必要 パラメータ2:不要
という2パターンがあったとして、
ユーザーの入力が
処理:Hoge / パラメータ1:bar / パラメータ2:(入力なし)
だったら、Hoge01かHoge02、どちらも選べる可能性がある。
C++のコンパイラなら「曖昧です」でエラーを出すところだが、
実行時に曖昧になったんじゃどうしようもないから、
入力なしは「不要」とマッチさせるか、「可能であればデフォルト値のもの」とマッチさせるか決めないと。
>>897 そんなに悪くないからとりあえずそれでやってみればいいよ
やってみたら変なとこ出てくるかもしれないし
907 :
880:2006/06/06(火) 15:04:31
>>883 ソースがあるなら、jpeg_set_colorspace の中見てみてください。
JCS_YCbCrのトコで 4:1:1 にセットしてるんで、
これ呼んだ後にでも
cinfo->comp[0].h_sample_factor = cinfo->comp[0].v_sample_factor = 1;
とかすると良いと思います。
>>885さん、ありがとうございました。
配列の外側を参照してしまうためにエラーが起きてたわけですね。
909 :
デフォルトの名無しさん:2006/06/06(火) 17:21:35
質問です。
XPでVC++.NETを使ってます。
ソケットを使ってWebの情報を読むプログラムを作ろうとしているのですが、
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
MessageBox(hParent, "WSAStartupエラー", "error", MB_OK);
return -1;
}
wsprintf(szStr, "wsagetlasterror:%d", WSAGetLastError());
MessageBox(hParent, szStr, "message", MB_OK);
s = socket(AF_INET, SOCK_STREAM, 0);
if (s == INVALID_SOCKET) {
wsprintf(szStr, "ソケットオープンエラー,error:%d", WSAGetLastError());
MessageBox(hParent, szStr, "error", MB_OK);
WSACleanup();
return -2;
}
のMessageBoxで出る1回目の値は0ですが、
2回目(for文)は0、次に10093と出てエラーとなってしまいます。
エラー検索をすると
「アプリケーションが WSAStartup を呼び出していないか、または WSAStartup が失敗しました。」
と出ていますが、WSAStartupは呼び出しているし、エラーは出ていないので困っています。
どなたか解決策をお願いします。
>>909 > 2回目(for文)は
提示されたソースのどこにfor()文があるのかと(ry
# 提示したソース全体をfor()文で回している、
# と言うオチではなかろうな?
開けたら閉めましょう。
912 :
909:2006/06/06(火) 17:57:41
>>910 LRESULT CALLBACK DlgProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
の
switch (msg)のcase内にfor文がありその中で呼び出しています。
>>911 実際には下のほうにこれがあります。
closesocket(s);
WSACleanup();
return nTotal;
}
913 :
880:2006/06/06(火) 18:06:33
>>909 どのメッセージボックスがそのメッセージ出してるのかわかりますか(キャプションは何)?
エラーじゃないのに WSAGetLastError を呼び出して、変な数が帰ってきてるとか
いってるわけじゃないですよね。
WSAGetLastError は、直前のエラーのエラーコードを返すわけで、
エラーが無かったときの挙動は定義されていないと思いますよ。
(ちなみに年に1回くらい GetLastError で同じ質問する人もいます)
914 :
909:2006/06/06(火) 18:39:33
>>913 1回目
messageで、wsagetlasterror:0
2回目
messageで、wsagetlasterror:0
errorで、ソケットオープンエラー,error:10093
です。
ソケットが開けないのでエラーだと思うのですが…?
そもそもWSAStartup/WSACleanupなんてそんな頻繁に呼ぶものではないだろ。
普通プログラムの開始・終了時に1度だけ呼ぶものではないか。
916 :
909:2006/06/06(火) 19:11:01
>>915 その通りにしたら読み込めました。
ありがとうございました。
時々見るのですが、
printf("そんな長くない文章\n");
printf("やっぱ長くない文章2\n");
と呼ぶのはなんのためでしょうか。
918 :
897:2006/06/06(火) 20:17:02
返信ありがとうございます。
>>904 今からC++に変更しても、ぶっちゃけ問題なかったりはするんですけどね(笑)
自分がやりたいのは、
>>905さんもおっしゃっている通り、C++で言う関数のオーバーロードっぽいものです。
ただ、あくまでも実行時に解釈するので、C++のオーバーロードとは少しニュアンスが違うかもしれませんね。
>>905 はい、問題ありません。
どっちにするかはまだ決めてませんけど。
>>906 とりあえずこのままやってみることにします。
設計の難しさをほんの少しだけ知ったような気がします……。
>917
「文字列の長さが1GBとかじゃなくて普段良く使う程度の長さの文章だよ」
「上のと内容が異なるけど長さ的には同じくらいだよ」
というのを暗示したいのではなかろうか。
>>919 なるほどサンクス 何度も関数を呼ぶ意味がワカランかった
>>917って
printf("hoge\nhage\n");じゃなくて2行に分けるのは何でって事?
それだったら単に出力時の見た目とコード上の見た目を合わせるためだと思われ
922 :
デフォルトの名無しさん:2006/06/06(火) 21:18:04
#include<stdio.h>
class Object
{
float px,py;
public:
Object(int x,int y){px=x;py=y;}
void Draw(void){printf("X座標=%d\nY座標=%d\n",px,py);}
};
int main(void)
{
Object ufo(2,4);
ufo.Draw();
return 0;
}
なんか数値がおかしいのですが、どこが悪いのでしょうか
-void Draw(void){printf("X座標=%d\nY座標=%d\n",px,py);}
+void Draw(void){printf("X座標=%f\nY座標=%f\n",px,py);}
924 :
922:2006/06/06(火) 21:32:19
>>923 どういうことですか?試しにそのようにコードを修正してみましたが、エラーが出ます
>921
でもそれだと
printf(
"一行目の文章\n"
"二行目の文章\n");
で事足りるし。
コピペしやすいからに決まってるじゃないか
>924
floatを%d(10進整数)で出力しようとするなってこと。
手元の環境(Win2k, BCC5.5)じゃ
X座標=2.000000
Y座標=4.000000
のように出力されたけど?
929 :
922:2006/06/06(火) 21:42:46
>927
あ、コンパイルできました。+とか-とかはいらなかったんですね
どうもありがとうございました
>>929 じゃもう1個指摘
-#include<stdio.h>
+#include<cstdio>
+using namespace std;
922は古い書き方で最近の環境では通らなかったりする
それと
Object(int x,int y){px=x;py=y;}
のx,yの型とpx,pyの型は揃えなくて良いの?
>922は古い書き方で最近の環境では通らなかったりする
そんな環境あるの?
最新のC++規格にも<stdio.h>はあると思うんだが。
932 :
930:2006/06/06(火) 22:22:35
質問です。XPで.NET Framework SDKのコンパイラ使ってます。
#include <stdio.h>
int main(void)
{
char input_data[10];
do {
fgets(input_data, sizeof(input_data), stdin);
input_dataに入ってる文字列を処理
} while(条件);
return 0;
}
fgetsでデータを入力したいのですが、この場合もし10文字以上入力されるとエラーになって
強制終了されてしまいます。
用意した配列の大きさより大きい文字列が打ち込まれた場合の対処はどうしたらいいのでしょうか。
>>933 fgets() にはバッファのサイズを渡してるから、強制終了はしないはず。
その後の処理のほうが間違ってるんだろ。
Ctrl + Z で逃げるような話?
とりあえずfgetsの戻り値ぐらいは確認しとくべきちゃうか。
937 :
933:2006/06/07(水) 08:39:15
あ、すみません、強制終了するのは後の処理が間違っていました。
強制終了ではなくて、配列内に収まりきらなかった分が、doループで次回のfgetsが来た時に
読み込まれてしまうのを防ぎたいのですが、どうすればよいのでしょうか。
>>937 fgetsで'\n'を読めなかったことを確認したら、'\n'までgetcharで読み捨てれば良い。
939 :
933:2006/06/07(水) 09:39:15
>>938 ああー、なるほど。ありがとうございました。
すいません簡単な質問です
effectiveC++読んでる途中ですが
using namespace std;をあえて使わず
std::・・・と文法上つかってますが
using namespace std;に甘えない方が
良いのでしょうか。
(読んでる途中なので最後まで読めと言われれば
そうなんですけど)
あと、「std::stringなどは継承するな」って書いてあったの
ですが、本当にそんなトリッキーな事する奴いるんでしょうか・・・
(居たから書いてるんだろうな)
941 :
デフォルトの名無しさん:2006/06/07(水) 14:25:25
初歩の質問です。
std::stringの文字列をconst char *(またはchar *)にキャストしたいのですが、
dynamic_cast,static_cast,reinterpret_cast,const_castのいずれもダメです。
どうすればキャストできますか。
プログラム自体はキャストしなくても、最初からconst char*の文字列に
しとけばいいんですが、どうも気になって、、、
942 :
よろしくお願いします:2006/06/07(水) 14:26:29
http://www.geocities.jp/hideohara777/tec/sort2.html をC++(cin coutを使う)に直す宿題が出ましたが、自分で直してみましたがどこが悪いのかが解りません。
どなたか直してくれる方はいらっしゃいますか?(↓自分で直したがエラー続発)
#include <iostream>
void main(void)
{
int a[5]={9,5,7,2,1};
int b, i ,j, k;
cout <<"ソートするデータ" ;
for ( k=0; k<5; k++ )cout << "" << a[k] );
cout << "\n" ;
cout << "\n" ;
for ( i=0; i<4; i++ )
{
for ( j=i+1; j<5; j++ )
{
if ( a[i]>a[j] )
{
b = a[i];
a[i]=a[j];
a[j]=b;}
}
}
cout << "ソート結果\n" ;
for ( k=0; k<5; k++ )cout << "%d ", a[k] ;
cout << "\n";
}
945 :
デフォルトの名無しさん:2006/06/07(水) 14:36:18
943>
944>
早い、速いッスよ。
俺も早くあんたらのようになって、この板を
sageてみせるよ、ありがとう。
947 :
271:2006/06/07(水) 14:43:00
>>946様 どちらに書こうか迷いましたが、このスレの初心者歓迎の文句に魅かれてしまいました。
宿題のサイトにはご迷惑をおかけしたので、ここで質問した所存であります。
void main(void) の前に
using namespace std;
を追加して、
これと⇒ for ( k=0; k<5; k++ )cout << "" << a[k] );
これを⇒ for ( k=0; k<5; k++ )cout << "%d ", a[k] ;
こうすれば動くんじゃない? ⇒ for ( k=0; k<5; k++ ) cout << " " << a[k] ;
>宿題のサイトにはご迷惑をおかけしたので、ここで質問した所存であります。
宿題やってくれっていうのは「C/C++ に関する質問」じゃないというのはわかりますか?
「車の整備についての質問(初心者歓迎)っていうスレ」があったとして、
「車の調子悪いが自分では整備できないから誰か整備して」
なんて書くのはスレ違いでしょ。
>>940 >using namespace std;に甘えない方が
>良いのでしょうか。
良い
これはコンパイラのバグまで絡んでくるのでやっかい
要約すると、
ヘッダでは使うな。ただし関数内では思う存分使ってよい。
>std::stringなどは継承するな」って書いてあったの
>ですが、本当にそんなトリッキーな事する奴いるんでしょうか
template typedefがないのでそういう状況も出てくる
まあ分からないならやらない方がいい
>>948 その通りです。またご迷惑をおかけしました。
951 :
デフォルトの名無しさん:2006/06/07(水) 17:18:08
gcc + linux でプログラムを作っているのですが、
ファイルのコピーの命令が見当たりません。
Windows なら、CopyFile というのがあるのですが、
Linux ではどうやって書くのか教えてください。
952 :
sage:2006/06/07(水) 17:34:15
>>951 Pythonのソース見たら、普通にファイル開いて、しこしこ書き込んでた。
便利なやつがあればと思ったけど、自作しないといけないんだな。
>>951 Linuxのことはあまりしらないけど、
C++でもいいなら、boost::filesystem::copy_fileがあるよ。
手っ取り早くやるならUNIXコマンド直接起動で
system("cp 元 先");
でいいんじゃね。移植性は皆無だが。
どうせ、自前でコーディングしないのであれば
標準で用意されてない以上移植性は期待で着ない。
956 :
デフォルトの名無しさん:2006/06/07(水) 21:58:23
#include <stadio.h>
main () {
printf("C programming");
return 0;
}
というプログラムを書いてコンパイルしようとしたら
エラー E2209 sample.c 1: インクルードファイル 'stadio.h' をオープンできない
警告 W8065 sample.c 4: プロトタイプ宣言のない関数 'printf' の呼び出し(関数 main
)
と表示されました。「オープンできない」 「プロトタイプ宣言のない」とはどういうことですか?
>>956 見たまんまの意味だな。もっとエラーメッセージを理解する努力をしよう。
>>956 ・オープンできない
綴りが間違ってるからね。ファイルが無いから。
・プロトタイプ宣言のない
printf関数はstudio.hに入っているので。
なんの前触れも無く、コンパイラが『printf』なんて見つけても、 何なんだよ、printfって てな事になる。
960 :
959:2006/06/07(水) 22:14:37
うほっ 間違えた。
stdio.hね。
ちなみにstdioは、『スタンダード アイ/オー』ね。
961 :
デフォルトの名無しさん:2006/06/07(水) 22:23:49
ありがとうございます。綴りを直したんですが今度はこのメッセージが出ました。
認識されいないと出ているんですが操作可能にするにはどうすれば?
C:\source>bcc32.sample.c
'bcc32.sample.c' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
×bcc32.sample.c
○bcc32 sample.c
というかもうちょっと考えてから人に聞こう
965 :
デフォルトの名無しさん:2006/06/07(水) 23:40:29
map< int , Object* > objectMap;
objectMap.insert( pair< int , Object* >( 1 , new Object ) );
objectIterator = objectMap.find( 1 );
objectMap.erase( objectIterator );
こんな感じのソースを書いてしまったんですが、
やっぱり .erase を使うだけではオブジェクトの実体(メモリ)は開放されないですか?
967 :
デフォルトの名無しさん:2006/06/08(木) 00:02:24
#include <stdio.h>
main () {
printf("C programming");
return 0;
}
綴りを直しても
エラー E2209 sample.c 1: インクルードファイル 'stdio.h' をオープンできない
警告 W8065 sample.c 4: プロトタイプ宣言のない関数 'printf' の呼び出し(関数 main
)
のままでした
969 :
デフォルトの名無しさん:2006/06/08(木) 02:05:38
エラー E2209 test.c 1: インクルードファイル 'stdio.h' をオープンできない
ゼロから始めた者ですが↑のようなエラーが出て先へ進めません。どうしたらよいですか?
どうせbcc32.cfgでインクルードパス指定するの忘れてるってオチだろ
setbccでぐぐれ
972 :
デフォルトの名無しさん:2006/06/08(木) 03:42:42
数式を与えたら、それを解釈して木構造を構築するようにしたいのですが・・
( (1)+((2+3))*(6*(8)) ) のように無駄に括弧が入りまくってても大丈夫なヤツ
を早急に作らないといけないんです。助けてください
>972
boost::spirit
つってもコンパイラに依存するけど
974 :
972:2006/06/08(木) 06:46:17
>973
boost::spirit について少し調べてみます。
というか、自力で作りました。すいません。
VC++6.0を使っているのですが、
ローカル定義のシンボル "_malloc" がインポートされました
というwarningがでます。
warningの内容の意味が理解できないので、これがどれくらい良くないことなのか
さっぱり分かりません。
どういう意味なのでしょうか?
976 :
デフォルトの名無しさん:2006/06/09(金) 01:49:21
test1ではsmemの値は7FFDF000で,
このアドレスには"テスト"の文字列が格納されてました。
がしかしtest2でのdmemの値は00913424だったのですが
このアドレスにはよくわからないデータしかなく,
"テスト"の文字列はその周辺にも見あたりませんでした。
dmemは何を指してるのでしょうか。。
int test1()
{
char* smem;
strcpy(smem, "テスト");
printf("%p",smem);
return 0;
}
int test2()
{
char* dmem = new char[8];
strcpy(dmem, "テスト");
printf("%p",dmem);
delete[] dmem;
return 0;
}
いやむしろsmemはどこを指しているのさ
strcpyの書き込む先は?
すいません、Cで画像や音声を読み込んで表示したいのですが、
fopenでよいのでしょうか?
うん
サンクス
音声を表示するのか?
いや音声は表示しなくていいです。
えーと、fopenでファイルを開いて、関数に代入すればいいんですよね?
そこから先どうすればよろしいんでしょうか
>fopenでファイルを開いて、関数に代入
なんてすばらしい言語なんだろう。
画像や音声の扱いはそんな単純じゃないよ
ぐぐるか本買うかしてしっかり勉強すべき。
それ以上はそっちの環境がわかんないと何も言えない
まずはこっちを埋めようぜ?
最近、std::tr1ていう名前空間をよくみかけるようになたんだけど
お姉さま、あれは何ですの?
ume
990
埋め
梅
993
994 :
994:2006/06/11(日) 18:07:11
うめお
997
998
999 :
デフォルトの名無しさん:2006/06/11(日) 18:10:10
↓1000おめでとう
1000
1001 :
1001:
このスレッドは1000を超えました。
もう書けないので、新しいスレッドを立ててくださいです。。。