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

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

ただいまの
回答率

91.24%

  • C

    2701questions

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

  • C++

    2533questions

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

scandir関数を使ったファイルの検索について

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 85

tuyudaku

score 8

早速本題に入らせて貰います

int is_event_device(const struct dirent *dir)
{
    return strncmp("event", dir->d_name, 5) == 0;
}
struct dirent **namelist;
int i, ndev;

ndev = scandir("/dev/input", &namelist, is_event_device, alphasort);

大分省いてソースを書きましたが
このようなC言語のソースがあり、コンパイルも通り
問題なく動作することが確認できました

これを元に既にあるC++のプログラムに組み込もうと思い
以下のように変更しました

int クラス名::is_event_device(const struct dirent *dir)
{
    return strncmp("event", dir->d_name, 5) == 0;
}


変更といいましても、使用したいクラス内に組み込んだだけなので
クラス関数(メソッド?)として追加しただけなのですが
これをコンパイルするとエラーになってしまいました。
エラーはint型をint (*)(struct dirent*)型に変換できないという内容でした

これをクラス外で宣言してソースの「クラス名::」の部分を消すだけで
コンパイルが通るようになりました。
出来ればこれをクラス関数として使いたいため解決法が分かる方居ましたら
教えていただけませんでしょうか?

出来ればこういうエラーになってしまう原因なども分かりましたら教えていただけると嬉しいです。
関数とクラス関数は似ているようで別物なのでしょうか

以上、よろしくお願いいたします

----------追記--------------
クラス宣言

//ファイル名:クラス名.h
namespace 名前
{

//----------------------------------------------------------------------------
// クラス宣言.
//----------------------------------------------------------------------------
class クラス名
{
//----------------------------------------------------------------------------
// 定数定義.
//----------------------------------------------------------------------------


//----------------------------------------------------------------------------
// メンバ関数.
//----------------------------------------------------------------------------
// 公開メンバ関数.
public:


// 非公開メンバ関数.
private:
    int is_event_device(const struct dirent *dir)

//----------------------------------------------------------------------------
// メンバ変数.
//----------------------------------------------------------------------------
// 非公開メンバ変数.
private:

};

}  // namespace 名前

エラー文は
「cannot convert '名前::クラス名::is_event_device' from type 'int (名前::クラス名::)(const dirent*) to type 'int (*)(const dirent*)'」
です

エラーが出ているのは
ndev = scandir("/dev/input", &namelist, is_event_device, alphasort);
のところです

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • Chironian

    2018/01/12 17:43

    C++のクラスの宣言も記載下さい。エラーメッセージはコピペして下さい。エラーメッセージが出ている行も示して下さい。

    キャンセル

  • tuyudaku

    2018/01/12 17:55

    申し訳ありません、補足したのでよろしくお願いいたします。コード内に日本語で書いてある部分は会社のソースのため特定されそうな部分は置き換えてあります。分かりづらくて申し訳ありませんが、よろしくお願いいたします...

    キャンセル

回答 3

+1

(追記2)
試してみてコンパイルが通ったので、コードを載せておきます。

class scandirTest
{
public:
    void callScandir(void){
        struct dirent **namelist;
        int i, ndev;
        ndev = scandir("/dev/input", &namelist, is_event_device, NULL);  
    }
private:
    static int is_event_device(const struct dirent *dir){
        return strncmp("event", dir->d_name, 5) == 0;
    }
};

int main(void){
    class scandirTest *p = new scandirTest();
    p->callScandir();
}


(追記1)
すみません、良く調べずに回答してしまいました。
is_event_deviceはscandirのコールバックとして登録するのですね。
出直します・・・。

以下は忘れてください。

クラスの宣言部分を追記いただいた方が、より良い回答が得られると思います。

勘ですが、そもそもis_event_device関数に渡している変数が間違っていませんか?
エラーメッセージの解釈が正しいのであれば、渡されている変数の型はint型だと言っています。
しかしis_event_device関数はstruct dirent *型を受け取りたいはずです。
scandir関数の戻り値ndevを渡してたりしないでしょうか。
*namelistを渡していますか?

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/12 18:01

    そこが間違っている場合、C言語のコンパイラでも通らないと思っているのですが
    やはり言語が違うと変わってくるのでしょうか...
    自分でも試行錯誤しながら回答を待ちたいと思います

    回答ありがとうございました

    キャンセル

  • 2018/01/12 18:03

    いえ、わざわざありがとうございます
    単純そうで意外と深い部分の問題な気がしてとても困っています

    回答ありがとうございました

    キャンセル

  • 2018/01/12 18:21

    試してみました。
    ただ、出力されるエラーが異なり、static関数でないとダメと言われたので、static宣言しましたところ、コンパイルは通りました
    インスタンス化されていないものをコールバックの対象にはできないでしょうから当然ですね。
    こうしました↓
    static int is_event_device(const struct dirent *dir)

    キャンセル

  • 2018/01/12 18:27

    コードを追記しましたので参考にしてみてください。

    キャンセル

  • 2018/01/15 11:56

    とりあえずstaticにして試してみましたが
    「cannot declare member function 'static int 名前::クラス名::is_event_device(const dirent*)' to have static linkage」
    というエラーが出てしまいました。

    何が違うのでしょうか...

    皆様のアドバイスを参考にもう少し試行錯誤してみたいと思います

    回答ありがとうございました。

    キャンセル

