トップページ⇒tech
1001コメント289KB

【初心者歓迎】C/C++室 Ver.26【環境依存OK】

レス数が900を超えています。1000を超えると表示できなくなるよ。
0001デフォルトの名無しさん2006/03/29(水) 11:59:26
エスケープシーケンスやWin32APIなどの環境依存な物でもOK。
ただしその場合、質問者は必ず、環境を書きましょう。
※sageは禁止です。
【前スレ】
【初心者歓迎】C/C++室 Ver.25【環境依存OK】
http://pc8.2ch.net/test/read.cgi/tech/1140963340/l50
【アップローダー】(質問が長い時はココ使うと便利)
http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/joyful.htm
0809デフォルトの名無しさん2006/05/05(金) 15:42:21
>>808
言語について書かれてある本ならば問題ない
開発環境について書かれてあるならば
その内容は古くなってるかもわからんね
0810デフォルトの名無しさん2006/05/05(金) 15:55:19
そういえば、自分の経験からいくと、
「Visual C++入門」だとか、「C++ Builder入門」だとか、
ある特定の開発環境に限定した書籍で、良書を見たことがないのだが。

言語の解説はいまいち、開発環境の使い方の解説もいまいちといった、
中途半端な本ばかりだという印象がある。
0811デフォルトの名無しさん2006/05/05(金) 15:58:34
>>809,810
ありがとうございます。
まずは図書館で、言語についての本を借りてこようと思います。
0812デフォルトの名無しさん2006/05/05(金) 16:03:32
まぁ入門書はあくまでも入門書だからな
0813デフォルトの名無しさん2006/05/05(金) 16:26:37
>>802
cout の方でも abc に相当するポインタを作って
使うわけにはいかないの?
0814デフォルトの名無しさん2006/05/05(金) 18:04:23
>>806
>>http://pc8.2ch.net/test/read.cgi/tech/1146323457/187
0815デフォルトの名無しさん2006/05/05(金) 19:22:31
ファイルサイズを得るにはどうすればいいんでしょう?
0816デフォルトの名無しさん2006/05/05(金) 19:24:02
fseek,ftell
0817デフォルトの名無しさん2006/05/05(金) 19:26:10
なるほど
0818デフォルトの名無しさん2006/05/05(金) 19:45:34
>>815
環境依存しない完璧な手段はない。
例えばsize_tが4バイトの環境で2GB以下のファイルで、ファイルシステムがサイズに関して小細工しない場合に限り、>816でできるかもしれない。
0819デフォルトの名無しさん2006/05/05(金) 20:40:27
>>818
どうもご親切に。
0820デフォルトの名無しさん2006/05/05(金) 20:41:23
バイナリデータを格納する場合はcharの配列に入れた方がいいのかな?
0821デフォルトの名無しさん2006/05/05(金) 20:54:20
お好きなように
0822デフォルトの名無しさん2006/05/05(金) 21:11:00
fstreamのオブジェクトからバイナリデータをmemcpyする事ってできる?
0823デフォルトの名無しさん2006/05/05(金) 21:45:37
自作ソフトが作りたくてVC#expressを入れたんだけど、
これってどうやってexe作るの?
[ビルド]→[newPgの発行]でひたすらOK押していったら、setup.exeってのが出来たんだけど
インストールしたりレジストリ弄ったりしちゃうんだけど…
ふっつーのVectorで配布してるようなの作る方法教えてー
08248232006/05/05(金) 21:46:44
てか今更だけどC#ってスレ違いだったり…?
0825デフォルトの名無しさん2006/05/05(金) 21:50:14
バイナリはヘキサにして%02Xにして保管しとくと後々読み出すとき楽だよ
文字列から数字へがatoi以外知らないから、自分の場合ファイルに保管するけど、
例えば
char* a="あいうえお";
FILE *p;
p=fopen("ドライブ:/path","a");
fprintf(p,"%02X",a);
fclose(p);
わざわざファイルに保管しなくとも、文字列をヘキサなど数字で保管できる関数ややり方があれば便利だなと思うんだけど。
0826デフォルトの名無しさん2006/05/05(金) 22:15:52
>>822
memcpyなんぞいらん。fstreamからrdbuf()->sgetn()使え。
0827デフォルトの名無しさん2006/05/05(金) 22:25:03
>>823
ビデオの再生ボタンみたいなのを押すと幸せになれるよ
0828デフォルトの名無しさん2006/05/05(金) 22:34:40
>>827
ちょっとだけ幸せは得ましたが、自分だけの幸せで終わりそうです。
みんなが幸せになるにはどうすれば…?
08298252006/05/05(金) 23:37:38
ゴメン。825じゃだめだ。
char* a="あいうえお";
unsigned int i=0;
FILE *p;
printf("%d",strlen(a)-1);
p=fopen("ドライブ:/パス","a");
for(i=0;i<strlen(a);i++){
fprintf(p,"%04x",a);a++;}
fclose(p);
です、ヘキサ保存。
0830デフォルトの名無しさん2006/05/05(金) 23:43:01
よりによってO(n²)かよ
08318252006/05/06(土) 00:00:35
もう一箇所
a++;ではなく、a=a+2;
0832デフォルトの名無しさん2006/05/06(土) 00:17:34
・DLL
・上記DLLをロードするプログラム
って、両方ともコンパイラは同種にしないとだめですか?
それとも両者(DLL、プログラム)がANSI-C準拠のコードであれば問題なし?
0833デフォルトの名無しさん2006/05/06(土) 00:38:56
>>826
ありがとうございます。
0834デフォルトの名無しさん2006/05/06(土) 00:43:49
>>832
そもそもDLL自体、ANSI Cの規格ではない。
あとはわかるな?
08358322006/05/06(土) 01:42:15
>>834
「あとはわかるな?」と言われても、どうとでも解釈できるような。
都合の良いように解釈すると、「コードの内容に関係なく、
MS固有仕様をサポートしているコンパイラであれば、組み合わせは何でもあり」ってことですか?
0836デフォルトの名無しさん2006/05/06(土) 02:10:21
>>835
うんにゃ、俺は別に>>834ではないが、そもそもdllやexeを
作るのはコンパイラじゃないってことはわかってるのか?
0837832/8352006/05/06(土) 02:49:52
>>836
すみません、よくわかってないです。
コンパイラで機械語に落とし込んでリンカで実行ファイルにする、ということを指していますか?

