電子書籍の厳選無料作品が豊富!

Linuxのcpコマンドでは
cp A B でAがBにコピーされますが、
Cの関数strcpy()では
strcpy(A,B) で、BがAにコピーされます

どちらの方向が正解ということは無いですが、混乱してしまいます。
自作の関数でも、その時の気分で方向が一定せず、再利用するときに、混乱してしまいます。

例えば、f(A,B) の標準を代入文と同じ A=B にしておいて、
逆の方向の場合は f_fromtoなど関数名で区別する
というのを思いつきましたが、逆方向の場合の関数名が長くなって使いにくいです。 

混乱を回避するために皆さんが行っている工夫、ありましたら教えてください。

A 回答 (6件)

言い訳がましい理由ですが、「先」になるものを第1引数にすることは良くあります。



というのも、関数に限らず、処理全般には「入力」と「結果」があると思いますが、往々にして結果は一つであり、機能拡張などによって引数が増える要素は入力の方が圧倒的に多いと感じています。なので、もし(下手くそなプログラミングによくありがちな)関数の引数を増やす必要に迫られた場合は、入力にあたるものを引数の後ろに増やしていくことで若干整合性が取りやすいかな、と思います。

例)
func(input, output);

func(input, output, input2, ...);

func(output, input);

func(output, input, input2, ...);

あとは、入力要素が多いときは、No.1の方がかなり否定的に書かれていますが、構造体を使ったりすることは実際にあります。たとえばpthread_create()みたいな感じの使い方です(pthread_create()は引数を4つ取るが、ユーザ定義の情報の引き渡しは第4引数のvoid *に限られる)。
    • good
    • 0
この回答へのお礼

>入力にあたるものを引数の後ろに増やしていくことで若干整合性が取りやすい
なるほど! func(output, input, input2, ...); ですね。

素晴らしい、覚えやすいルールです。
ありがとうございます。

お礼日時:2019/11/12 17:07

#1 で否定してるのは, そういうことじゃない>#4.



例えば strcpy 相当の関数を作るときに
struct strcpy_par {
char *dest;
const char *src;
};
char *strcpy_struct(strcpy_par par);
ってやれば「なんちゃって named argument」になるんだけど, それを全ての関数でやりたいですか? ってこと.
    • good
    • 0
この回答へのお礼

再度の回答、解説ありがとうございます。
参考にさせていただきます。

お礼日時:2019/11/14 07:34

関数のリストを作成するとか


使っているエディタで関数名の上にカーソルを置くとそれを表示させるようなソフトを作るとか
(あ、もちろん私は使っていないです。作るような能力ありませんから)
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
なるほど、取説で解決する方法ですね。
私もそのようなソフトを作る能力ありませんが、そのような解決策もありですね。

お礼日時:2019/11/14 07:32

C言語以外の言語になりますが、関数の第1引数に特別な意味を持たせる場合があります


https://tour.dlang.org/tour/ja/gems/uniform-func …
https://docs.python.org/ja/3/faq/design.html#why …

これらは、関数とメソッドの相互運用性を高めるための工夫ですが、
そもそもの前提として、処理対象は関数の第1引数に指定すべき、
という認識があるようです。

この認識にしたがって、主体となる処理対象が明確な場合は、
方向とは関係なく第1引数に主体を指定させます。
主体を考慮したメソッド名ならば、まず混乱することは無いでしょう。
例)
inputData(主体, 送信元)
outputData(主体, 送信先)

両側が対等で主体が無いならば仕方がないので、
標準関数である memcpy と同じという理由で、
後ろから前に指定させます。
例)
copy(送信先, 送信元)
    • good
    • 0
この回答へのお礼

回答ありがとうございます
主体を関数の第1引数に指定するという考えですね。
いろんな考え方があるのですね。参考にさせていただきます。

お礼日時:2019/11/12 16:32

#1 のポイントは, C99 以降 (#1 では「C99 or after」と書いてしまったが, 英語だと「C99 or later」であるべきかなぁと今思った) では


構造体オブジェクトを構築するときに (構造体の定義の順とは関係なく) メンバーを指定して初期化できる
ことで, 結果として「引数の個数が固定」の場合には順序に関係なく 1つの関数で全て対応できるようになる. 大きな欠点は
・関数ごとに構造体が必要となる
・いちいち構造体オブジェクトを作らなきゃならない
ことで, さすがに面倒くさすぎる.

と, これは完全に冗談で書いた案なわけだけど, 普通には
自分の中で (ある程度) 固定しておく
という作戦を採用するところかなぁ. C の関数だとだいたい
後ろから前
になってるはず (未確認) なので, それに従っておくとか. 少なくとも「その時の気分で方向が一定せず」というのはちょっと, ねぇ.

実現例のある方法としては, 例えば FROM や TO という定数を用意したうえで
copy(FROM, A, TO, B)
と呼び出すってのもあるけど... 関数の中で死にそうな気もするな.
    • good
    • 0
この回答へのお礼

再度、回答ありがとうございます
>自分の中で (ある程度) 固定しておく
そうなんですが、
>少なくとも「その時の気分で方向が一定せず」というのはちょっと, ねぇ.
こちらもそうなんですが、5年、10年と気分を一定させ続けるのもかなり難しいものです。

>C の関数だとだいたい
>後ろから前
Tacosanさんは、このルールで運用中ということでしょうか。参考にさせていただきます。

お礼日時:2019/11/12 08:09

引数を構造体にしちゃえば


なんちゃって named argument
にできる (C99 or after) から完全に解決できる... かな.

できたとしても絶対やらんけど.
    • good
    • 0
この回答へのお礼

回答ありがとうございます

なるほど、構造体にすれば順序関係ないですね。
また copy( from:A, to:B); のようにnamed argumentにできれば、順番は関係ないですね。

>できたとしても絶対やらんけど.
たしかに。逆の方向の場合は f_fromtoなど関数名で区別するのと手間は変わらなそうですね。
でもアイデア感謝します。

お礼日時:2019/11/08 06:54

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!