- ベストアンサー
C言語で文字列から文字を探すプログラムの作成方法
- C言語で文字列から文字を探すプログラムを作成する方法について解説します。
- 具体的なコード例を紹介しながら、文字列strの中に文字cが含まれているかどうかを判定する関数の作成方法を説明します。
- また、コンパイルエラーについての疑問点に対する解決方法も説明します。
- みんなの回答 (7)
- 専門家の回答
質問者が選んだベストアンサー
char *str_chr(const char *str, int c) {} という宣言では 戻り値: char *型(charへのポインタ) 引数: str (cosnt char *型/const charへのポインタ) となります。 const char というのは、「変更できないchar」と言う意味です。 char c='A' ; const char cc='A' ; /* 初期化によってのみ代入可能 */ c ='C' ; /* OK */ cc ='C' ; /* エラー */ const char * はconst char への(普通の)ポインタです。ポインタが指す実体はconst charなので変更できませんが、ポインタ自身は通常の変数なので変更できます。 char str[] = "abcde" ; char * cp = str; const char* ccp ="ABCDE" ; cp ++ ; /* OK */ *cp = 'A' ; /* OK */ ccp ++ ; /* OK */ *ccp = 'A' ; /* エラー */ このように、振舞いが違うので、char/char *型とは別の型として扱われます。 char → const char,char * → const char * は暗黙の型変換ができます。変更を禁止するだけですから。 逆方向は、(本来は)基本できません。const の意味を失ってしまうし、文字列リテラルのような本当に変更してはいけない(致命的なエラーになりかねない)ものもあるからです。 型変換(キャスト)は、暗黙の変換ができない場合でも、強制的に型変換を行うもので、変換したいものの前に (変換したい型) と付けます。 (char *)str はstrの型を強制的にchar *型にします。 なお、この変換は、キャストを書いた箇所だけのもので、変数そのものを変換するわけではありません。 さて、問題のプログラムですが。 return str としていますから、char * 型をreturnしなければならないところに、const char *型を指定している、という警告です。 const char * → char *の暗黙の型変換は無いので、char *として使えない、ということです。 そのため、戻り値の型を合わせるために(char *)でキャストしています。 > strはポインタなのになぜまたわざわざchar型に変換しているのですか? char型には変換していません。 char型に変換するときは(char)です。
その他の回答 (6)
- kb-nike
- ベストアンサー率36% (72/200)
ANo.6です、質問の内容を早とちりして、勘違いしていました。 再回答します。 >このreturn strの部分はreturn (char*)strが正解のようです。 >意味がわかりません。 >strはポインタなのになぜまたわざわざchar型に変換しているのですか? >といか(char*)の意味が根本的にわかりません。 質問者さんのコードをそのままコンパイルすると、 VC++では次のような「警告」がかえってきます。 warning C4090: 'return' : 異なる 'const' 修飾子です。 str_chr()引数で「const char *」型として渡された引数を、 「char *」型として戻そうとするために、エラーまたは警告となります。 引数の型を「const char *」→「char *」に変更すると、 エラーまたは警告がなくなることで、その意味がわかると思います。
- kb-nike
- ベストアンサー率36% (72/200)
柴田望洋さんのHP:「C」→「標準関数」→「strchr」 http://www.bohyoh.com/CandCPP/C/Library/strchr.html に、「■実装例■」として模範例が出ています。 ご自身のコードと比較してみてください。
- okormazd
- ベストアンサー率50% (1224/2412)
char *str_chr(const char *str, int c) {} を作れといっているのだから,「誤り」といわれてもネ。 //はその文字が何番目にあるかにしたいと思っただけで,質問とは関係ない #include<stdio.h> char *str_chr(const char *str, int c) { while(*str){ if(*str==c) return (char *)str;/*一時的に型キャスト,キャストしなくてもエラーではない。constといっているのに変える気か,というような警告*/ str++; } return NULL; } int main() { char str[100]={0};/*scanfで文字列を取りたいのだから配列にして,初期化しておく*/ char c; //char *p; scanf("%s",str); scanf(" %c",&c);/*scanfの引数はアドレス*/ //p=str-1; printf("%p\n",str_chr(str,c));/*ポインタを返すのだから,書式は%p*/ //printf("%d\n",str_chr(str,c)-p);/*ポインタで返されてもわからないから,何番目かわかるようにすればこうなるというだけ*/ return 0; }
- CanvasShoes
- ベストアンサー率64% (16/25)
(1) 関数の宣言で、 誤:char *str_chr(const char *str, int c) 正:const char *str_chr(const char *str, int c) です。 str_chrの内容は合っていると思います。 (2) mainにおいて、 printf("%d", str_chr(str,c)); は、間違っています。 ------------ 誤:printf("%d", str_chr(str,c)); 正:printf("%s", str_chr(str,c)); です。 改行するなら、printf("%s\n", str_chr(str,c));と\nをつけます。 (3) mainにおいて、 char *str ; scanf("%s", str) ; は間違いです。 実体あってのポインタです。 [ポインタ]----->[実体] char *str ; は、ポインタサイズの容器strを確保しますが、容器の中身は不定です。 そのような値を関数に渡してはいけません。 ----- char enoughBuffer[1024] ; enoughBuffer[0] = '\0' ; /* 空文字列として初期化 */ char *str = &enoughBuffer[0] ; /* ポインタサイズの容器strを確保し、バッファの先頭文字へのポインタを格納 */ scanf("%s", str) ; とか、 char enoughBuffer[1024] ; enoughBuffer[0] = '\0' ; /* 空文字列として初期化 */ scanf("%s", enoughBuffer) ; /* バッファの先頭へのポインタを渡す */ とすべきです。 ちなみに、C言語では、&enoughBuffer[0]とenoughBufferは、同じ値(同じポインタ)です。 ------------------------- 以下、ご参考 ------------------------- ご存じのとおり、C言語には文字列型は存在しません。代わりに文字配列と'\0'の組み合わせで表現します。 (4) 文字へのポインタも、文字配列へのポインタも、char *で表します。 a. [ポインタ(char *)]------>(char)[文字] b. [ポインタ(char *)]------>(char配列)[文字][文字]...[文字][文字] たとえば、 char *p ; という定義において、pがa,bいずれのタイプを指しているかは、プログラムを書いた人にしかわかりません。そのため実務上は、char *pMoji, *pNameなど、変数名で区別します。 (5) ポインタが指している実体を書き換えてほしくないときは、constを使います。 たとえば char moji = 'X' ; char *p1 = &moji ; const char *p2 = &moji ; と定義されているとすると、 p1は、将来、実体を書き換えることを示唆しています。(たとえば、*p1 = 'S') p2は、実体を参照はするかもしれないが、書き換える意図はないことを示唆しています。 (6) 文字列定数は、内部的に文字配列(最後の要素が'\0')です。 定数は書き換えてほしくないので、constを使います。 (例) const char *pcstr = "Good Morning." ; コンパイラが許せば、テクニックとしては、 char *pstr = (char *)"Good Morning." ; という定義も可能ですが、良いプログラムではありません。
- ohtawa
- ベストアンサー率23% (9/38)
No.2さんが示されているとおりです 私も間違ったことあるだけでなく なかなか理解できませんでした 私は次のように要約して理解しています (1)const char * と char * とは 別の型である (2)暗黙に変換される方向とそうでない方向がある (3)const char * は書き込み不可 char * 書き込み可 だが キャストは変数を変えることはしないその場限りである うーん うまく表現できないな
- 正親町(@Ohgimachi)
- ベストアンサー率43% (110/252)
コンパイラがwarningを出す理由は関数の宣言が char *str_chr(const char *str, int c){ と、strがconstと宣言されていて、関数の戻り値の定義、char *と一致しないからです。 ちなみにgccでは以下のworningが出力されています。 warning: return discards qualifiers from pointer target type これは、「リターンでポインターの型宣言が破棄されている」ということです。 const宣言は、「変数の内容が変更できない」と意味なので、誤って変更してしまうバグを予防するために使用されます。この場合は、scanf()で読み取る文字列ですから、内容が変更され使用方法が矛盾しています。 const宣言は一般的にメッセージや定数などの内容を変更してはならない変数(記憶領域)に対して使用されます。特に変数がROMにある場合には、その変数に書き込むとプログラムの実行時にCPUの動作が異常になります。 (割り込み処理に移行したり停止したりする) したがってconstの使用はバグの予防対策として実装されているのです。 あとは、main()の scanf()とprintf()の見直しですね。