ちなみにやろうとしていることは、
リンカ機能を持つコンパイラAでDLL(hoge.dll)を作成後、
リンカ機能を持つコンパイラBでhoge.dllをロードするhoge.exeを作成しようということです。
これでhoge.exeを実行したら正常動作するのか、機械語レベルで誤動作するのか気になっています。

(でもDLLを提供しているサイトでは環境ごとにDLLファイルを分けてなかったような気がしてきました)

0838デフォルトの名無しさん2006/05/06(土) 03:07:10
>>837
>これでhoge.exeを実行したら正常動作するのか、機械語レベルで誤動作するのか気になっています。
だから、そこが根本的に間違っているんだ。
いいかね?
hoge.dllやhoge.exeが正常に(コンパイルエラーもリンクエラーもなく)作成できたなら
どんな動作結果が出ようとも、それは機械語レベルで「正常」に動作しているのだ。
そこでお前の思ったように動作しないとしたら、それはお前の作り方が間違って
いたからだ。
0839デフォルトの名無しさん2006/05/06(土) 03:52:45
何か答えてる方が無理に訳分からなくしているような。

DLLが公開する関数の、
・返値の型
・引数の数と型
・呼び出し規約
を正しく一致させて呼べば、違う言語からでも呼び出せる。
0840デフォルトの名無しさん2006/05/06(土) 04:04:09
>>839
それがわかるようなら>>832や>>835や>>837のようなレスが
付くはずがないんだがなあ。
0841デフォルトの名無しさん2006/05/06(土) 04:16:05
正しく設計してあることも前提だけどね。
たとえばFILE*を渡してたりするとNG。
0842デフォルトの名無しさん2006/05/06(土) 05:12:40
>>841
そりゃいくらなんでも具体的過ぎでしょ?
おいらは日常的にMSVCRT.DLLとFILE*を
やりとりしとるよ?
0843デフォルトの名無しさん2006/05/06(土) 05:54:51
俺の作ったASCII,UTF16(UTF-8未対応)
のファイルダンプのCのソース出して良い?
http://sourcepost.sytes.net/sourcepost/sourceview.aspx?source_id=27657
0844832/835/8372006/05/06(土) 06:22:54
>838-842
無粋な質問をしてしまったようで、すみません。
そもそもDLL(実行ファイル)の概念をよく理解していなかったようで、
「CでつくったDLLはCで(かつ同じ環境で)つくったEXEからしか使えない」という認識を
持っていたのが間違いの原因でした。