checkベストアンサー

0

こんにちは。

出遅れました。ttyp03さんが回答されている通りstatic関数でないことが原因です。

非staticなメンバ関数は、内部的に this をパラメータで受け取っています。(コンパイラがこっそり付けてます。呼び出し側と呼び出される側両方にです。)
C言語にはそのような機能はありませんので、C言語のコールバック関数を呼ぶことを想定しているライブラリは、当然、thisを渡さないで呼び出しますから、引数リストがずれて異常動作します。それが自明ですので、事前にコンパイラがエラーにしているということなのです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/15 11:56

    とりあえずstaticにして試してみましたが
    「cannot declare member function 'static int 名前::クラス名::is_event_device(const dirent*)' to have static linkage」
    というエラーが出てしまいました。

    何が違うのでしょうか...

    皆様のアドバイスを参考にもう少し試行錯誤してみたいと思います

    回答ありがとうございました。

    キャンセル

  • 2018/01/15 12:43

    staticを付ける場所が違います。
    クラスを宣言している側に付けて下さい。
    関数定義側には付けてはいけません。

    キャンセル

  • 2018/01/15 12:48

    はい、ごめんなさい
    私もそれに気付いてたった今修正したところでした...

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

    分かっていたことですが、自分自身の勉強不足ぶりが遺憾なく発揮されて
    落ち込むばかりです...

    ChironianさんのC++講座がかなり興味深かったので
    これを機に暇な時間(仕事中)に読み進めたいと思います
    買って全然読んでない参考書も読み進めたいです...

    なんとか問題は解決できそうです
    ありがとうございました!

    キャンセル

0

他の方が説明されていますが、

変更といいましても、使用したいクラス内に組み込んだだけなのでクラス関数(メソッド?)として追加しただけなのですが

「関数」を「メンバ関数」という別の物へかえてしまったのですから大問題です。「だけ」じゃありません。

エラー文は「cannot convert '名前::クラス名::is_event_device' from type 'int (名前::クラス名::)(const dirent*) to type 'int (*)(const dirent*)'」です 

といいますが、(名前::クラス名::)は(名前::クラス名::*)のはずです。
エラーメッセージは正確に載せるべきです。
といいますか、このエラーメッセージに「メンバ関数へのポインタ」は「関数へのポインタ」に変換できませんと、はっきり書いてあります^^
クラスのメンバ関数へのポインタについては、C++の基礎なので、参考書をみてください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

ただいまの回答率

91.24%

関連した質問

  • 解決済

    2次元配列のソート

    2次元配列a[n][2]を、<algorithm>ライブラリのsort関数を使ってa[i][0]の値をキーとしてソートすることはできますか?pairを使えばできますが、使わずにでき

  • 解決済

    C++でのファイル分割

    C++のファイル分割について、重複定義の意味と #ifndef の使い方がよく分かりません。 // main.h int funcA(int x); int funcB(

  • 解決済

    構造体に関数ポインタを入れ込みたい

    いつも活用させていただいております。 C++にて、構造体に関数ポインタを入れ込みたいと考えているのですが、 下記のようなコードではBuildエラーになってしまいます。

  • 解決済

    C++で定数を宣言するときの方法について

    こんにちは。 今まで僕は何気なく実装ファイルの上の方にconst修飾子をつけて定数を宣言していましたが、本当にこれで良いのでしょうか? const std::strin

  • 解決済

    [c++] 入れ子になったテンプレートクラスのメンバ関数の特殊化。。。

    こんにちは。タイトル通りですが、入れ子になったテンプレートクラスのメンバ関数の特殊化の方法が分かりません。。。 #include <iostream> // コンテナクラス

  • 解決済

    WebAudioAPIでピッチシフトさせるためのコードについて(JavaScript初心者)

    WebAudioAPIでピッチシフトをさせるためにScriptProcessorNodeを使って実装させようと思ってます。ピッチを二倍するためには波形を再生速度を0.5倍にして0.

  • 解決済

    数字の合計を表示させる方法

    こんにちは。C++で、int a,bにいくつかの数字を入力し、それぞれの合計を表示するプログラムを作りたいのですが、合計を表示させる方法が分かりません。どなたか教えていただけないで

  • 解決済

    multimapの参照がうまくできない(C++)

    C++のmultimapにはデータペアを削除する関数がないため、struct v tmp_vのキーに該当する部分をequal_rangeで取り出したのち、その部分からデータがtmp

同じタグがついた質問を見る

  • C

    2701questions

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

  • C++

    2533questions

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