2014-08-28 38 views
9

Tôi có một lớp trông như thế nàyLàm thế nào để lưu trữ một số loại "null" trong C++ đôi hoặc int biến?

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

tôi phải đọc tắt của một tập tin giá trị cho a1, b1, a2, và b2. Hầu hết thời gian, tất cả bốn số đều có trong tệp, nhưng đôi khi chỉ có hai số.

Khi có hai số, tôi muốn lưu trữ các giá trị trong a1b1 và tôi muốn lưu trữ "không có gì" trong a2b2. Nếu a2b2 là con trỏ, tôi có thể chỉ định chúng là nullptr, nhưng chúng không phải là con trỏ.

Có điều gì tôi có thể lưu trữ trong các biến số doubleint để cho biết rằng 'không có gì' được lưu trữ không?

Tôi biết Boost.Optional khả dụng, nhưng tôi đang cố tránh thư viện đó.

+0

Chọn giá trị bạn biết biến sẽ không bao giờ lấy và đặt tên là 'NULL'. Sau đó so sánh các biến với 'NULL'. Lựa chọn đầu tiên thường là 0 hoặc -1 – scohe001

+0

Đó là sự cố, tôi không biết giá trị mà các biến của tôi sẽ không bao giờ có. – jlconlin

+1

@Josh: Không, đừng đặt tên là 'NULL'. Đặt cho nó một cái tên duy nhất không xung đột với thư viện chuẩn. –

Trả lời

8

Bạn có thể gán NAN cho a2 kép, điều này cũng cho biết rằng int b2 không hợp lệ.

This page để sử dụng NAN.

+1

Điều đó có vẻ giống như một giải pháp hợp lý. Điểm khác biệt giữa 'std :: numeric_limits :: quiet_NaN()' và 'std :: nan (" 1 ")' là gì? – jlconlin

+1

Tôi nghĩ rằng quiet_NaN() là thực hiện cụ thể, std :: nan ("1") tạo ra một tập hợp các bit cụ thể. Về thông tin bạn đã cung cấp, nó không quan trọng vì bạn nên sử dụng is_nan() để kiểm tra NaN. – jonas25007

+0

Chỉ là một cảnh báo, bạn muốn sử dụng "NaN" yên tĩnh, nếu không thì thiết lập nó thành NaN có thể làm tăng ngoại lệ dấu chấm động. Nếu bạn không biết nếu bạn có NaNs yên tĩnh hay không, thì bạn không nên sử dụng NaN. –

3

Hoặc bạn có giá trị không hợp pháp hoặc bạn không. Nếu bạn có giá trị không hợp lệ (như -1), hãy sử dụng giá trị đó dưới dạng một dấu bưu điện. Nếu không, thì không. Sử dụng Boost.Optional hoặc cuộn lớp "giá trị cộng với boolean" của riêng bạn.

+0

Nếu bạn sử dụng giá trị bất hợp pháp dưới dạng sentinel, bạn nên thêm xác nhận kiểm tra xem có giá trị nào được cung cấp hợp pháp hay không. – Walter

1
  1. Bạn có thể chọn một giá trị mà không thể tham gia các tập tin văn bản (một giá trị bất hợp pháp), chẳng hạn như 0, -1, std::numeric_limits<int>::max(). Khi bạn xử lý dữ liệu, chỉ sử dụng giá trị nếu nó không bằng giá trị bất hợp pháp (hoặc sentinel).
  2. Bao gồm một bool chỉ ra bao nhiêu giá trị đó là:

    struct A { 
        double a1; 
        int b1; 
        double a2; 
        int b2; 
        bool has_4_nums; 
    }; 
    
  3. Sử dụng một con trỏ (int* hoặc std::unique_ptr<int> theo @ Peter Pei Guo), và gán nullptr khi họ không tồn tại.

3

