• ベストアンサー

【C言語教えて下さい!】文字検索

引数として、複数の文字列を格納した配列、その文字列数、あるいは文字列aを与え、aが複数の文字列を格納した配列中に見つかれば1を返し、見つからなければ0を返す関数find_string()をつくりたいのですがよくわかりません。 どなたかご教授お願いします。 ヒントや考え方など教えて下さい。

質問者が選んだベストアンサー

  • ベストアンサー
noname#137556
noname#137556
回答No.6

> 最初の配列は自分の好きなものを格納します。 中身の問題ではなくて,(混乱させてしまうかもしれませんが,) 「複数の文字列を格納した配列」を実現する方法が幾つか考えられます。 # 既に2通りの考え方に基づいた回答が出てる 例えば,  char a[] = "Red\0Green\0Blue";       // char 型の配列  char b[][8] = { "Red", "Green", "Blue" };  // (char 型の配列)の配列  char *c[] = { "Red", "Green", "Blue" };   // (char 型へのポインタ)の配列 これらは,いずれも「複数の文字列を格納した配列」と言えそうですが, メモリ上の文字列の配置が違います。 これらを受け取る関数の引数の型や,処理方法も変わります。 2番目のと3番目のは既に出ているので,(ANo.3 と ANo.4) 1番目ので作ってみました。 int find_string(const char *s, int n, const char *a) {   int i;   const char *p = s;   for (i=0 ; i<n ; i++) {     if (strcmp(p, a) == 0)  // 文字列の値が等しいか?       return 1;     p += strlen(p) + 1;   // 次の文字列に移動   }   return 0; }

その他の回答 (5)

noname#137556
noname#137556
回答No.5

「あるいは」に気を取られるけど、よくよく考えると、「複数の文字列を格納した配列」の方が問題だよなぁ… 自分で都合のいいように決めればいいのかな?

grantead
質問者

補足

最初の配列は自分の好きなものを格納します。

  • jjk65536
  • ベストアンサー率59% (66/111)
回答No.4

他の方が言うように、「あるいは」の意味が不明ですよね。 額面通りに捉えると、文字列数(数値)あるいは文字列(アドレス値)となりますが、 どちらの意味か判定する方法はC言語仕様上ありません。 「あるいは」を無理やり採用してコーディングするとこうですか? int find_string(char **strings, unsigned int a /* 文字列数、あるいは文字列 */ ) {  int i;  for(i=0; i<a; i++){   if(strstr(strings[i], (char *)a))    return 1;  }  return 0; } ちなみに、当然ですがこれでは正しく動作することはできません。 No.2さんのように「あるいは」は無視すると、以下のように それなりのものが作れそうです。 int find_string(char **strings, int num, char *a) {  int i;  for(i=0; i<num; i++){   if(strstr(strings[i], a))    return 1;  }  return 0; }

  • yama5140
  • ベストアンサー率54% (136/250)
回答No.3

#2 さんの改変版 ・引数には文字列の配列とその要素数、検索対象の文字列aを与える ・文字列の配列内で、検索対象文字列aが「含まれている」ものを探す ・一つでも「含まれて」いれば1、全て比較しても「含まれて」いなければ0 >ヒントや考え方など教えて下さい。  http://www.bohyoh.com/CandCPP/C/Library/strstr.html   この strstr を使用すればいいと思います。  cStr[ 3 ][ 32 } = {    "どなたかご教示お願いします",    "凸凹大学××教授が失踪した",    "○○教授がノーベル賞を受賞した"  }; 関数内 {  3回ループ( i++ )  {    if( NULL != strstr( cStr[ i ], "教授" ) ) return( 1 );  }  return( 0 ); // 全てに含まれていない }

  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.2

