質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

6回答

2599閲覧

C言語による検索アルゴリズムの記述方法について

HogeAnimalLover

総合スコア4830

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

3クリップ

投稿2021/08/13 14:15

お世話になっております。C言語を学び20年ほど経ちましたが、未だにスマートな記述方法を知らないケースがあります。質問させてください。

配列dataの中から特定値VALUEを検索し、発見時に条件分岐することを考えます。

これをサブルーチン化せずに記述すると以下のようになりgoto/label構文が出てきます。もちろん、サブルーチン化とかフラグ管理という方法もありますが、goto/label構文以上に複雑になってしまっては本末転倒です。これをスマートに記す方法があればご教示願います。よろしくおねがいします。

C

1 2for(i = 0; i < N;i++) { 3 if(VALUE == data[i]){ 4 //当該データを発見した場合の処理。 5 goto label; 6 } 7} 8//当該データが存在しなかった場合の処理。 9label:;

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2021/08/13 23:35 編集

サブルーチン化で検索という一機能をモジュール化できるならそうするのがスマートだと思います。 それによってテストも再利用も可能になり、コードの依存性も低くなります。 記述は増えるかもしれませんが、メインルーチンを読む際に検索の実装まで読む必要はなくなり、ループが関数呼び出しにかわることで単純になって可読性も高くなります。 できないのであれば、そこにはできない理由(極度のチューニングが求められるなど)があるはずなので、追及すべきはスマートさではなく実行効率などになるはずです。 検索の速度を上げたいのであれば、リニアサーチをやめてアルゴリズムとそれを支えるデータ構造を考え直すのが良いと思います。 どういう状況でしょうか?
episteme

2021/08/14 00:41

C++tag ついてるけど、Cの質問? C++なら std::find / std::find_if で解決するんだが。
dodox86

2021/08/14 01:55

> サブルーチン化とかフラグ管理という方法もありますが、goto/label構文以上に複雑になってしまっては本末転倒です。 個人的な範囲ですが、C言語のプログラミングでも goto/labelの出番を感じたことが無いので、むしろその感覚に少し違和感を感じます。「スマート」と思う主観に相違があるのでは。
dodox86

2021/08/14 01:59

> C言語のプログラミングでも goto/labelの出番を感じたことが無いので、 これは言い過ぎだったかも。多重ループからの脱出や、Linuxのドライバーなど、一部のプログラムでは散見されるケースはありますね。(私自身は使いませんが)
HogeAnimalLover

2021/08/14 03:54

失礼、ライブラリ関数の利用は考えていないと書いていませんでした。これも含めようと思います。
Zuishin

2021/08/14 03:56

> ライブラリ関数の利用は考えていないと書いていませんでした。 スマートじゃないです。
episteme

2021/08/14 05:41

> ライブラリ関数の利用は考えていないと書いていませんでした。 後出しジャンケンかよー...回答に追記しました。
takasima20

2021/08/14 11:12

現在の自分の知見が正しいと確認したいがための質問じゃないの? たぶん何を回答しても納得しない気がするなあ。
guest

回答6

0

ベストアンサー

未だにスマートな記述方法を知らないケースがあります。

「なにをもってスマートとするか」によるんじゃないかと。
コードを書かずに解決するのがいちばんスマートと考えるなら、
検索アルゴリズムは書かずにライブラリに任せます。

C

1#include <stdio.h> 2#include <search.h> 3 4// 検索はライブラリに任せ、比較関数だけを用意する 5int equals(const void* x, const void* y) { 6 return *(const int*)x == *(const int*)y ? 0 : 1; 7} 8 9int main(void) { 10 int data[5] = { 1, 3, 5, 0, 2 }; 11 unsigned int size = 5; 12 13 int key = 3; 14 // VC++ では lfind は deprecated とのこと、しゃーないから _lfind で代用 15 int* p = (int*)_lfind(&key, 16 data, &size, sizeof(int), 17 equals); 18 if ( p != NULL ) { 19 printf("found %d at %p\n", *p, p); 20 } else { 21 printf("sorry, not found %d\n", key); 22 } 23 return 0; 24}

[追記] 後出しジャンケンに対応:

ライブラリ関数の利用は考えていないと書いていませんでした。これも含めようと思います。

どうせなら使いまわしの効くコードを書くのがスマートと考えるなら、
qsort みたく配列の型にも要素数にも検索条件にも依存しない検索関数を定義します。

C

1#include <stdio.h> 2#include <stdbool.h> 3 4/* どんな配列が検索対象であっても使えるスマートな検索関数 */ 5void* find_if(const void* base, unsigned int nelem, unsigned int size, bool (*comp)(const void*, const void*), void* arg) { 6 for ( unsigned int i = 0; i < nelem ; ++i ) { 7 if ( comp(base, arg) ) return base; 8 base = (const unsigned char*)base + size; 9 } 10 return NULL; 11} 12 13/* 比較関数: 等しいならば true を返す */ 14bool equals(const void* item, const void* arg) { 15 return *(const int*)item == *(const int*)arg; 16} 17 18int main(void) { 19 int data[5] = { 1, 3, 5, 0, 2 }; 20 21 int key = 3; 22 int* p = (int*)find_if(data, 5, sizeof(int), 23 equals, &key); 24 if ( p != NULL ) { 25 printf("found %d at %p\n", *p, p); 26 } else { 27 printf("sorry, not found %d\n", key); 28 } 29 return 0; 30}

投稿2021/08/14 00:34

編集2021/08/14 06:07
episteme

総合スコア16612

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodox86

2021/08/14 01:40

> コードを書かずに解決するのがいちばんスマートと考えるなら、 > 検索アルゴリズムは書かずにライブラリに任せます。 自らコードを書かないことがバグを含む問題を減らすことにも繋がり、いち意見としても方針が明確と感じましたので高評価させていただきました。
HogeAnimalLover

2021/08/15 02:43 編集

題意にライブラリ使用の可否を書き忘れましたが、追記くださりありがとうございます。ベストアンサーにさせていただきます。
episteme

2021/08/15 02:52

...で、あなたは"なにをもってスマート"としたのでしょうか?
HogeAnimalLover

2021/08/15 03:06 編集

はい。質問当初はy_waiwaiさんの回答がもっとも欲しいもの(当初考えるスマートな記述)でした。 ただし、そもそも「スマート」の方針が曖昧であり、ご指摘の通り出来あえ関数利用やサブルーチン化も適切と考えました。
episteme

2021/08/15 03:55 編集

> 質問当初はy_waiwaiさんの回答がもっとも欲しいもの 一発こっきり/他で使うつもりがないなら僕だってそうします。 # そもそも他に選択肢があるならCでは書かないけどwww
guest

0

C

1for(i = 0; i < N ;i++) { 2 if(VALUE == data[i]) break; 3} 4if(i<N){ 5 //当該データを発見した場合の処理。 6}else{ 7 //当該データが存在しなかった場合の処理。 8}

ってするかなあ、オレなら

投稿2021/08/13 22:25

y_waiwai

総合スコア88024

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

HogeAnimalLover

2021/08/15 02:46

ありがとうございます。質問当初の状況においては最も欲しかった回答でした。
guest

0

話の前提(「検索」という機能で関数化しないことの必要性?)が良く分かりませんが…

【検索して何かするような処理】というのを一塊で書かなくてはならないのだとしても,
それをmain関数内にべた書きせねばならないのでなければ,その処理自体を丸ごと関数にしてやれば良いのでは.
そうすればreturnで抜けれるので,{見つかったとき,見つからなかったとき}を素直に書けるのではないでしょうか.

//何かわからんけど,dataからVALUEを検索して, //見つかったときには何かをするし,見つからなかったときも何かをする void SomeFunc( const ???Type *data, ???Type VALUE ) { for(int i = 0; i < N;i++){ if(VALUE == data[i]){ //データを発見した場合の処理をここで行い,returnする ... return; } } //データ未発見時処理 ... }

投稿2021/08/14 02:18

編集2021/08/14 02:25
fana

総合スコア11954

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fana

2021/08/14 02:23 編集

一塊の【検索して何かするような処理】は,そのプログラム内において相応の役目を担っており,名前も付けれるだろし,IN/OUT を明確にできるはずだし明確にすべき. C言語で書いていて,そういう処理をあえて関数にしない理由(利点)があるのだろうか?
HogeAnimalLover

2021/08/15 02:44

仰るとおり、そもそもサブルーチン化が適切と思います。設計を見直します。
guest

0

C++

1std::vector<int> v{ 3, 3, 4 }; 2if(std::find(v.begin(), v.end(), 1) != v.end()){ 3 std::cout << "found" << std::endl; 4} 5else{ 6 std::cout << "unfound" << std::endl; 7}

これも一般的かと。コンテナによっては、hasメソッドがあることもあります。

投稿2021/08/13 16:27

編集2021/08/15 09:27
majiponi

総合スコア1722

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

HogeAnimalLover

2021/08/15 02:47

ライブラリの使用は考えていませんでしたが、参考になりました。ありがとうございます。
guest

0

スマートとは何をもっていうのでしょうか。
短いことでしょうか。
分かりやすいことでしょうか。

それによっては答えが真逆になると思います。

自分だけがそのコードを弄るなら気にしませんが、他の人が触る可能性があるなら、冗長であろうとも分かりやすいフラグ管理法を使うと思います。(C では大丈夫ですが、他の言語だと for カウンタをその場で宣言することで、for ブロック外で for カウンタの値を使えないこともありますから)

投稿2021/08/13 22:59

tacsheaven

総合スコア13703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

HogeAnimalLover

2021/08/15 02:45

設計、というか方針を見直します。ありがとうございます。
guest

0

こんなイディオムが一般的だと思います。

c

1for(i=0; i<N && VALUE!=data[i]; i++); 2if(i!=N){ 3 //当該データを発見した場合の処理。 4}

投稿2021/08/13 14:56

SaitoAtsushi

総合スコア5675

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

HogeAnimalLover

2021/08/15 02:47

質問当初の状況に置いては欲しかった回答の一つです。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問