Bạn không thể. Tôi có thể nghĩ ra hai cách khác nhau:

  1. sử dụng int *; hoặc
  2. Sử dụng giá trị chắc chắn không hợp lệ trong ngữ cảnh của bạn. Ví dụ, nếu nó không bao giờ có thể là tiêu cực, sau đó sử dụng -1 để chỉ ra null. Nhưng tôi vẫn thích cách đầu tiên, vì tính chính xác của nó không phụ thuộc vào yêu cầu hay ngữ cảnh.
+0

Hoặc 'std :: unique_ptr 'vì đây là C++ 11 – matsjoyce

+0

@matsjoyce: Giới thiệu phân bổ động mà bạn không cần nó có lẽ là một ý tưởng tồi, ít nhất là cho hiệu suất. –

+0

Đúng, nhưng để sử dụng 'int *', bạn sẽ phải duy trì một danh sách tất cả các số được sử dụng, để duy trì con trỏ. – matsjoyce

0

Bạn có hai lựa chọn để tránh boost::optional và do đó phụ thuộc để tăng cường:

  • Sử dụng các trình biên dịch std::experimental::optional, trong đó có sẵn từ GCC 4.9+ (và Clang trong các phiên bản gần đây IIRC) với -std=c++14.

  • Sử dụng "triển khai tham chiếu" từ Andrzej Krzemieński cho std::experimental::optional từ GitHub. Đó là tiêu đề duy nhất, vì vậy bạn chỉ có thể sao chép tiêu đề cho dự án của bạn (tất nhiên chú ý đến giấy phép)

1

Dường như bạn sẽ gặp sự cố tiếp tục xuống đường. Sự cần thiết phải biết có bao nhiêu giá trị hợp lệ sẽ được rắc qua cơ sở mã.

Tôi đề xuất có một nhà máy lớp cơ sở. Về cơ bản, bạn sẽ có ít nhất hai lớp:

struct two_values 
{ 
    double a1; 
    int b1; 
}; 

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

Khi một chức năng đòi hỏi một cách rõ ràng bốn giá trị, sử dụng cấu trúc four_values trong tờ khai. Nếu không, hãy sử dụng cấu trúc two_values trong khai báo hàm.

Mối quan hệ này tuyên bố rằng một phiên bản four_values có thể được sử dụng trong bất kỳ chức năng nào yêu cầu cấu trúc two_values.

Alternative
Một cách khác là sử dụng std::vector cho các hạng mục của bạn:

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

Một lợi ích với thiết kế này là các vectơ có thể cho bạn biết có bao nhiêu mặt hàng có và khái niệm được mở rộng, trong trường hợp bạn cần 6 mục.

+0

Trong khi câu hỏi ban đầu là về "không hoạt động" nổi và ints, tôi nghĩ rằng phản ứng này là lời khuyên tốt nhất. Bạn có thể nướng việc xử lý 2 hoặc 4 giá trị vào mô hình đối tượng và làm cho nó sạch sẽ. Nếu bạn cho phép giá trị nullable, bây giờ bạn mở cho mình lên đến 16 kết hợp có thể (2 ** 4) khi trong thực tế, bạn chỉ muốn 2 kết hợp có thể. Bạn sẽ làm gì nếu 'a1' bị vô hiệu, hoặc' a2' bị vô hiệu nhưng không phải là 'b2'? –

0

Ngoài ra, bạn có thể bổ sung thêm thành viên phải biết nếu các thành viên bình thường đã bị ảnh hưởng, một cái gì đó như:

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

hoặc

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
struct A { 
    double a1; 
    int b1; 
    double a2; 
    int b2; 

}; 

cho Bạn chỉ có thể sử dụng bất kỳ loại biến để cho biết liệu hai hoặc bốn giá trị được gán cho biến này hay không.

Giống như có một tên biến được gán = -1

Vì vậy, nếu giá trị đầu vào của bạn là dương tính sau đó nếu hai giá trị là tập tin bên trong thì chỉ cần đảm

a2 = b2 = assigend

Vì vậy, khi bạn đang kiểm tra, sau đó chỉ kiểm tra xem giá trị của a2 và b2 là -1 hay cái gì khác,

Các vấn đề liên quan