2010-09-05 23 views
6

Nếu tôi phân bổ một mảng C như thế này:Làm thế nào để kiểm tra xem "thiết lập" trong c

int array[ 5 ]; 

Sau đó, thiết lập chỉ có một đối tượng:

array[ 0 ] = 7; 

Làm thế nào tôi có thể kiểm tra xem tất cả các khác phím (array[1], array[2],…) đang lưu trữ một giá trị? (Trong trường hợp này, tất nhiên, chúng không phải.)

Có chức năng nào như PHP isset() không?

if (isset(array[ 1 ])) ... 
+0

AFAIK Bạn chỉ có thể kiểm tra với 0. – Robus

+1

@Robus Thực tế là không. C mảng không được cho là được khởi tạo tại 0. – log0

Trả lời

6

Không có những thứ như thế này trong C. Nội dung của mảng tĩnh luôn được "đặt". Tuy nhiên, bạn có thể điền vào một số giá trị đặc biệt để giả vờ là không được khởi tạo, ví dụ:

// make sure this value isn't really used. 
#define UNINITIALIZED 0xcdcdcdcd 

int array[5] = {UNINITIALIZED, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED}; 

array[0] = 7; 

if (array[1] != UNINITIALIZED) { 
    ... 
+0

Tôi đoán đây là lựa chọn duy nhất có thể trong C – rano

+0

Cảm ơn, không biết tại sao điều này không xảy ra với tôi trước đây! – pop850

6

Bạn có thể không

giá trị Có tất cả không xác định (như vậy, ngẫu nhiên).

Bạn hoàn toàn có thể loại bỏ tất cả các giá trị để bắt đầu, vì vậy, ít nhất bạn có điểm bắt đầu tốt. Nhưng sử dụng các số ma thuật để phát hiện nếu một đối tượng đã được khởi tạo được coi là thực hành không tốt (nhưng các biến khởi tạo được coi là thực hành tốt).

int array[ 5 ] = {}; 

Nhưng nếu bạn muốn kiểm tra rõ ràng nếu chúng được đặt rõ ràng (không sử dụng số ma thuật) kể từ khi tạo, bạn cần lưu trữ thông tin đó trong cấu trúc khác.

int array[ 5 ] = {}; // Init all to 0 
int isSet[ 5 ] = {}; // Init all to 0 (false) 

int getVal(int index)   {return array[index];} 
int isSet(int index)   {return isSet[index];} 
void setVal(int index,int val) {array[index] = val; isSet[index] = 1; } 
+0

phụ thuộc. c có thể khởi tạo các giá trị (tôi nghĩ nó làm cho các vars tĩnh và toàn cục) – knittl

+1

@knittl: Từ ngữ cảnh của câu hỏi đó là không thể nói, vì vậy tôi đã sai lầm về mặt thận trọng. Và nó không gây tổn hại đến việc khởi tạo một cách rõ ràng bằng cách sử dụng danh sách khởi tạo. –

+0

Không có 'std :: map' trong C. – kennytm

2

Trong C, tất cả các phần tử sẽ có giá trị (rác) tại thời điểm phân bổ. Vì vậy, bạn không thể thực sự có một chức năng giống như những gì bạn đang yêu cầu.

Tuy nhiên, theo mặc định, bạn có thể điền vào một số giá trị chuẩn như 0 hoặc INT_MIN bằng cách sử dụng memset() và sau đó viết một mã isset().

+1

'memset' không thể điền bằng' INT_MIN'. Nó chỉ lấp đầy byte. –

+0

Rác chỉ đúng với phân bổ heap và biến tự động. mảng toàn cầu và tĩnh sẽ được khởi tạo thành 0 nếu không được chỉ định khác. – dmckee

+0

@R .., Trong khi đó là đúng, trên hầu hết các nền tảng hiện đại 'INT_MIN' là' ~ 0', và sẽ điền vào tất cả các phần tử của 'int []' với '-1'. – strager

1

Một giải pháp có lẽ là sử dụng một mảng cờ riêng biệt. Khi bạn gán một trong các phần tử, hãy đặt cờ trong mảng boolean.

Bạn cũng có thể sử dụng con trỏ. Bạn có thể sử dụng con trỏ null để biểu diễn dữ liệu chưa được gán. Tôi đã thực hiện một ví dụ bên dưới:

int * p_array[3] = {NULL,NULL,NULL}; 
     p_array[0] = malloc(sizeof(int)); 
     *p_array[0] = (int)0; 
     p_array[2] = malloc(sizeof(int)); 
     *p_array[2] = (int)4; 
     for (int x = 0; x < 3; x++) { 
      if (p_array[x] != NULL) { 
       printf("Element at %i is assigned and the value is %i\n",x,*p_array[x]); 
      }else{ 
       printf("Element at %i is not assigned.\n",x); 
      } 
     } 

Bạn có thể tạo một hàm phân bổ bộ nhớ và chức năng khác hoạt động như hàm isset trong PHP bằng cách kiểm tra NULL cho bạn.

Tôi hy vọng điều đó sẽ giúp ích cho bạn.

Chỉnh sửa: Đảm bảo bộ nhớ được deallocated sau khi bạn đã hoàn tất. Một chức năng khác có thể được sử dụng để deallocate một số yếu tố hoặc toàn bộ mảng.

Tôi đã sử dụng con trỏ NULL trước để biểu thị dữ liệu chưa được tạo hoặc cần được tạo lại.

2

Tôi không biết php, nhưng một trong hai điều đang xảy ra ở đây

  • mảng php thực sự là một hash-bản đồ (awk nào đó)
  • mảng php đã được lấp đầy với các loại trống

trong cả hai trường hợp có khái niệm "không được đặt" có ý nghĩa cho các giá trị của mảng. Mặt khác, một mảng c được tích hợp sẵn có giá trị một số giá trị trong mọi ô ở mọi thời điểm. Nếu mảng là uninitialized và được tự động hoặc được phân bổ trên đống những giá trị có thể là ngẫu nhiên, nhưng chúng tồn tại.

Để có được hành vi php:

  • Thực hiện (hoặc tìm một wit thư viện) và sử dụng một hashmap thay vì trên một mảng.
  • Biến nó thành một mảng cấu trúc bao gồm trường isNull.
  • Khởi tạo mảng thành một số giá trị sentinal trong tất cả các ô.
+0

+1 để hiển thị sự khác biệt giữa PHP và C – alex

1

Cách tiếp cận mà tôi thích là tạo 2 mảng, một mảng gắn cờ bit mà chỉ mục của mảng được đặt và giá trị còn lại chứa giá trị thực. Ngay cả trong trường hợp bạn không cần phải biết liệu một mục trong mảng có được "đặt" hay không, nó có thể là một tối ưu hóa hữu ích. Việc tạo bit mảng bit 1 bit cho mỗi phần tử nhanh hơn rất nhiều so với việc khởi tạo mảng 8 byte cho mỗi phần tử là size_t, đặc biệt nếu mảng sẽ vẫn còn thưa thớt (hầu hết là không được lấp đầy) cho toàn bộ thời gian tồn tại của nó.

Một ví dụ thực tế mà tôi đã sử dụng thủ thuật này nằm trong chức năng tìm kiếm chuỗi con, sử dụng bảng bỏ qua ký tự xấu kiểu Boyer-Moore. Bảng yêu cầu 256 mục nhập loại size_t, nhưng chỉ những cái tương ứng với các ký tự thực sự xuất hiện trong chuỗi kim cần được lấp đầy. Một 1kb (hoặc 2kb trên 64-bit) memset sẽ thống trị sử dụng cpu trong trường hợp tìm kiếm rất ngắn, dẫn đầu triển khai khác để ném xung quanh chẩn đoán cho dù có hay không sử dụng bảng. Nhưng thay vào đó, tôi để cho bảng bỏ qua đi uninitialized, và sử dụng một bit bit 256-bit (chỉ 32 byte để nuôi để memset) để cờ mà mục được sử dụng.

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