たしかにこれはひじょーにわかりづらい。 それが素の文だとすると、私なら「あるいは」の部分を意図的に無視してこう取った上で、出題者にこれでいいかを確認しますね。 ・引数には文字列の配列とその要素数、検索対象の文字列aを与える ・文字列の配列内で検索対象文字列aと「完全一致」するものを探す ・一つでも完全一致すれば1、全て比較しても一致しなければ0

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

「よくわかりません」ということは, 「わかるところもあるけどわからないところもある」ってことだね. じゃあ ・どこまではわかるのか ・どこからがわからないのか を, もっとはっきり書いてほしい. あと, この関数の仕様に曖昧なところがある: 1. 「引数として、複数の文字列を格納した配列、その文字列数、あるいは文字列aを与え」ってあるけど, これは多分意味が通じない. 「あるいは」はどんな意味で使ってるの? 2. 「a が配列中に見つかる」というのは, 「正確に一致したものがある」という意味なのか「部分文字列として見付かる」だけでいいのか, どっち? 念の為聞いておきたいんだけど, 「ある文字列が別の文字列と正確に一致する」とか「ある文字列が別の文字列の中にある」というのはわかる?

grantead
質問者

補足

もともとこういう文なので・・・・・・・多分、引数として文字列を格納した配列を入力し、そこから検索したい文字列を入力→その文字列が最初の文字列の中に含まれていれば1を、ないなら0を返すものです。