>>841
>正しく設計してあることも前提だけどね。
>たとえばFILE*を渡してたりするとNG。
これがNGなのはなぜでしょうか。
「FILE*を渡すこと」が正しい設計でない、というのがよくわからないのですが、
引数や返却値はint,charなどの基本型でないとだめというわけではないですよね。
もしくは上記は「違う言語から呼び出す場合(呼び出し側がCでDLLがC以外の言語)」について
言及していますか?

0845デフォルトの名無しさん2006/05/06(土) 06:58:45
ポインタがどうか判断出来ない命名が有るから気をつけろということでは?
0846デフォルトの名無しさん2006/05/06(土) 08:18:06
hint: FILE構造体は実装依存。
0847デフォルトの名無しさん2006/05/06(土) 09:29:18
EXEでnewした物をDLLでdeleteとか、その逆もダメだな。
0848デフォルトの名無しさん2006/05/06(土) 09:54:02
>>846の通り
たとえ関数の引数の型があっていてもヘッダによってメモリレイアウトや実装が違うと
そこでNGになる

C言語はバイナリのレイアウトを規定していない
FILE構造体も当然そう

バイナリレベルでの互換性がないわけ
そのためにIDL等が存在するわけだ
0849デフォルトの名無しさん2006/05/06(土) 13:57:10
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void main(void){
char* a="abcde";
unsigned int i=0;
FILE *p;
p=fopen("ドライブ:/パス","a");
for(i=0;i<strlen(a);i++){
fprintf(p,"%04x",*a);a++;}
fclose(p);
}
だとうまくファイルにabcdeのHexコードが入るんだけど、
2Byte文字の"あいうえお"とか使うと例えば'あ'は82a0hなんだけど、
ffffff82ffffffa0とかおのおの4Byteに変更されてしまう。
何か82a0になるようなうまい方法ないかな。
0850デフォルトの名無しさん2006/05/06(土) 13:58:12
charをunsigned charにしなはれ。
0851デフォルトの名無しさん2006/05/06(土) 14:06:15
>>850
それだけだと 0082 00a0 になってダメなんじゃない?
0852デフォルトの名無しさん2006/05/06(土) 14:19:43
>>850
ありがとう、その通りでうまくいきました。
他部分も手直しして、これで1Byteでも2Byteでもうまくいきました。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void main(void){
unsigned char* a="abcde";//"あいうえお"でもOK
int i=0;
int b=strlen(a);
FILE *p;
p=fopen("c:/windows/デスクトップ/h.bin","a");
for(i=0;i<b;i++){
fprintf(p,"%02x",*a);a++;}
fclose(p);
}
ありがとう、聞いて良かったです。
0853デフォルトの名無しさん2006/05/06(土) 14:55:54
>>852
"abcde" は char の配列だし、 strlen() の引数も char* だから
a の型は char* のまま、 *a を (unsigned char)*a にするのが正解。
char const* にするとなお良し(C++なら必須)。

