如果您要將二進制數據讀入您的程序,那麼您需要查看並查看您正在嘗試讀取的內容。 hexdump
或od
是偉大的工具,用於查看數據:
$ hexdump -C -n 512 dat/acars.bin
00000000 59 56 32 38 32 37 00 4b 43 4c 54 00 4b 53 52 51 |YV2827.KCLT.KSRQ|
00000010 00 00 00 00 2c 83 d0 52 59 56 32 37 38 32 00 4b |....,..RYV2782.K|
00000020 43 4c 54 00 4b 53 52 51 00 00 00 00 cc 3e ed 52 |CLT.KSRQ.....>.R|
00000030 59 56 32 37 33 32 00 4b 43 4c 54 00 4b 53 52 51 |YV2732.KCLT.KSRQ|
00000040 00 00 00 00 88 f4 d5 52 59 56 32 36 37 35 00 4b |.......RYV2675.K|
00000050 43 4c 54 00 4b 53 52 51 00 00 00 00 20 57 9f 52 |CLT.KSRQ.... W.R|
00000060 59 34 39 38 34 31 00 4b 4d 43 4f 00 4d 4d 4d 58 |Y49841.KMCO.MMMX|
根據你的描述,你有航班號,出發機場,目的地機場和時間戳。查看數據,您會發現航班號爲YV2827
(終止爲空),您有KCLT
,這是Charlotte/Douglass Intl的IACO標識符。機場,下一個KSRQ
(佛羅里達州薩拉索塔機場的IACO標識符),接下來是幾個填充字節,最後是一個代表時間戳的4字節數字。所以數據文件很有意義。
現在該如何閱讀?如果您的描述成立,那麼包含元素的結構應該提供讀取數據的方式。您可以有不同成員,不同屬性工作得到填充,以鍛鍊身體,但一些接近下面應該工作:
typedef struct {
char flight[7];
char dept[5];
char dest[5];
unsigned tstamp;
} flight;
接下來,如何讀取該文件,並存儲值內存在你的代碼中。如果您不需要存儲這些值,那麼只需簡單地讀取和打印數據即可。假設您需要將其存儲以實際使用數據,那麼在不知道acars.bin
中包含多少航班的情況下,您需要一種方案來讀取/分配內存以保存數據。
甲靈活的方法是使用一個靜態緩衝讀取每個飛行成,然後使用malloc
/calloc
分配指針數組飛行,並在必要時realloc
保持飛行數據。喜歡的東西:
flight buf = {{0}, {0}, {0}, 0};
flight **flts = NULL;
size_t idx = 0;
size_t nbytes = 0;
...
/* allocate MAXS pointers to flight */
flts = xcalloc (MAXS, sizeof *flts);
/* read into buf until no data read, allocate/copy to flts[i] */
while ((nbytes = fread (&buf, sizeof buf, 1, fp))) {
flts[idx] = calloc (1, sizeof **flts);
memcpy (flts[idx++], &buf, sizeof **flts);
if (idx == maxs) /* if pointer limit reached, realloc */
flts = (flight **)xrealloc_dp((void *)flts, &maxs);
}
以上,代碼分配指針飛行中「FLTS」的初始數量和使用靜態結構buf
作爲緩衝從acars.bin文件中讀取數據。在讀取其中nbytes
被讀取且非零時,分配存儲器用於存儲緩衝區flts[idx]
和memcpy
用於將數據從buf
複製到flts[idx]
。 (你應該添加驗證,即讀取的內容實際上是你期望的)。
標準重分配方案被使用,具有第一分配maxs
指針STRUCT,當達到該數字時,指針的數量經由xrealloc_dp
重新分配給兩次電流量(其爲雙指針宏簡單再分配 - 你也可以使用一個簡單的函數)這裏的目的只是爲了保持代碼的主體乾淨,所以邏輯不會被所有realloc
驗證碼等遮擋。
繼完整閱讀acars.bin,然後您將所有值存儲在flts
(請注意,時間戳存儲爲unsigned int
值,因此轉換爲日曆時間類型並格式化輸出留給y我們的輸出例程)。輸出一個簡單的格式化可能是:
for (i = 0; i < 10; i++) {
time_t fdate = (time_t)flts[i]->tstamp;
printf (" flight[%4zu] %-8s %-5s %-5s %s", i, flts[i]->flight,
flts[i]->dept, flts[i]->dest, ctime (&fdate));
}
其中flts[i]->tstamp
被轉換爲time_t
,然後用ctime
用於與飛行數據的其餘一起提供輸出格式化的日期。
把所有的拼在一起,並理解xcalloc
和xrealloc_dp
只是簡單的錯誤檢查宏calloc
和realloc
,你可以使用類似以下內容。有2778
包含在acars.bin
航班和下面簡單的代碼打印前10的數據和最後10趟:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
/* calloc with error check - exits on any allocation error */
#define xcalloc(nmemb, size) \
({ void *memptr = calloc((size_t)nmemb, (size_t)size); \
if (!memptr) { \
fprintf(stderr, "error: virtual memory exhausted.\n"); \
exit(EXIT_FAILURE); \
} \
memptr; \
})
/* realloc with error check - exits on any allocation error */
#define xrealloc_dp(ptr,nmemb) \
({ \
void **p = ptr; \
size_t *n = nmemb; \
void *tmp = realloc (p, 2 * *n * sizeof tmp); \
if (!tmp) { \
fprintf (stderr, "%s() error: virtual memory exhausted.\n", __func__); \
exit (EXIT_FAILURE); \
} \
p = tmp; \
memset (p + *n, 0, *n * sizeof tmp); /* set new pointers NULL */ \
*n *= 2; \
p; \
})
#define MAXS 256
typedef struct {
char flight[7];
char dept[5];
char dest[5];
unsigned tstamp;
} flight;
int main (int argc, char **argv) {
flight buf = {{0}, {0}, {0}, 0};
flight **flts = NULL;
size_t idx = 0;
size_t nbytes = 0;
size_t maxs = MAXS;
size_t i, index;
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) {
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
/* allocate MAXS pointers to flight */
flts = xcalloc (MAXS, sizeof *flts);
/* read into buf until no data read, allocate/copy to flts[i] */
while ((nbytes = fread (&buf, sizeof buf, 1, fp))) {
flts[idx] = calloc (1, sizeof **flts);
memcpy (flts[idx++], &buf, sizeof **flts);
if (idx == maxs) /* if pointer limit reached, realloc */
flts = (flight **)xrealloc_dp((void *)flts, &maxs);
}
if (fp != stdin) fclose (fp);
printf ("\n There are '%zu' flights in acars data.\n", idx);
printf ("\n The first 10 flights are:\n\n");
for (i = 0; i < 10; i++) {
time_t fdate = (time_t)flts[i]->tstamp;
printf (" flight[%4zu] %-8s %-5s %-5s %s", i, flts[i]->flight,
flts[i]->dept, flts[i]->dest, ctime (&fdate));
}
printf ("\n The last 10 flights are:\n\n");
index = idx - 10;
for (i = index; i < idx; i++) {
time_t fdate = (time_t)flts[i]->tstamp;
printf (" flight[%4zu] %-8s %-5s %-5s %s", i, flts[i]->flight,
flts[i]->dept, flts[i]->dest, ctime (&fdate));
}
/* free memory */
for (i = 0; i < idx; i++)
free (flts[i]);
free (flts);
return 0;
}
輸出
$ ./bin/readacars dat/acars.bin
There are '2778' flights in acars data.
The first 10 flights are:
flight[ 0] YV2827 KCLT KSRQ Fri Jan 10 17:33:00 2014
flight[ 1] YV2782 KCLT KSRQ Sat Feb 1 12:37:00 2014
flight[ 2] YV2732 KCLT KSRQ Tue Jan 14 20:38:00 2014
flight[ 3] YV2675 KCLT KSRQ Wed Dec 4 10:24:00 2013
flight[ 4] Y49841 KMCO MMMX Tue Jul 23 13:25:00 2013
flight[ 5] Y45981 KMCO MMMX Wed Feb 26 13:31:00 2014
flight[ 6] Y45980 MMMX KMCO Tue Mar 25 13:49:00 2014
flight[ 7] Y40981 KMCO MMMX Wed Mar 5 13:23:00 2014
flight[ 8] Y40980 MMMX KMCO Sat Mar 29 11:38:00 2014
flight[ 9] XX0671 KJFK MSLP Tue Mar 25 05:46:00 2014
The last 10 flights are:
flight[2768] 4O2993 KJFK MMMX Wed Feb 12 09:25:00 2014
flight[2769] 1L9221 KSAT KSFB Thu Jan 9 15:41:00 2014
flight[2770] 1L1761 KCID KSFB Tue Jan 14 13:11:00 2014
flight[2771] 1L1625 KABE KSFB Thu Jan 16 10:22:00 2014
flight[2772] 1L0751 KMFE KSFB Thu Jan 16 19:52:00 2014
flight[2773] 1L0697 KTYS KSFB Wed Jan 15 10:21:00 2014
flight[2774] 1L0696 KSFB KTYS Wed Jan 15 07:00:00 2014
flight[2775] 1L0655 KIAG KSFB Fri Jan 17 21:11:00 2014
flight[2776] 1L0654 KSFB KIAG Fri Jan 17 15:49:00 2014
flight[2777] 1L0641 KGFK KSFB Fri Jan 17 14:21:00 2014
MEMOR錯誤/泄漏檢查
在您的寫入動態分配內存的任何代碼中,您必須使用內存錯誤檢查程序來確保你沒有寫超出你分配的內存,並確認你已經釋放了你分配的所有內存。對於Linux valgrind
是正常的選擇。濫用一塊可能導致真正問題的內存塊有很多微妙的方法,沒有理由不這樣做。每個平臺都有類似的內存檢查器。它們使用簡單。通過它來運行你的程序。
$ valgrind ./bin/readacars dat/acars.bin
==12304== Memcheck, a memory error detector
==12304== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==12304== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==12304== Command: ./bin/readacars dat/acars.bin
==12304==
There are '2778' flights in acars data.
The first 10 flights are:
flight[ 0] YV2827 KCLT KSRQ Fri Jan 10 17:33:00 2014
flight[ 1] YV2782 KCLT KSRQ Sat Feb 1 12:37:00 2014
flight[ 2] YV2732 KCLT KSRQ Tue Jan 14 20:38:00 2014
<snip>
flight[2776] 1L0654 KSFB KIAG Fri Jan 17 15:49:00 2014
flight[2777] 1L0641 KGFK KSFB Fri Jan 17 14:21:00 2014
==12304==
==12304== HEAP SUMMARY:
==12304== in use at exit: 0 bytes in 0 blocks
==12304== total heap usage: 2,812 allocs, 2,812 frees, 134,011 bytes allocated
==12304==
==12304== All heap blocks were freed -- no leaks are possible
==12304==
==12304== For counts of detected and suppressed errors, rerun with: -v
==12304== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
134,011
字節分配和所有堆塊被釋放 - 無泄漏是可能確認你釋放你分配的所有內存。 錯誤摘要:來自0個上下文的0錯誤確認分配的內存塊之外沒有無意的寫入。
查看代碼,讓我知道如果您有任何問題,我會很樂意進一步幫助。
你需要做的第一件事是檢查來自fopen和fread的返回值。您的問題可能與未成功打開文件一樣簡單。 –
每個記錄都是24個字節,你的結構是42或74,具體取決於你的系統上的int大小(我們不知道這個大小,你應該使用像int32_t這樣的顯式類型或其他合適的),所以你有個問題。 'int FlightNum [7]'是絕對錯誤的,因爲航班號是字符。 – hobbs
使48或80,我忘了填補之前的最後一場。 – hobbs