関連するQ&A

  • C言語について教えてください。

    二次元配列でまとめられた「配列で実現する文字列」の文字と文字列を表示する関数を定義し、その関数の機能を確認するプログラムを作成する。 ただし、以下の例のように文字列の個数が変更されても処理できる関数を作成する。 また、文字列の文字の個数は最大9とする(一次元配列の要素数は10とする) さらに、関数printf()をできるだけ用いない。 (1)二次元配列でまとめられたすべての文字列を「一度に」表示する関数を定義する (2)二次元配列でまとめられたすべての文字列の文字を「一度に」表示する関数を定義する。このとき、前回の課題で定義した「すべての文字を表示する関数print_all_char()」を新しく定義する関数から呼び出して用いる。 (3)二次元配列に各文字列を格納してまとめるとき、初期化ではなく、配列の宣言・定義の後で、関数strcpy()を用いること(例では、初期化によりまとめている) [例] char astr[][10] = { "ABCD", "EFGHIJ", }; [実行結果の例] すべての文字列の表示 ABCD EFGHIJ すべての文字列の文字の表示 A B C D E F G H I J [ヒント] (1)二次元配列でまとめられた文字列の文字あるいは文字列を表示する関数<返却値型><関数名>(二次元配列の受け渡しに対応した仮引数の宣言、文字列の数) (2)文字列の数を求める。二次元配列のすべての要素に文字列が格納されている場合、文字列の数=二次元配列の要素数(一次元配列の数) =sizeof(astr)/sizeof(astr[0]) ただし、sizeof演算子の生成する型はsize_t型である。 この問題について教えてください。問題丸投げだとは分かっていますがどうしても分かりません。教えてください。ちなみに前回の課題の定義は下の通りです。 void print_all_char(char *chs) { while(*chs!='\0') { printf("%c\n",*chs); chs++; } } よろしくお願いします。

  • C言語

    以下のC言語のプログラムを教えてください。 お願いします。 (1)標準入力から文字列(2 文字以上)を入力し,文字数を計上すると共に,入力された文字列の逆順に入れ替える処理を実現してください.なお,以下の要件を満たしたプログラムを作成してください. ・ 入力された文字列は,char 型の配列(要素数50)で受け取ること ・ 文字数を計上するcount 関数(引数:配列のアドレス,戻り値:文字数)を定義 し,main 関数より呼び出すこと ・ 文字列を逆順に入れ替えるreverse 関数(引数:配列のアドレス,戻り値:無し) を定義し,main 関数より呼び出すこと ・ 標準出力の処理は,main 関数で記述すること 【プロトタイプ宣言】 int count(char *str); void reverse(char *str); 【実行結果】 文字列を入力してください(2 文字以上) apple 文字数 = 5 入れ換え前 apple 入れ換え後 elppa (2)char 型の配列(要素数50)を2 つ宣言し,標準入力から2 つの文字列を入力してください.そして,格納した字列を入れ替える関数(swapstr 関数)を作成し,入れ替え前と入れ替え後の配列内の値(文字列)を配列名とともに標準出力するプログラムを作成してください. 【プロトタイプ宣言】 void swapstr(char *str1, char *str2); 【実行結果】 2 つの文字列を入力してください apple strawberry 入れ換え前 配列str1 = apple 配列str2 = strawberry 入れ換え後 配列str1 = strawberry 配列str2 = apple

  • C# 文字列の分割

    VS2005を使用しているものです。 複数のURL(入力)を格納したString型の配列があるのですが、 この配列から各要素(URL)の最後尾にあるファイル名だけを 取り出して別のString型の配列に入れたいのですが Splitなどを駆使すればよいのでしょうか? 例 C:\○○○\▲▲▲\××.拡張子 (元の配列の要素の一例)   などから××.拡張子の文字列だけを取り出して   別の配列に格納する感じです。 splitを使う際は\などを区切りに考えています。 for文の中でsplitを駆使しようと考えたのですが、分割した文字列を別で配列に格納して、その最後尾の要素だけ取り出したいのですが、URLの長さは入力によってまちまちなのでどのようにして取り出せばよいか困っています。 勉強不足で恐れ入りますが、何かご教授願えれば幸いです。

  • C言語についての質問です

    C言語についての質問です キーボードから文字列を入力しそれらを結合して行くことで長い文字列を作成する "Q"を入力した場合入力終了する "F"を入力した場合既存の文字列の前部に追加文字列を加える "R"を入力した場合既存の文字列の後部に追加文字列を追加する。 追加文字列はF,Q,Rのいずれかを入力したのちにキーボードより入力する。 またグローバル関数を使用しないでプログラムを作成する。加えてmain関数とは別に次の様な関数を作成し利用する 戻り値 : 無し(void型) 引数1 : コマンド文字列(Q,F,Rなどの追加文字列の追加場所を決定するchar型配列) 引数2 : 追加文字列(char配列) 引数3 : 追加される側の文字列(char配列) どうしてもグローバル関数を使用しないで作成することができません。また後部への追加文字列の追加はstrcat関数を使い実現することができましたが前部への追加文字列の追加の方法がわかりません。アドバイスやヒントなど何でもいいので指導のほどよろしくお願いします。

  • C言語:小文字を大文字に変換する関数を作成

    C言語超初心者です。学校の課題で次のような問題が出されました。 ・問題・ 次に挙げる縛りに沿い、以下の関数とメイン関数を作り、処理結果を画面に作成しなさい。 char *tst(char *str) ・strの中の文字列も小文字を大文字に変換し、変換した文字列が格納されているchar *に返す。 ・引数strの中の文字列は受け取った状態で手を加えない。 ・関数内でmalloc関数を使用し、領域を確保して大文字に変換した文字列を格納しreturnでポインタを返す。 ・malloc関数を使用する。 ---------------------------------------------------------------------------------- 大文字に変換するには while(*str != '\0') { if(*str >= 'a' && *str <= 'z') { *str -= 'a'- 'A'; } ++str; } というのは分かったのですがここから何をすするか全く分かりません。初心者なのでなるべく分かりやすく教えてもらえると有難いです。 お願いします。

  • C言語の基礎

    1.main関数の引数である、int argc と char **argvはどのように使用するのでしょうか? 2.特定の文字列(UserID)を入力し,それぞれの文字が使用可能文字列(数字とアルファベット(大文字小文字)と一致したら,使用可能文字列(配列)から削除し,残りの配列の文字を使って6~8文字のパスワードを作成するにはどのように関数を設計すればいいでしょうか? パスワードを作成するのに時刻を種とした乱数を使用してある一文字を取得するという方法を考えました。 srand(unsigned time(NULL); パスワードはUserIDに使用した文字を含まないようにしたいので,(使用可能文字列)-(UserID)= パスワードに使用できる文字列になると思うのですが, 配列-配列なんてできるのでしょうか?実力不足のため,変な質問をして申し訳ございません。どうかご教授ください。

  • C言語に関する質問

    C言語を独学で学んでいる者です。 配列に10桁の文字を格納して、そこから任意の1文字を探し出す(何番目に何の文字があると表示する)プログラムを作ってみたいのですが、どのように記述したらよいか分かりません。特に、10桁の文字列に同じ文字が複数含まれる場合は完全にどうしたら良いのかわからない状態です。 お分かりの方は、ぜひご教授願います。

  • 複数列の中の文字列の検索、個数抽出

    どなたかお力をお貸しください。。 エクセル2003を使用しています。    A列 B  C  D 1  あ  う     あ 2  い  お  か  か 3  う        う 4  え     き  く 5  お  い  う  け Dの文字列のなかでA~C列の中に重複している文字が何個あるかを出したいです。 この場合D列は「あ、か、う、く、け」なので、A~C列にある「あ、か、う」が重複しているので、3個と出したいです。 もしくは重複していない「く、け」で2個と出したいです。 MATCH関数を使うと出来そうなのですが、MATCH関数だと配列の概念がなさそうなので、どうしたものかと。 条件として、 ・一つのセルで関数を使用して出す。 ・マクロ、計算用のセルはできたら使用しない。 ・空白セルもあり、文字列の完全一致のみ個数としてカウント。 ・列の数はだんだん増えてくるので、列数は増えても大丈夫なやり方の方がいいです。 COUNTIFで重複個数を出すと、「う」が複数回出てくるので、重複の個数が増えてしまい困っています。 もしかしたら不可能かもしれませんが、どなたかお知恵をお貸しください。 よろしくお願いいたします。

  • c言語 int型の数字をchar型の配列に

    c言語についてです。 int型の数字をchar型の配列に入れたいです。 関数に対してint型の数字を文字列として渡し、 関数内でchar型の配列に格納したいです。 例として、 a(char a[]){  ~~  ~~ } int main(void){ int x = 5678;  ~~  a(x); } とできるようにしたいです。 しかしこれだと5678という値がそのままchar型の一つの配列に入る?ため正しくないです。 欲しい結果としてはちゃんとa関数内で、 a[1] = '5' a[2] = '6' a[3] = '7' a[4] = '8' となってほしいです。 もともと渡す値が”5678”となっていれば結果は正しく出るのですが、 渡す値がint型と決まっているためどうにかして5678を”5678”とすればいいのではないかと考えています。 つまり5678を単純に文字列に変換すればいいのでしょうか? またプログラム内ではsprintfやatolを使用しないで実現させたいです。 難しいかもしれませんがお願いします。 なんだか説明が下手ですみません。 お願いいたします。

  • 文字列の置換をCStringで(C++)

    あいうえお(5)かきく(8)けこ という文字列の ”(数字)”を別の文字列”さささささ” に変えたいんです。 (つまり、正解は あいうえおさささささかきくさささささけこ) replace関数を使ってみようと思ったのですが、 string型のものならば、 (開始場所、変えたい文字数、変えたい文字列) を引数にすればいいのはわかるのですが、 これを、CStringでやりたいのです。 ヘルプを見てもCStringのreplace関数は (変更前の文字列、変更後の文字列)を引数にする、 となっていて、私のように(数字)というアバウトな場合にはむかないのかとも思いますが、他のプログラムとの関係で、CString型がいいのです。 ややこしくてすいませんが、アドバイスお願いいたします。

専門家に質問してみよう