【初心者歓迎】C/C++室 Ver.29【環境依存OK】
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
2006/07/08(土) 23:05:12ただしその場合、質問者は必ず、環境を書きましょう。
※sageは禁止です。
【前スレ】
【初心者歓迎】C/C++室 Ver.28【環境依存OK】
http://pc8.2ch.net/test/read.cgi/tech/1149815331/
【アップローダー】(質問が長い時はココ使うと便利)
http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/joyful.htm
0153デフォルトの名無しさん
2006/07/14(金) 20:25:37void call(Hoge& hoge, void (Hoge::*fn)(int, int, int)) {
ptr = hoge;
call(callEntry);
}
0154123
2006/07/14(金) 20:33:49それがですね・・・・
俺が買った入門書が、やっぱ駄目駄目なようで
ついでにSTLについての本も買ったんですが・・・・・
2つともハーバート・シルト著で[独習C++]と[STL標準講座]でっす!!
ただ、疑問に思うのは、独習C++もSTL標準講座も、本当に原著
通りのサンプルソースを載せてるのか?とも思う点です。
特に[STL標準講座]は、サンプルソースに間違いがあったり
<algorithm>のlower_bound()の解説が「一致する最初の要素を返す」
となってるけど、実際のreturn value は "greater than or equal"
だと、googleで検索してようやくわかったぐらいで、あとremove()とかも・・・
ま、結局思うのは、翻訳と監修してる人は、本当にちゃんと翻訳監修をしては
いないんだろうと、「わかんねーから省いちゃえ」ってな感じで翻訳監修作業を
してるんだろうと思うところです。
(しっかし、[STL標準講座]のソースは、一貫性がなさすぎて訳がわからん
あっちのソースではstd::cout文の後に"\n"つかって、こっちのソースではendl使って
キャストはc言語タイプのキャストしてるし、そりゃc言語タイプのキャストでも良いけど
こっちはc++勉強してんだからstatic_cast<>()使うのが筋ってなもんだろって思ったり・・・
入門書の内容を疑いながら読まなきゃならない入門書って、いったいなんなんだよ)
以上、独り言の愚痴でした
0155デフォルトの名無しさん
2006/07/14(金) 21:50:05さらに突っ込んだ内容は、もっと分厚い本を読んだけど。
あとなんか、図書館で買ったiostreamの本も役に立ったな。一冊丸ごとiostreamの本。
0156148
2006/07/14(金) 21:52:04インスタンスとメンバ関数で、staticなメンバ関数を作れるかとおもったら、そうもいかないみたいですね。
マルチスレッドは考慮しなくていいので、callの宣言がかわらないように、>>152さんの方法を書き換えて
使うことにします。ありがとうございました。
class A{
private:
static A *p;
static void (A::*p2)(int,int,int);
public:
void func2(int a,int b,int c){
cout << "func2(" << a << "," << b << "," << c << ")" << endl;
}
void callfunc(){
A::p=this;
A::p2=&A::func2;
call(&callfunc2);
}
static void callfunc2(int a,int b,int c){
(p->*p2)(a,b,c);
}
};
A *A::p;
void (A::*A::p2)(int,int,int);
0157デフォルトの名無しさん
2006/07/14(金) 21:58:160158デフォルトの名無しさん
2006/07/14(金) 22:12:05( ゚д゚)ポカーン
0159デフォルトの名無しさん
2006/07/14(金) 22:13:530160デフォルトの名無しさん
2006/07/14(金) 22:15:56>>150
callはそのままにせざるを得ないようだが。
0161デフォルトの名無しさん
2006/07/14(金) 22:37:03>渡すにはどうしたらいいのでしょうか。教えてください。
>callは、Cで書かれた別のライブラリの関数で、書き換えることができないんです。
CのライブラリにC++クラスのインスタンスを渡すのか?
無茶言うね。
というか
>void call(void(*)(int,int,int))
この関数の宣言を買えずに、どうやってインスタンスが渡せるんだ?
0162デフォルトの名無しさん
2006/07/14(金) 22:50:51C++の基本からやり直すべきじゃないかい?
0163148
2006/07/15(土) 01:06:55void glutMouseFunc(void (*func)(int button, int state, int x, int y));
みたいな形でコールバック関数を登録するようになっていて、そこにstaticでない
自作のメンバ関数を登録したかったのです。Cでオブジェクトの概念を使っている
gtkみたいに、インスタンスとメンバ関数ポインタをくっつけて、普通の関数ポインタとして、
渡したかったわけなのですが、綺麗に書く方法がないということは、
やはりちょっと無茶だったのかもしれません。
0164デフォルトの名無しさん
2006/07/15(土) 03:29:35K&R の原著と、その訳書の 石田晴久 の本との違いもそんな感じだよ
0165デフォルトの名無しさん
2006/07/15(土) 04:14:31GTKってこんな機能あったっけ?
GTKだって、シグナルコネクト関数でコールバック登録するときは、第一パラメータがwidgetのポインタだったと思うが。
インスタンスとコールバック関数をくっつけるのではなく、インスタンス(へのポインタ)とコールバックを、別々の引数と
して渡して、関連付けを行うんだと思ったが。
0166デフォルトの名無しさん
2006/07/15(土) 08:49:430167デフォルトの名無しさん
2006/07/15(土) 16:19:07test t=new test[4]; とかやるとコンストラクタがないというエラーになってしまいます。。
0168デフォルトの名無しさん
2006/07/15(土) 16:26:29のまちがいです
0169デフォルトの名無しさん
2006/07/15(土) 16:33:080170デフォルトの名無しさん
2006/07/15(土) 16:44:46いまのところできない。
169のようにポインタの配列を持つようにするか、std::vectorか何かを使うしかない。
0171デフォルトの名無しさん
2006/07/15(土) 16:45:19それだと delete[] が使えないね。まあ仕方ないだろうが
0172デフォルトの名無しさん
2006/07/15(土) 17:05:19std::uninitialized_fill( &p[0], &p[4], test("hoge") ) ;
0173デフォルトの名無しさん
2006/07/15(土) 20:21:16良いアイデアはないでしょうか?
0174デフォルトの名無しさん
2006/07/15(土) 20:34:470175デフォルトの名無しさん
2006/07/15(土) 20:46:52ポインタの配列か、vectorのどっちかを使おうとおもいます!!
0176デフォルトの名無しさん
2006/07/15(土) 20:53:030177173
2006/07/15(土) 21:42:25ネットでしばらく情報探してみましたが、他言語のreadlineがひっかかるようですので、
明日にでも書店・図書館で調べてみます。
ありがとうございました。
0178デフォルトの名無しさん
2006/07/15(土) 21:56:53開発環境は?
0179173
2006/07/15(土) 22:08:06これで答えになってますでしょうか?
0180デフォルトの名無しさん
2006/07/15(土) 23:30:06{
p = malloc(sizeof(int) * 10);
}
void kaihou(int *p)
0181180
2006/07/15(土) 23:31:290182デフォルトの名無しさん
2006/07/15(土) 23:34:24じゃここから落とせる。
ttp://jarp.does.notwork.org/win32/
凝ったことするんじゃなければ、readline.hをインクルードして
char *p;
p = readline("> ");
とかするだけでいい。
srcパッケージのほうにはmanファイルが入ってるかも(未確認)。
0183デフォルトの名無しさん
2006/07/16(日) 10:11:05class C_MAX_##TYPE \
この##って何?連結?
0184デフォルトの名無しさん
2006/07/16(日) 10:42:50プリプロセッサだけ走らせればわかるよ
あとは#で引数の文字列評価とか
0186デフォルトの名無しさん
2006/07/16(日) 11:31:580187173
2006/07/16(日) 13:20:17さっそくreadline-4.3-2-mingw32.zipの中身をコピーして試してみたのですが、
C:\(パス)\Temp/ccaYbaaa.o(.text+0x57c):command_test.c: undefined reference to `_imp__readline'
collect2: ld returned 1 exit status
という警告が出てしまいます。
おそらくどこかでreadlineの追加分の定義が必要なのかなとは思うのですが。。。
0188デフォルトの名無しさん
2006/07/16(日) 13:25:150189173
2006/07/16(日) 13:57:40gcc -lreadlineを試してみると、
/mingw/lib/libmingw32.a(main.o)(.text+0x106):main.c: undefined reference to `WinMain@16'
collect2: ld returned 1 exit status
とメッセージ内容は変わりましたが、やっぱり警告が出てしまいます。
0190デフォルトの名無しさん
2006/07/16(日) 14:03:39どんなコードをコンパイルしようとしてるの?
ちなみにhistoryも使える最小限のコードは以下。-lreadline付けてコンパイルしてみて。
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
int main()
{
char *p;
using_history();
while (1) {
p = readline("$ ");
add_history(p);
}
return 0;
}
0191173
2006/07/16(日) 14:20:02C:\(パス)\Temp/cckPaaaa.o(.text+0x39):test.c: undefined reference to `_imp__readline'
C:\(パス)\Temp/cckPaaaa.o(.text+0x49):test.c: undefined reference to `_imp__add_history'
collect2: ld returned 1 exit status
の警告が出ました。
ちなみにCの入門書を2冊やり終えたくらいのレベルです。
で、UNIXのコマンドラインのようなものを作ってみようとチャレンジ中だったのですが、
TAB補完と入力間違いしたときのBSで消すことを両方させるところで壁に当たってしまいました。
とりあえずTAB補完だけ・BSだけならgetcheやfgets,getcharあたりでできたのですが。
このレベルじゃまだしんどそうなら、さらに勉強してからチャレンジしてみます。
0192デフォルトの名無しさん
2006/07/16(日) 14:21:210193デフォルトの名無しさん
2006/07/16(日) 14:22:58readlineのlib*を他のライブラリが入ってるディレクトリにコピーしてみて。
0194デフォルトの名無しさん
2006/07/16(日) 14:23:14で、ライブラリがないと結局たいしたことはできないと。
0195デフォルトの名無しさん
2006/07/16(日) 14:29:13インストールできるんだけどね。
readlineもsrc packageならそうなってるかもしれん。
0196173
2006/07/16(日) 14:48:37bin,doc,include,libをそれぞれMinGW内の同じところへコピーしてみた
(し直してみた)けどダメでした。
さっきと同じエラー(でいいですよね?192さん)が出てしまいます。
これができたら、次はオライリーのC実践プログラミングで勉強しようと
思ってたのですが(評判よさそうなので)、ライブラリの勉強とでしたら
どちらが先の方がいいでしょうか?
0197デフォルトの名無しさん
2006/07/16(日) 14:55:13俺回線が細くて、今すぐMinGWインストールできないから、これ以上の
アドバイスは出来ん。
今すぐreadlineを使ったアプリを作りたいってわけじゃなさそうだから、
勉強のほうを進めれば?
0198デフォルトの名無しさん
2006/07/16(日) 14:55:550199173
2006/07/16(日) 15:01:44Cygwinは今いれると目標への熱意が冷めてしまいそうなので、今回の件を
ちゃんと理解できるようになってから試してみることにします。
たくさんのアドバイスありがとうございました。
0200デフォルトの名無しさん
2006/07/16(日) 17:33:51ディレクトリ構成
解凍パス/bin
解凍パス/doc
解凍パス/include
解凍パス/lib
解凍パス/test.c (>190さんのサンプル)
解凍パス/readline.dll (binから移動)
コンパイル
gcc -Iinclude -Llib test.c -lreadline
結果
問題無し。-lreadline をつける場所を間違えたんじゃね?
0201デフォルトの名無しさん
2006/07/16(日) 18:37:38typedef struct {
unsigned short file_type;
unsigned int file_size;
unsigned short reserved1;
unsigned short reserved2;
unsigned int offset;
}BmpFileHeader;
という、サイズが14バイトのつもりのヘッダ構造体を作ったのですが、
sizeof (BmpFileHeader);
としてやると16という値が出てしまいます。
何かプログラム間違ってるでしょうか?
0202デフォルトの名無しさん
2006/07/16(日) 18:39:050203デフォルトの名無しさん
2006/07/16(日) 18:43:33のコードの一部の引用です
#define OP_ASSERT(x) do { \
std::stringstream out_str; \
bool bTestOk = true; \
(x); \
if ( !bTestOk) std::cout << "Assertion failed: \n'" << #x << "'\n" <<
out_str.str() << std::endl; \
} while(0)
こういうマクロを見かけたんですがこのマクロはどうして
do { } while(0)
なんてことをしているのでしょうか?
単純に{ } とブロックで囲むのとはどこか違うのでしょうか?
そもそもどうしてブロックで囲んでいるのでしょうか?
0204デフォルトの名無しさん
2006/07/16(日) 18:49:00{} で囲むのは、中で使う変数のためのスコープを作るため。
do while(0) するのは、マクロ呼び出しの後のセミコロンを必須にするため。
0205デフォルトの名無しさん
2006/07/16(日) 18:56:36if (...) OP_ASSERT(...);
としたときのための深謀遠慮。
0207デフォルトの名無しさん
2006/07/16(日) 19:05:22もしWindowsならPlatform SDKのBITMAPFILEHEADERを使うべきだよ。
そうでないなら自分で定義するしかないけど。
0208203
2006/07/16(日) 19:19:47ちょっと理解するのに時間かかりそうです
>>204
変数のスコープ作成のためというのは理解できました
マクロ記述以前の部分で同名変数あったらまずいですものね
マクロ呼出し後のセミコロンを必須とするためというのも理解できました
文の最後に;がないのは気持ち悪いですものね
do {} while(0)で囲むことによって
OP_ASSERT(3)
とか;が抜かった場合ちゃんとコンパイルエラーになってくれますね
で、>>205が理解できてません
頭をひねっていますあと30分考えれば理解できるだろうか・・・やってみます
0209デフォルトの名無しさん
2006/07/16(日) 19:44:08{};
else{}
if()
do{}while(0);
else{}
上だとelseが浮いてエラーでしょ?
0211203
2006/07/16(日) 19:49:55やっと理解できました
if (...) OP_ASSERT(...);
else printf("else");
としたときにマクロをdo { } while (0) で囲ってないと
elseとifが対応しないというコンパイルエラーになるんですね
これで合ってますか?
0212203
2006/07/16(日) 20:02:24あ、先に答え書いてくれてたんですね。
ありがとうございます
ただ、どうしてdo {} while(0);だとコンパイルエラーにならないのかが
わかりません
if ()
{};
else{};
だと二行目の{};でif文の終わりと解釈されてエラー
if()
do{}while(0);
else{};
だと二行目は
if() 文;
else 文;
の形式として解釈されて問題なし
ということですかね
0213デフォルトの名無しさん
2006/07/16(日) 21:35:09virtual void Init();
};
class cData : public cBase {
void Init(){ /*初期化処理*/ };
};
main() {
static char *works=(char*)malloc(1000);
cData *data;
data=(cData*)&(works[50]);
data->Init();
}
こういった感じで別途確保した領域をクラスとして使いたいのですが、->Init()実行時にエラーが出てしまいます。
コンストラクタが実行されていない為に仮想関数のテーブルが作成されていない、と予想しているのですが、
この予想で正しいでしょうか。また、解決法はありますでしょうか。
知恵を貸してください。
0214デフォルトの名無しさん
2006/07/16(日) 21:44:43アラインメントの問題がなければ、<new>をインクルードして、
data = new(&works[50]) cData;などとする。
それで&works[50]にコンストラクタが呼ばれcDataのオブジェクトが作られる。
逆は、data->~cData();のように自分でデストラクタを呼んでからfree()すればよい。
0215デフォルトの名無しさん
2006/07/16(日) 22:04:150216デフォルトの名無しさん
2006/07/16(日) 22:11:56cData *data = new cData();
0217デフォルトの名無しさん
2006/07/16(日) 22:15:300218216
2006/07/16(日) 22:15:31+50 はアライメントの問題が発生しそうだな。
0219デフォルトの名無しさん
2006/07/16(日) 22:22:33ご教示いただけた手法で解決いたしました。
new の使い方や、ヘッダの存在自体しらなかったりと勉強不足を思い知らされました。
ありがとうございました。
data->cData();
これでコンストラクタが呼べても良いと思うんですけどねぇ・・
0220213,219
2006/07/16(日) 22:32:25+50は例としてあげるのは不味かったですね・・
実際はローカルなメモリ管理クラスが返す領域で、16byteにアラインが調整されています。
大人の事情というか、管理上の都合なんですがオーバーロードすると特定の領域からの
割り当てしか出来なくなってしまいそうなので今回は別の手段を、と考えました。
ありがとうございました。
0221デフォルトの名無しさん
2006/07/16(日) 22:37:40printf, puts, putcharやscanf, getcharの使い分けがよくわかりません。
1文字ならputchar, getcharが良いとか、
エスケープシーケンスを使うならprintf、使わないならputsが良いということでしょうか?
今まではprintfとscanfしか使っていなかったのですが、使い分けるべきでしょうか?
実行効率や、エラー時に違いがあるのでしょうか?
ご教授お願いします。
0222デフォルトの名無しさん
2006/07/16(日) 22:51:50効率は実装依存。
エラー時の違いはヘルプ読め。
0223デフォルトの名無しさん
2006/07/16(日) 22:55:10やっぱりprintfは書式文字の解釈をする分、
単純に文字列を書くだけなら余計な手間がかかることになる。
だから、どちらかというとputs/putcharで済むならそっちを使うと言う傾向にあることはある。
世の中、printfをputsやputcharに置き換えられるときには
置き換えるという最適化をする変わり者のコンパイラもあるけどね。
入力の方も事情は大体同じ。
ただしscanfはまともに使うのが恐ろしく面倒で、getsはまず間違いなく安全に使えない。
そこで、たとえばfgetsとsscanfを使う。
(getcharはOK)
0224デフォルトの名無しさん
2006/07/16(日) 23:04:32標準ライブラリ関数の最適化による挿げ替えをするのは変わり者なのですか?
それじゃ、最適化による関数のインライン展開は?
標準ライブラリ関数より高速な関数への挿げ替えは?
0225デフォルトの名無しさん
2006/07/16(日) 23:27:06変わり者で良いだろ
0226デフォルトの名無しさん
2006/07/16(日) 23:31:140227デフォルトの名無しさん
2006/07/16(日) 23:37:04よい意味で変わり者だと思う。
0228デフォルトの名無しさん
2006/07/17(月) 01:28:27#define PUTWS(wtes) (wprintf(L"%s\n", #wtes)
ってしようとすると、ポインタの型が合いませんって
コンパイラさんが怒ってます。
何かいい回避方法はないでしょうか?
0229デフォルトの名無しさん
2006/07/17(月) 01:33:110230228
2006/07/17(月) 01:41:41229さんありがとうございます。
#xxx
って、"xxx"に展開されるだけだったんですね。
勉強になりました。
0231228
2006/07/17(月) 01:56:38んで、
#define PUTWS(wtes); wprintf(L"%s\n", L ## #wtes);
としたら両方で解決しました。
んでは。
0232229
2006/07/17(月) 02:14:550233デフォルトの名無しさん
2006/07/17(月) 04:44:01iccもやるよ。MSもmemcpy()をインライン展開するくらいしたと思ったが。
0234デフォルトの名無しさん
2006/07/17(月) 12:05:04printfに渡されている文字列定数の中身までみるようなコンパイラはないだろ。
0235デフォルトの名無しさん
2006/07/17(月) 12:06:20VCもgccも文字列定数を見て型の不一致の警告を出したりしたと思ったが
0236デフォルトの名無しさん
2006/07/17(月) 12:18:22VC8だと出すんだな。
printfのようなものなんて久しく使ってないから気づかなかった。
0237デフォルトの名無しさん
2006/07/17(月) 12:18:52printf("%s\n", foo);をputs(foo);に置き換えるくらいは平気でやる。
printf("%c", '\n');がputchar('\n');に置き換えるくらいもやったと思った。
0238デフォルトの名無しさん
2006/07/17(月) 16:12:36int main(){
FILE *fp;
fp=fopen("test.txt","a+");
return 0;
}
このプログラムを実行してもtest.txtというファイルが作成されません。
何か勘違いがあるのでしょうか?
0239デフォルトの名無しさん
2006/07/17(月) 16:17:20戻り値調べて、ヌルが返ってきてたら perror() してみろ。
0240デフォルトの名無しさん
2006/07/17(月) 16:25:230242デフォルトの名無しさん
2006/07/17(月) 16:33:40理由はよくわかりませんがアドバイスをくださった皆さん、どうもありがとうございました。
0243デフォルトの名無しさん
2006/07/17(月) 16:37:35質問に便乗する形になってすまんが、誰か詳しく教えてくれんか?
0244デフォルトの名無しさん
2006/07/17(月) 16:41:24>>241
環境も何もわからんのにわかるかボケ。
0245デフォルトの名無しさん
2006/07/17(月) 16:58:01カレンディレクトリについて勉強して出直してこい。
0246笹井奈琴
2006/07/17(月) 18:44:36ttp://puchi15.hp.infoseek.co.jp/karen/karen3.html
こうですか?!わかりません!
0247デフォルトの名無しさん
2006/07/17(月) 19:39:430248デフォルトの名無しさん
2006/07/17(月) 21:34:33戻り値の型はintよりBOOLの方が真偽であると分かりいいと思うが、
<windows.h>をBOOL以外に使う必要が無い場合、
インクルードしたくない。boolはc++でしか使えない。
他にいい方法がありましたら教えてください。
0249デフォルトの名無しさん
2006/07/17(月) 21:40:370250デフォルトの名無しさん
2006/07/17(月) 21:44:49C99の<stdint.h>
0251デフォルトの名無しさん
2006/07/17(月) 21:45:07ある関数と、その関数から呼ばれた関数と、さらにその呼ばれた関数から呼ばれた関数と・・・
という関数群でのみ通用する、ローカル変数とグローバル変数の中間の変数みたいなものってありませんか?
何も考えずにグローバルに詰め込んでたら何がなんだかわからなくなってしまって・・・
0252デフォルトの名無しさん
2006/07/17(月) 21:47:29■ このスレッドは過去ログ倉庫に格納されています