あとは、
main の戻り値は int にしとけ。
インデントする気が無いならソース貼るのに全角スペース混ぜるな。
0854デフォルトの名無しさん2006/05/06(土) 15:38:53
コンパイラオプションで、charをunsignedにするのが常套手段
0855デフォルトの名無しさん2006/05/06(土) 15:39:57
修正しました(C,C++双方でやってみました)
#include<stdio.h>
#include<string.h>
int main(void){
const char* a="abcde";//"あいうえお"でもOK
int i=0;
int b=strlen(a);
FILE *p;
p=fopen("c:/windows/デスクトップ/h.bin","a");
for(i=0;i<b;i++){
fprintf(p,"%02x",(unsignedchar)*a);a++;}
fclose(p);
return 0;
}
あと、ファイル読み込みのほうですが、参考になるが分かりませんが一応セットで・・
#include<stdio.h>
int main(void){
char b;
int i=0;
FILE *p;
p=fopen("c:/windows/デスクトップ/h.bin","r");
while(fscanf(p,"%02X",&b)!=-1){
printf("%c",b);}
fclose(p);
return 0;
}
FILE処理失敗した場合の場合分けが双方ないのですが、
何かのネタにでもしてもらえれば幸いです。
0856デフォルトの名無しさん2006/05/06(土) 18:50:19
>>855
そういうふうに1バイトずつデータを読み書きしたいのならgetc/putcがお勧め。
0857デフォルトの名無しさん2006/05/06(土) 19:17:33
バイナリデータの入れ替えは何を使うのですか?
0858デフォルトの名無しさん2006/05/06(土) 19:25:03
キャラクタだからといって特別扱いはしてないから、そのままバイナリもいける。
0859デフォルトの名無しさん2006/05/06(土) 22:29:22
>>857 : error: too few arguments to function `入れ替え'
08608552006/05/07(日) 00:05:51
バイナリということで、簡単なサンプルですが作ってみました。
#include<stdio.h>
int main(void){
char b=0;
FILE *p;
FILE *pcopy;
p=fopen("c:/windows/デスクトップ/internet.lnk","r");
pcopy=fopen("c:/windows/デスクトップ/internet2.lnk","w");
while((b=getc(p))!=-1){
printf("%c",b);
fprintf(pcopy,"%c",b);
}
fclose(p);
return0;
}
使い方は簡単です。適宜なディレクトリにInternetショートカットを作り、名前を
この例の場合Internetとしています。
そして、fopenのある行2つを適宜なディレクトリにして、実行すれば、ソース経由でコピペされたバイナリで新たにInternetショートカットができてるはずです。
もっと使えるものに改良してもらえればありがたいです。
0861デフォルトの名無しさん2006/05/07(日) 00:20:47
PNGのCRCをC/C++で計算するソースって転がってないですか?
0862デフォルトの名無しさん2006/05/07(日) 00:30:31
>>860
インターネットショートカットは拡張子urlだけど。
ちなみに拡張子lnkのショートカットはバイナリファイルだからバイナリモード使え。
0863デフォルトの名無しさん2006/05/07(日) 00:31:52
>860
Cの基本としてbはintで定義しようね。
あと-1ではなくEOFとの比較に。
0864デフォルトの名無しさん2006/05/07(日) 00:44:48
>>860で一つ大事なのが抜けてました。
return 0;の手前にfclose(pcopy);です。
0865デフォルトの名無しさん2006/05/07(日) 00:45:26
864より863の方が大事だと思う。
0866デフォルトの名無しさん2006/05/07(日) 01:25:01
>>861
普通にPNGのソースじゃ駄目なの?
0867デフォルトの名無しさん2006/05/07(日) 01:27:22
>>860
バイナリモードにした方が…
0868デフォルトの名無しさん2006/05/07(日) 02:15:55
透過したいならマスク、圧縮したいならRLEで十分。
0869デフォルトの名無しさん2006/05/07(日) 17:12:19
マルチポストさせていただきます。

Dllに関する質問:
Dllの作成はdefファイルを使ってエクスポートしています。
defの抜粋fnSetColor@5
void HogeHoge::fnSetColor(void){
CColorDialog *col1Dlg= new CColorDialog;
col1Dlg->DoModaltheHogeHoge.();
theHogeHoge.m_Color= col1Dlg->GetColor();

if(col1Dlg != NULL)
delete col1Dlg;
}
呼び出し側:
typedefvoid(*fnSetColor)(void);
fnSetColor pfnSetColor= NULL;

pfnSetColor= (fnSetColor)GetProcAddress(hMod, "fnSetColor");

pfnSetColor();//ここでエラー:Run-Time Check Failure #0 〜

環境:WinXPHomeSP2+ VisualStudio2005です。よろしくお願いします。
0870デフォルトの名無しさん2006/05/07(日) 17:25:41
わかった!
0871デフォルトの名無しさん2006/05/07(日) 17:35:34
こういうのはマルチ煽りとかしてもいいんだろうか
0872デフォルトの名無しさん2006/05/07(日) 18:29:44
>>869
GetProcAddressがエラーで0を返し、それを呼び出そうとしたので、
ぬるぽと化しRun-Time Checkでガッされたという状態。
C++の関数名・変数名はコンパイラによって変形される。GetProcAddressが使うのもその変形された名前。
DEFファイルでどうにかすれば名前はどうにでもなるけど、
HogeHoge::fnSetColorが非メンバなら__thiscallだからアウト。

おとなしく、グローバル関数でラッピングしろ。

extern "C" void HogeHoge_fnSetColor(HogeHoge* p)
{
  p->fnSetColor();
}
08738692006/05/07(日) 18:51:15
>>872氏
GetProcAddressからは関数へのポインタが返ってきています。
#0は The value of ESP was not properly saved across a function call.
This is usually a result of calling a function declared
with one calling convention with a function pointer declared
with a different calling convention.
となっておりますので、
呼ばれる関数名と呼ぶときの関数名が違うのではないかと思うんですが?
0874デフォルトの名無しさん2006/05/07(日) 18:56:52
クラスのメンバ関数は暗黙でthisを引数に取るのに呼び出し側で渡してない。
つーかメンバ関数の意味わかってなさそう。
0875デフォルトの名無しさん2006/05/07(日) 19:43:44
char型の配列を unsigned charの配列にするにはどうすれば?
0876デフォルトの名無しさん2006/05/07(日) 19:47:27
>>875
符号が変わる場合があるわけだが、その場合はどうするつもりかね?
0877デフォルトの名無しさん2006/05/07(日) 19:56:42
>>876
全て+なのでその点に関しては大丈夫です。
0878デフォルトの名無しさん2006/05/07(日) 20:01:19
>>877
じゃぁ assert(x >= 0) を入れながらコピーすればいい。

スピードが問題になる場合で、2つの配列の実体が同じでもいいのなら
キャストを使ってコピーを省くことも可能。
0879デフォルトの名無しさん2006/05/07(日) 20:07:16
キャストの方を教えていただけませんか?
(unsigned char)としただけではエラーになるのですが。
0880デフォルトの名無しさん2006/05/07(日) 20:11:15
残念ながら
char a[10];
unsigned char b[10];
b=(unsigned char)a;
みたいなことはできないので中身を一つづつコピーしましょう
0881デフォルトの名無しさん2006/05/07(日) 20:14:07
std::copy(a, a + sizeof(a), b);
でできるわけだが。
0882デフォルトの名無しさん2006/05/07(日) 20:15:10
char a[10];
unsigned char* b;
b=(unsigned char *)a;
0883デフォルトの名無しさん2006/05/07(日) 20:15:52
>>879
本当にキャストをしたいのか?コピーでいいならコピーしとけ。
基本的に、キャストは最後の手段と考えるようであってほしいな。

char a[10];
unsigned char* const b = (unsigned char*)a;

C++ なら
unsigned char* const b = reinterpret_cast<unsigned char*>(a);
0884デフォルトの名無しさん2006/05/07(日) 20:17:56
const unsigned char * b = (unsigned char *)a;
じゃないの?
0885デフォルトの名無しさん2006/05/07(日) 20:20:48
皆さんありがとう。
>>882のでできました。
0886デフォルトの名無しさん2006/05/07(日) 20:21:07
>>884
何故constで受ける? 変更したいかもしれないじゃないか。
0887デフォルトの名無しさん2006/05/07(日) 20:22:08
>>885
意味はきちんと理解してから使おうね。
お姉さんとの約束だぞ。
0888デフォルトの名無しさん2006/05/07(日) 20:22:49
なんでキャストをデフォルトにするかなぁ?
0889デフォルトの名無しさん2006/05/07(日) 20:25:31
>>884
正直、これだけの話じゃ、constにすべかどうかさえわからない
0890デフォルトの名無しさん2006/05/07(日) 20:44:09
>877で、signed charで正数だと言ってるから大丈夫だろう。
0891デフォルトの名無しさん2006/05/07(日) 21:19:03
fscanfでファイルを読み込んで検索するwhile文作ったが、EOFに行ったきりファイルを読み込んでくれない。
ファイルポジションをファイルの先頭に持ってくるにはどうしたら。
0892デフォルトの名無しさん2006/05/07(日) 21:22:18
fseek
0893デフォルトの名無しさん2006/05/07(日) 21:24:17
freopenとかは?
0894デフォルトの名無しさん2006/05/07(日) 21:38:48
>>891
rewind
0895デフォルトの名無しさん2006/05/07(日) 21:42:01
>>891
exit
0896デフォルトの名無しさん2006/05/08(月) 00:29:36
1バイトのint型変数を作るにはどうしたらいいんですか?
0897デフォルトの名無しさん2006/05/08(月) 00:35:20
>>896
int のサイズが何バイトかは選べないよ。
0898デフォルトの名無しさん2006/05/08(月) 00:40:31
1バイトの変数の型(0〜255までの数字を扱える)を新しく作りたいのです。
0899デフォルトの名無しさん2006/05/08(月) 00:44:08
あまり見かけられませんが、構造体にはビットフィールドと呼ばれる技術があります
これは、ひとつのメモリ領域(バイト単位)に名前をつけてビット単位に振り分けるものです

ビットフィールドの作成は、構造体の生成とほぼ同じです
ビットフィールドで使われる方は、通常intまたはunsignedです(signedの場合は上位ビットが符合に使われます)

型 名前: サイズ;

型は説明したとおりです
名前にはメンバ名同様に、このビット領域の名前を指定します
サイズにはビット領域を指定します。3と指定すれば、この名前の領域に3ビット割り当てられます

このような特徴から、ビットフィールドは特定のビット数で確実に表現できる情報に用いられたりします
たとえば、boolean型の変数の作成などにはビットフィールドが有効です
1ビットの変数を生成しておけば、確実に0か1しか入りません
0900デフォルトの名無しさん2006/05/08(月) 00:50:07
wisdomさんありがとう。
0901デフォルトの名無しさん2006/05/08(月) 00:52:56
>>899
> あまり見かけられませんが、構造体にはビットフィールドと呼ばれる技術があります
普通に見かけます。貴方が低能なだけです。

> ビットフィールドで使われる方は、通常intまたはunsignedです(signedの場合は上位ビットが符合に使われます)
方→型。unsignedという型はありません。

加えて言えば、何ビットが1バイトか定義されていないプログラミング言語で
1バイトの変数を決めうちで作るのは規格にそった方法では不可能です。
0902デフォルトの名無しさん2006/05/08(月) 00:54:34
>>901
C/C++ で1バイトのビット数って CHAR_BIT じゃないの?
0903デフォルトの名無しさん2006/05/08(月) 00:58:47
ちょびっツ
0904デフォルトの名無しさん2006/05/08(月) 01:10:36
ただし、ビットフィールド自体は1ビットでも
構造体変数はunsigned(通常は4バイト)の領域であるということに注意してください
先ほどのプログラムのビットフィールドは、そのうちの1ビットなのです



意味ねぇーーーーーーーーーメモリ節約したかたのに
0905デフォルトの名無しさん2006/05/08(月) 01:13:43
>>904
char 使えばいいじゃん。
0906デフォルトの名無しさん2006/05/08(月) 01:16:17
他に方法は無いのかね?
0907デフォルトの名無しさん2006/05/08(月) 01:18:46
>>906 何が不満だ?
0908デフォルトの名無しさん2006/05/08(月) 01:22:23
>>907
もっと色々できるのかなって。この辺がC/C++の限界という事ですか。
レス数が900を超えています。1000を超えると表示できなくなるよ。