web-dev-qa-db-ja.com

C ++ doubleまたはint変数にある種の「null」を格納する方法は?

このようなクラスがあります

struct A {
     double a1;
     int b1;
     double a2;
     int b2;
};

a1b1a2、およびb2のファイル値を読み取る必要があります。ほとんどの場合、4つの数値すべてがファイルにありますが、2つの数値しか存在しない場合もあります。

2つの数値がある場合、a1およびb1に値を格納し、a2およびb2に「何も」格納しないようにします。 a2b2がポインターである場合、それらをnullptrに割り当てることができますが、それらはポインターではありません。

「何も」保存されていないことを示すために、doubleおよびint変数に保存できるものはありますか?

Boost.Optionalが利用可能であることは知っていますが、そのライブラリを避けようとしています。

12
jlconlin

NANをdouble a2に割り当てると、int b2が無効であることも示されます。

このページ NANの使用。

9
jonas25007

正当でない値を持っているか、そうでないかのどちらかです。無効な値(-1など)がある場合は、それを番兵として使用します。そうでない場合は、いいえ。 Boost.Optional を使用するか、独自の「値とブール値」クラスをロールします。

4
David Schwartz

できません。私は2つの代替方法を考えることができます:

  1. int *を使用します;または
  2. コンテキストで確実に無効な値を使用してください。たとえば、負にならない場合は、-1を使用してNULLを示します。しかし、その正確さは要件やコンテキストに依存しないため、私はまだ最初の方法を好みます。
4
Peter Pei Guo

今後さらに問題が発生するようです。有効な値の数を知る必要性は、コードベースに振りかけられます。

factoryおよびbase classを持つことをお勧めします。基本的に、少なくとも2つのクラスがあります。

struct two_values
{
  double a1;
  int    b1;
};

struct four_values : public two_values
{
  double a2;
  int    b2;
};

関数が明示的に4つの値を必要とする場合、宣言でfour_values構造を使用します。それ以外の場合は、関数宣言でtwo_values構造を使用します。

この関係は、four_values構造を必要とする関数でtwo_valuesインスタンスを使用できることを示しています。

代替
別の方法は、アイテムにstd::vectorを使用することです:

struct Container
{
  std::vector<double> a_values;
  std::vector<int>    b_values;
};

このデザインの利点は、6つのアイテムが必要な場合に、ベクターがアイテムの数を教えてくれ、コンセプトが拡張可能であることです。

2
Thomas Matthews
  1. _0_、_-1_、std::numeric_limits<int>::max()など、テキストファイルに含まれない値(不正な値)を選択できます。データを処理するとき、不正な値(またはセンチネル)と等しくない場合にのみ値を使用します。
  2. 値がいくつあるかを示すブールを含めます。

    _struct A {
        double a1;
        int b1;
        double a2;
        int b2;
        bool has_4_nums;
    };
    _
  3. ポインター(_int*_または@Peter Pei Guoによる_std::unique_ptr<int>_)を使用し、存在しない場合はnullptrを割り当てます。

1
matsjoyce

boost::optionalを回避するための2つのオプションがあり、Boostへの依存関係があります。

  • コンパイラの std::experimental::optional を使用します。これは、GCC 4.9+(および最近のバージョンIIRCのClang)から-std=c++14で使用できます。

  • GitHub からのstd::experimental::optionalには、AndrzejKrzemieńskiの「参照実装」を使用します。これはヘッダーのみなので、ヘッダーをプロジェクトにコピーするだけです(もちろん、ライセンスに注意してください)

0
Daniel Frey
struct A {
     double a1;
     int b1;
     double a2;
     int b2;

};

このため、任意のタイプの変数を使用して、これらの変数に2つまたは4つの値が割り当てられているかどうかを示すことができます。

割り当てられた変数名を取る= -1

入力値が正の場合、2つの値がファイル内にある場合は、

a2 = b2 = assigend

したがって、チェックするときは、a2とb2の値が-1または他の値であるかどうかをチェックするだけです。

0
Robin Halder

または、通常のメンバーが影響を受けているかどうかを知るために、次のような追加のメンバーを追加できます。

struct A {
     double a1;
     int b1;
     double a2;
     int b2;
     bool is_assigned[4];
};

または

struct A {
     double a1;
     int b1;
     double a2;
     int b2;
     double* p_a1; // point to a1 when initialized, else nullptr
     int* p_b1;    // point to b1 when initialized, else nullptr
     double* p_a2; // point to a2 when initialized, else nullptr
     int* p_b1;    // point to b2 when initialized, else nullptr
};
0
Jarod42