【初心者歓迎】C/C++室 Ver.49【環境依存OK】
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
2008/02/20(水) 12:33:41ただしその場合、質問者は必ず環境を書きましょう。
※sage禁止です(と代々スレに書いてありますが自己判断で)。
【前スレ】
【初心者歓迎】C/C++室 Ver.48【環境依存OK】
http://pc11.2ch.net/test/read.cgi/tech/1202141921/
【アップローダー】(質問が長い時はココ使うと便利)
http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/joyful.htm
0232デフォルトの名無しさん
2008/02/22(金) 22:49:58何ができるかを伝えてあげるべき。
ようこそプログラムの世界へ。
0233デフォルトの名無しさん
2008/02/22(金) 22:50:250234デフォルトの名無しさん
2008/02/22(金) 22:51:22それは関数そのものではないでしょうか
わざわざ教えたいただいたのですが、伝達不足でした、すみません
int strch_idx(const char* s, char c);
という関数の雛形が与えられて、この中身を作るのに、cを認識する必要があると判断したのですが、間違っているでしょうか
0235デフォルトの名無しさん
2008/02/22(金) 22:54:41今のC++では無理だね。だからSTLコンテナではreserveしてpush_backしたり、
組込の配列からコピー初期化したりする。
0236デフォルトの名無しさん
2008/02/22(金) 22:56:20cを認識の意味がわかりません
s内からcを検索したいってこと?
0237デフォルトの名無しさん
2008/02/22(金) 23:17:22この場合大人しくループまわして作ることになるんでしょうね。
ありがとうございました。
0238デフォルトの名無しさん
2008/02/22(金) 23:34:21例えば、sという文字列にcincoと入力すると、1を
sという文字列にiicicoと入力すると3を
sという文字列にnorioと入力すると-1をreturnで返却する
こういう関数を作ろうと思うと、sという文字列の中身について、
s[0]に格納されているのはcかどうか、s[1]に格納されてるのはcかどうか、s[2]に格納されているのは…
と、ひたすら繰り返して行く必要があると考えました
そのためには、s[n]について、cなのかどうか判定する必要があるのではないかと
この判定というのが、認識と同じ意味のつもりで使いました
0239デフォルトの名無しさん
2008/02/22(金) 23:40:52検索すればいくらでも出るだろ
0240デフォルトの名無しさん
2008/02/22(金) 23:45:33if (s[0] == 'c') return 1;
if (s[1] == 'c') return 2;
if (s[2] == 'c') return 3;
...and so on.
0241デフォルトの名無しさん
2008/02/22(金) 23:50:48学校の宿題は自分でやれよ。屑
0242デフォルトの名無しさん
2008/02/23(土) 00:02:06それ以外に方法はstrchrを使用するぐらいしか思いつかない
(strchrもおそらくは、中で同じようなことしてると思うけど)
なにが疑問なのかよくわからないので、とりえあず2通りソースを貼り付けときます
�@
int i;
for(i=0; s[i] != '\0' && s[i] != c; i++);
return s[i] != '\0' ? i : -1;
�A
char *p;
return (p=strchr(s, c)) != NULL ? (int)(p-s) : -1;
返ってくるのは配列の添え字ですのであしからず
0243デフォルトの名無しさん
2008/02/23(土) 00:06:01どうも、理解できました
>>242
ご丁寧にどうもありがとうございました
0244デフォルトの名無しさん
2008/02/23(土) 03:34:24C++ VS2005
略)
printf("Got: %02x%02x%02x%02x%02x\n", buf[0], buf[1], buf[2], buf[3], buf[4]);
※
buf[0]には01
buf[1]には06
buf[2]には17
buf[3]にはf3
buf[4]には34
が入る。
を文字列"0106171f34"に置き換えたい。
1.このbuf[]の中(16進数)を文字列に変換したい。
2.文字列に変換した後に、buf[0]〜buf[5]を繋げたい。
sprintとかを使えば良いみたいなのですが、どのようにやってよいか分からずに困っています。
どうかよろしくお願いします。
0245デフォルトの名無しさん
2008/02/23(土) 03:35:36課題を丸投げしたいなら宿題スレにいけ
0246デフォルトの名無しさん
2008/02/23(土) 03:37:49いや一応答えると
sprintじゃなくてsprintfだな
sprintfで連結もできます
0248デフォルトの名無しさん
2008/02/23(土) 03:54:120249244
2008/02/23(土) 08:58:16なんとか解決しました。時間かかった>< やってみれば、なんと簡単なコードって感じですけど。
ヘルプのみかたってイマイチわからないんですけど、ヘルプの見方の解説サイトとかってありませんでしょうか?
0250デフォルトの名無しさん
2008/02/23(土) 09:49:02manコマンドのことなら、man manでOK。
0251デフォルトの名無しさん
2008/02/23(土) 10:05:35VC++6.0でデバッグしてると、関数に入るだけでESPが100バイトくらい進みます
C++だとモジュール毎にスタックをこんなに食うものなのでしょうか?
デバッグ情報か何かで食ってるのですか?
0252デフォルトの名無しさん
2008/02/23(土) 10:06:370253デフォルトの名無しさん
2008/02/23(土) 10:06:52ローカル変数が100バイトほどあるんじゃなくて?
0254251
2008/02/23(土) 11:07:16家のPCでためしたけど、
関数にステップインするときはESPは4バイトしか進まないが、
そこから1step進めて、{から関数内の1行目に入るときに、
80バイトも食う
char a[100];と宣言を入れると、これが180バイトになるから、やり方は間違ってないはず
この80バイトが何なのかわからん
0255デフォルトの名無しさん
2008/02/23(土) 11:21:130256デフォルトの名無しさん
2008/02/23(土) 11:22:06一時オブジェクトの置き場になってるとか?
関数の戻り値のオブジェクトを別の関数に直接渡してる場合とか・・・
アセンブラコード出させて見ても使われてなさげ?
0257要は、ソースも出さずにあれこれ言われてもしらねーよっと
2008/02/23(土) 11:24:15さもなければalloca()相当のコードが入っているとか。
あーそうそう、この場合のローカル変数は、Cのコード上現れるものに限らず
コンパイラが必要とした一時変数も含めてってことね。
例えば、構造体を値渡ししていたりreturnで戻していると作られるかもね。
0258251
2008/02/23(土) 11:32:53{
char a[100];
printf ("test");
}
int main(int argc, char* argv[])
{
test();
return 0;
}
コードはこれだけなんだけど。C++じゃねーな。
混合モードで見ると、これが原因らしいが、何でこんなことしてるのかな。
アセンブラわからん。
sub esp,0A4h
0259デフォルトの名無しさん
2008/02/23(土) 12:57:17VC++ なら sprintf とか入力して F1 推せば見れるだろ。
0260デフォルトの名無しさん
2008/02/23(土) 12:58:29デバッグ用じゃなくてもそうなら、
例外用のコードなのかもしれないな。
0261デフォルトの名無しさん
2008/02/23(土) 13:01:09手元の2005EEで試したが、リリースビルドの規定値では該当のコードは生成されない。
デバッグビルドだと生成されるが、「基本ランタイムチェック」を無効にしたら配列分だけになった。
つまり、>257の1行目だね。
0262デフォルトの名無しさん
2008/02/23(土) 13:23:220263デフォルトの名無しさん
2008/02/23(土) 13:24:01C言語でポインタを参照渡しするにはどうすればいいですか?
0264デフォルトの名無しさん
2008/02/23(土) 13:25:31ポインタのポインタを使う
int **p;みたいなの
0265デフォルトの名無しさん
2008/02/23(土) 13:25:41ポインタを渡すことで参照渡し「っぽいこと」はできるので、
ポインタのポインタを渡せばポインタの参照渡し「っぽいこと」はできます。
0266デフォルトの名無しさん
2008/02/23(土) 13:26:020267デフォルトの名無しさん
2008/02/23(土) 13:32:220268デフォルトの名無しさん
2008/02/23(土) 13:32:280269デフォルトの名無しさん
2008/02/23(土) 13:37:010270デフォルトの名無しさん
2008/02/23(土) 13:38:300271243
2008/02/23(土) 13:45:44何が間違っているのか、理解できません
添削をお願いしたいです
c++、Borland C++5.5.1 for win32でやっています
int strch_idx(const char* s, char c)
{
int i = 0;
while(s[i])
{
if(s[i] == 'c') goto end;
else if(s[i] == 0)
{
i = -1;
goto end;
}
i++;
}
end:
return i;
}
0272デフォルトの名無しさん
2008/02/23(土) 13:50:020273デフォルトの名無しさん
2008/02/23(土) 13:51:13>if(s[i] == 'c') goto end;
'c' じゃなくて c では?
あと、else if (s[i] == 0) の判定をする前に while の条件で抜けてしまうかと
0274デフォルトの名無しさん
2008/02/23(土) 13:55:02そういう不正確な事やってると
>>207 みたいな奴が出てくるんだよ。
0275デフォルトの名無しさん
2008/02/23(土) 14:11:18俺はCでの話を言ってるんだぞ?
アドレス渡ししかないんだからないんだから、不正確もなにもねぇだろうが
0276デフォルトの名無しさん
2008/02/23(土) 14:12:170277デフォルトの名無しさん
2008/02/23(土) 14:13:070278デフォルトの名無しさん
2008/02/23(土) 14:15:15ポインタもコピー
0279デフォルトの名無しさん
2008/02/23(土) 14:15:51C には参照渡しなんてないんだよ。
0280デフォルトの名無しさん
2008/02/23(土) 14:18:09どっちかだけ知らずに語ると馬鹿なことになるけど、どっちもしっかり理解してるなら別に問題ないでしょう
0281デフォルトの名無しさん
2008/02/23(土) 14:20:520282デフォルトの名無しさん
2008/02/23(土) 14:24:24static_castの方が用途が限定される
0283デフォルトの名無しさん
2008/02/23(土) 14:24:35個人がそう理解するのはかまわんけど、初心者への説明としては不親切じゃね?
0284デフォルトの名無しさん
2008/02/23(土) 14:25:07Cとの互換性を大事にしたいなら後者、意味をはっきりさせたいのなら前者を使うといいでしょう。
0285デフォルトの名無しさん
2008/02/23(土) 14:26:18実際やってみると
cuで2が、gguで3が、ijcoで4が返ってきます
これは、s[i] == cと、s[i] == 0の判定が成されていないという事ですよね?
しかし、while関数自体は終わってるので、s[i]は判定されている
どういうことなんでしょうか?
また、ご指摘を受けて、whileをdo-whileに変更しました、ありがとうございます
0286デフォルトの名無しさん
2008/02/23(土) 14:27:110287デフォルトの名無しさん
2008/02/23(土) 14:30:00てか絶対使わないようにしてるんだが、違うのか
0288デフォルトの名無しさん
2008/02/23(土) 14:31:58単なる構文糖衣じゃない。
参照の参照というのは存在しないが、
ポインタのポインタというのは存在する。
これは大きな違いで、適当な教え方してると >>207 みたいなやつが出てくる。
0289デフォルトの名無しさん
2008/02/23(土) 14:33:55むしろ使った方が綺麗になる状況では使う。
でも、上のは break; 使えば解決できることで、
goto を使って解決すべきじゃない。
0290デフォルトの名無しさん
2008/02/23(土) 14:37:52>>284
当面はあまり気にしなくてよさそうですね
どうもありがとうございました
0291デフォルトの名無しさん
2008/02/23(土) 14:39:03いいや、気にしろ。
0292デフォルトの名無しさん
2008/02/23(土) 14:42:06せいぜいクラスのテンポラリオブジェクトを作るのに関数風のキャストを使うくらい。
0293デフォルトの名無しさん
2008/02/23(土) 14:47:55それはキャストよりもコンストラクタ呼び出しのほうがしっくりくる
0294デフォルトの名無しさん
2008/02/23(土) 14:49:300295デフォルトの名無しさん
2008/02/23(土) 14:52:190296デフォルトの名無しさん
2008/02/23(土) 14:54:36すいません
気にしろとだけ言われましてもなにに気を使えばいいのかわかりません
まずい点でもでてくるのか
だとかを教えていただけませんか
0297デフォルトの名無しさん
2008/02/23(土) 14:58:130298デフォルトの名無しさん
2008/02/23(土) 14:58:20CreateWindowとCreateControlWindowはどう違いますか?
0299デフォルトの名無しさん
2008/02/23(土) 15:00:58C風のキャストはなんでもかんでもキャストできてしまうので、
プログラマの意図と違ってても警告が出ない
const void *p = 〜;
char *q = (char*)p; // charにキャスト・・・あれ? constも外しちゃったよ! でも警告は出ない
char *r = static_cast<char*>(p); // コンパイルエラー: static_castでconstは外せない
char *s = const_cast<char*>(static_cast<const char*>(p)); // constも外したい意図の場合はこう書く
0300デフォルトの名無しさん
2008/02/23(土) 15:03:54gotoのほうが行き先が明確になるので、理解しやすかったので、用いていますが
なぜ怖いのでしょうか
それと、「これは、s[i] == cと、s[i] == 0の判定が成されていないという事ですよね?
しかし、while関数自体は終わってるので、s[i]は判定されている
どういうことなんでしょうか? 」
これにも答えていただけると非常にありがたいです
0301デフォルトの名無しさん
2008/02/23(土) 15:04:05キャストというのは基本的にマズい処理。
アップキャストだけは例外的に安全だが、
それ以外は基本的にはあまりやるべきではない。
でも、実際にはどうしてもやる必要が出てくる事もある。
こればっかりは仕方が無い。
そういう時、C 風のキャストを使ってしまうと色々と問題が発生する。
・ 間違って危険なキャストをしてしまうかもしれない。
例えば、const を付けるべきところで const を付け忘れたり。
こういう時、static_cast なら危険な const の付け忘れがあるとコンパイルエラーになる。
C 風キャストだと問答無用でキャストされてしまう。
これが一番の問題。
・ キャストが原因っぽいバグが見つかった時、どこにキャストがあるのか探すのが面倒。
C++ のキャストだと検索でキャストを行っている箇所を簡単に見つけられる。
・ キャストがあまり目立たない。
危険な処理を行っている箇所が目立たないのは危険。
C++ のキャストは非常に目立つ。
・ 打鍵数が少ないので気軽にキャストをしてしまう。
C++ のキャストは打ち込むのが面倒で、キャストを本当に使うべきなのか
立ち止まって考えるよう思考を誘導してくれるかもしれない。
・ 今行おうとしているキャストはどういうものかをあまり意識しないかもしれない。
キャストという処理を軽く見ているのはよろしくない。
0302デフォルトの名無しさん
2008/02/23(土) 15:06:01gotoが必要になるのは言語の構造化能力を超えた構造が必要になる場合であって、
この場合はそういう場合でない。
0303デフォルトの名無しさん
2008/02/23(土) 15:06:12論理的に記述しようぜ。
「while を終了する」 と 「指定位置に移動する」 では
前者の方がより論理的だ。
論理的なコードは、一般に変更に強く、バグが出にくい。
まあ、break すらみだりに使うべきじゃないという人もいるけどね。
0304デフォルトの名無しさん
2008/02/23(土) 15:07:500305デフォルトの名無しさん
2008/02/23(土) 15:09:39不可能
0306デフォルトの名無しさん
2008/02/23(土) 15:10:05template <size_t N> void foo(char (&hoge)[N]);
と区別できなくはない。
0307デフォルトの名無しさん
2008/02/23(土) 15:12:020308デフォルトの名無しさん
2008/02/23(土) 15:12:33template <size_t N> inline void foo(char (&hoge)[N]) { foo(hoge, N); }
もちろん、こう実装するんだぜ。
0309デフォルトの名無しさん
2008/02/23(土) 15:13:120310デフォルトの名無しさん
2008/02/23(土) 15:13:14>cuで2が、gguで3が、ijcoで4が返ってきます
その書き方はおかしい
strch_idxには引数が2つあるので、cuとかgguだけでは結果は決まらないはずだ
0311デフォルトの名無しさん
2008/02/23(土) 15:13:24逆。
gotoの方がどこにでも飛ばせるせいで行き先が不明確になる。
自分の書いたコードを他人に読ませることを想像してごらん。
breakならどこに飛ぶのか一目瞭然だけど、gotoだといちいちラベルを検索しないといけない。
しかもbreakなら「ループの終了」という意図が一目瞭然だけど、
gotoだとどういう意図で飛ばしたのかを考えないといけない。
そういう理由でgotoは避けられるため、安易にgotoが入っているとさらに、
「gotoを使わなければいけないどんな理由があったのか?」と考えさせることになる。
0312デフォルトの名無しさん
2008/02/23(土) 15:14:13あと、コンテナの最後の要素以外を処理する時、
std::vector<T> container;
for (int n = 0; n < static_cast<int>(container.size()) - 1; ++n) container[n] = ...;
ってやる?
0313デフォルトの名無しさん
2008/02/23(土) 15:23:01俺はstatic_castを使う
コンテナの方は
for (size_t n = 0; 〜
って書けばいいのでは
本当は std::vector<T>::size_type の方が適切なのかもしれんが
0314デフォルトの名無しさん
2008/02/23(土) 15:23:54>int⇔floatの変換
うん。
>最後の要素以外を処理
unsigned使う。
0315デフォルトの名無しさん
2008/02/23(土) 15:31:10使う。
>コンテナの最後の・・・
for (std::vector<T>::size_type n = 0, size = container.size(); n + 1 < size; ++n) container[n] = ...;
ってやると思う。
符号無しの値を符号付きにキャストするのは基本的に危険だと思う。
0316デフォルトの名無しさん
2008/02/23(土) 15:32:52if( !c.empty() )
for( size_t n=0; n<c.size()-1; ++n)
で何か問題あるのか?
0317デフォルトの名無しさん
2008/02/23(土) 15:34:18n + 1 < c.size() で判定すれば empty チェックは要らない。
0318デフォルトの名無しさん
2008/02/23(土) 15:36:12まあ T をそういう意味で使ってるとは限らないが。
0319デフォルトの名無しさん
2008/02/23(土) 15:39:01>>311での説明とほぼ同じという理解でよろしいでしょうか
>>311
gotoよりbreakを使うべきというのは、よく理解でき、納得できました
しかし、怖いというのは一体
>>310
すみませんが、もうすこし噛み砕いて説明願えないでしょうか
const char* sには、任意の文字列が入って、char cで、検索する文字を固定という事ではないんですか?
そのconst char* sにcuですとか、gguですとかが入っているので、これで十分だと考えているのですが
0320デフォルトの名無しさん
2008/02/23(土) 15:43:08goto はまず特定の状況でしか使われない。
それ以外で使われると混乱するし、
何のために使われているかすぐに分からないので不気味で怖い。
0321デフォルトの名無しさん
2008/02/23(土) 15:44:11goto は意図が不明確。
goto のあるコードを変更することになった場合、
その意図が 100% 分からなければ、
手を加えて変なことになりかねないので怖い。
0322デフォルトの名無しさん
2008/02/23(土) 15:44:56一番怖いのは、バグの温床になること。
コードの分かりにくさってのはバグに直結する。
0323デフォルトの名無しさん
2008/02/23(土) 15:47:14イテレータ使うならこうだな。
前進イテレータでさえあれば、これでいけるはず。
if(! container.empty()) {
Iter it_next = container.begin();
++it_next;
for(Iter it = container.begin(), end = container.end(); it_next != end; ++it, ++it_next) *it = ...;
}
0324デフォルトの名無しさん
2008/02/23(土) 15:52:18const char* s が cu でも c の方は
strch_idx("cu", 'c') とか
strch_idx("cu", 'u') とか
strch_idx("cu", 'x') とか色々指定できるわけで
0325デフォルトの名無しさん
2008/02/23(土) 15:53:30なるほど、よく理解できました
ご親切にありがとうございます
1、意図が不明で不気味で怖い
2、バグを招きやすいから怖い
この二点ですね
そして、本筋のほうもできたら説明していただきたいのですが
0326デフォルトの名無しさん
2008/02/23(土) 15:53:540327デフォルトの名無しさん
2008/02/23(土) 15:58:000328デフォルトの名無しさん
2008/02/23(土) 15:58:55一般に、コンパイルに時間がかかる方が、
コンパイル時にある程度処理を行ってくれているため、速くなる。
ただ、コードがあまりにも肥大してくると、
キャッシュの効きが悪くなって遅くなる事もある。
0329デフォルトの名無しさん
2008/02/23(土) 16:02:03いくつか修正したみたいだけど今はどうなってるの?
0330デフォルトの名無しさん
2008/02/23(土) 16:05:44最初から全文現すべきでしたね、申し訳ありません
#include <iostream>
using namespace std;
int strch_idx(const char* s, char c)
{
int i = 0;
do {
if(s[i] == c) goto end;
else if(s[i] == 0)
{
i = -1;
break;
}
i++;
} while(s[i]);
return i;
}
int main()
{
cout << "文字列を入力:"; char p[] = ""; cin >> p;
char c = c; cout << strch_idx(p, c);
return 0;
}
>>327
forだと、終了させるための条件が思いつかなかったので、whileにしましたが、やはりforのほうが良い理由があるのでしょうか
0331デフォルトの名無しさん
2008/02/23(土) 16:07:30>char c = c;
これはなによ
■ このスレッドは過去ログ倉庫に格納されています