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

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

ただいまの
回答率

87.34%

for文などのループが最後まで回ったかを確認する方法

解決済

回答 5

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,550

score 69

QSerialPortInfoを使って接続されているシリアルポートデバイスの一覧から
接続したい対象のデバイスを探し出して、見つけたらQSerialPort::openを使ってデバイスと接続する
という処理を行っています。

    // 接続されているシリアルポートデバイスの一覧から検索。
    for(const QSerialPortInfo &serial_port: QSerialPortInfo::availablePorts())
    {
        // メーカー名から検索。
        if("tyometyome" == serial_port.manufacturer())
        {
            device_serial_port_->setPortName(serial_port.portName());

            if(!device_serial_port_->open(QIODevice::ReadWrite))
            {
                qDebug() << device_serial_port_->error();
                device_serial_port_->close();
            }
            else
            {
                // 成功
            }
            break;
        }
    }


この際に、デバイスは見つかったがQSerialPort::openで失敗したのか
単純にデバイスが見つからなかったのかでエラー表示を分けたいなと思ったのですが

素直に実装するならループが最後まで回ったら見つからなかったという処理にすれば良いので
if("tyometyome" == serial_port.manufacturer())に入った時点で適当なフラグを立てればいいと思ったのですが
どこかのサイトで、今時の高級言語であればやたらにフラグを使わずとも大体は実装できる
というような文を見たのを思い出したので

もしかしたら、「ループが最後まで回ったか?」というようなステータスを取得できる処理がC++の標準やQtにあるのでは?
と思ったので質問させてもらいました
自分なりに検索はしてみたのですがそれっぽいものは見当たらなかったで無いのかなとは思ったのですが
最後に皆様に聞いてみようと思い質問させてもらいました

よろしくお願いします。

追記

コードを修正してみました

    QList<QSerialPortInfo> port_list = QSerialPortInfo::availablePorts();

    // 接続されているシリアルポートデバイスの一覧からメーカー名と一致するものを検索
    auto find_result = std::find_if(port_list.begin(), port_list.end(), [](QSerialPortInfo port){ return "tyometyome" == port.manufacturer(); });
    if(port_list.end() == find_result)
    {
        // 見つからなかった
    }
    else
    {
        device_serial_port_->setPortName(find_result->portName());

        if(!device_serial_port_->open(QIODevice::ReadWrite))
        {
            qDebug() << device_serial_port_->error();
            device_serial_port_->close();
        }
        else
        {
            // 成功
        }
    }
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 5

+4

今時の高級言語であればやたらにフラグを使わずとも大体は実装できる

それは「forループで回す」という構造そのものを取らない、という意味ではないかと思います。

今回の場合、まずはじめにstd::find_ifでデバイスを探す、というのがいいかと思います。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/07/18 10:26

    >それは「forループで回す」という構造そのものを取らない、という意味ではないかと思います
    もっと根本的な部分からだったのですね

    >今回の場合、まずはじめにstd::find_ifでデバイスを探す、というのがいいかと思います
    そんな便利なものが...
    コードを修正してみました、よろしければ評価のほどお願いします

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

    キャンセル

checkベストアンサー

+2

こんにちは。

このケースは私も std::find_if を使うのがスマートと思いますが、std::find_if等のSTLを使えない場合、ラムダ式を使うのも一つです。

#include <iostream>

bool foo()
{
    static int count=0;
    return 6 <= ++count;
}

int main()
{
    bool reachedEnd = []()
        {
            for (int i=0; i < 5; ++i)
            {
                if (foo())
        return false;
            }
            return true;
        }();

    if (reachedEnd)
    {
        std::cout << "Reached the end.\n";
    }
}


wandbox

しかし、C++のラムダ式はキーワードがないので、なかなか読みにくいですね。
フラグ変数を使わないよう if 文の中でラムダ式を呼び出すバージョンもやってみたのですが、止めておいた方が良さそうです。


実は意外にラムダ式とループは相性が良いです。2重ループからの抜け出しは goto を使う、関数へ切り出す、フラグ変数を追加する等しないと無理ですが、関数内で関数を定義するラムダ式なら別のところに関数を定義しなくてもその場でかけるので、短い処理なら見通しがよくなります。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

+2

関数化して戻り値でエラーコードを返すのがいいと思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/07/18 09:37

    やたらにフラグを使うなというのは、構造化しろという意味だと思います。構造化の進んでいないコードはスパゲッティと呼ばれ、バグの温床となります。この質問のコードの場合は構造化のために関数に切り出すことが最善ではないかと思います。

    キャンセル

  • 2019/07/18 10:21

    >やたらにフラグを使うなというのは、構造化しろという意味だと思います
    なるほど、浅く捉えすぎていたみたいですね...
    構造化も意識しつつコードを修正していきたいと思います

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

    キャンセル

+2

std::find_if を利用して、条件に合うものが見つかったらそれに対する処理をする、見つからなかったらその場合の処理を書くというのはいかがでしょうか?

https://cpprefjp.github.io/reference/algorithm/find_if.html

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/07/18 10:28

    >std::find_if を利用して、条件に合うものが見つかったらそれに対する処理をする
    そんなものがあるなんて知りませんでした!
    やはり標準ライブラリをどれだけ知っているかでコードの質が変わりますね...
    コードを修正してみたのでよろしければ評価のほどお願いします

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

    キャンセル

+2

主題とちょっとズレている気もしますが,

「ループが最後まで回ったか?」というようなステータスを取得できる処理

に関しては,とりあえず古典的な(?)のはこんなですよね.
(別途フラグを用意する必要はない)

const int N = 5;
int A[N] = { 1,2,3,4,5 };

//範囲forじゃなくて,自前でiterationのカウンタ(コンテナならばiteratorとか)を扱えばいい
int i=0;
for( ; i<N; ++i )
{
    if( A[i]==3 )break;  //条件次第で途中で抜ける
}

std::cout << ( (i<N) ? "最後まで回った" : "途中で抜けた" ) << std::endl;

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

  • ただいまの回答率 87.34%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

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