2012-09-29 132 views
1

仍然是一個陣列真正的新C,但開始得到了它的竅門....讀入文件到結構用C

我的程序應該從一個數組創建/寫文件和存儲信息的結構。那部分很好。有什麼用是從文件中讀取回結構的空數組麻煩IM ....

這裏是我的結構:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <ctype.h> 

#define MAX 100 

struct Video { 
char name[1024];    //name 
int ranking;    // Number of viewer hits 
char url[1024];    // YouTube URL 
}; 

struct Video Collection[MAX]; 

這裏是我的加載方法,從我的文件讀取回到我的數組結構:

void load() 
{ 
FILE *fileName; 
fileName = fopen("ranking.dbm", "rb"); 
if (fileName != NULL){ 
    fread (Collection,1,1,fileName); 
} 
else { 
    printf("ERROR"); 
} 

} 

也在這裏是我寫的方法:

void save() 
{ 
FILE * pFile; 
pFile = fopen ("Ranking.dbm" , "wb"); 
fwrite (Collection, 1 , sizeof(Collection), pFile); 
fclose (pFile); 
} 

浩wever當我打印出我的陣列collection後加載....其空...即使我可以看到我的文件在項目文件夾中,並打開它,並驗證數據在那裏....

上午我正確認爲我不需要緩衝區,因爲在使用它之前我不需要做任何處理。

也因爲我已經靜態分配空間的內存....我是否正確認爲我可以直接讀入數組?

這裏是我的打印代碼:

void printall() 
{ 
int i; 

printf("\nCollections: \n"); 

for(i = 0; i < tail; i++) 
{ 
    printf("\nVideo Name: %s", Collection[i].name); 
    printf("\nRanking (Hits): %d", Collection[i].ranking); 
    printf("\nURL: %s", Collection[i].url); 
    printf("\n"); 
} 
} 
+1

你能仔細檢查你的來源嗎?在Video結構和Collection的聲明之間,我認爲缺少一些東西。 –

+0

你想要文件是二進制還是文本形式?你關心不同架構上數據文件的可移植性嗎? –

+0

我想你想定義:'結構視頻集合[MAX];' – slashmais

回答

2

我在這裏看到一些問題..首先你如何讀取文件:

fread (Collection,1,1,fileName); 

這將讀取到的收集從fileName 1個字節到Collection
您應該檢查的fread()返回的狀態,當它是成功的,它告訴你的總字節數讀。 (參數2 *參數3,或在你的情況下1 * 1)。

當我修改讀這樣的代碼:

fread(Collection, sizeof(struct Video), 1, fileName); 

它成功地從文件中讀取...但是你現在有一個不同的問題。比方說,你的文件包含在此:

something 5 http://something.com 
nothing 3 http://nothing.com 

所以(我認爲)這是爲您的文件的格式,名稱(ASCII),排名(INT)和URL(ASCII)。現在讓我們假設你的main()功能是這樣的:

int main() 
{ 
    load(); 
    printall(); 
    return 0; 
} 

你儘快回到stdout什麼會是這樣的:

Collections: 

Video Name: something 6 http://something.com 
nothing 3 http://nothing.com 
Ranking (Hits): 0 
URL: 

的原因是因爲你用static聲明您陣列(且非常大)元素。 fread()會嘗試讀取sizeof(struct Video),它是1024 + 4 + 1024字節,所以除非你的每一行都是確切的大小(名稱和url爲1024個字符),否則你會得到看起來很亂的東西或空數據。

我建議閱讀,直到你點擊一個空格,並將每個值存儲在正確的元素,而不是試圖讀出完整的文件到數組中。

編輯:
如果你想填充您的陣列,如:

fread(myarray, sizeofstruct, numberofstructs, file); 

你必須保證數據的長度。在你的例子中,你必須說「名稱是很多字符,空格= 1024」,URL也是一樣的。這似乎是一個可怕的空間浪費。更好的選擇是一個元素在同一時間填充您的陣列:

for(0 to last_element){ 
    set myarray.name = data until first space 
    set myarray.ranking = (int)data until second space 
    set myarray.url = data until newline 
} 

您可以使用fscanf()讀,直到空白。 坦率地說,如果你打算每次填充一個元素,我只是使用字符指針作爲名字和url,並動態分配內存,所以你沒有浪費巨大的數組。

+0

感謝您的詳細回覆!有沒有一種方法來構建我的'save()'方法,以便以更易於讀入的格式寫入文件?例如像'fwrite(Collection,sizeof(struct YouTubeVideo),MAX,pFile);'? – accraze

+0

@SunHypnotic - 這更多的是關於你處理非結構化大小(名稱和網址)的事實,然後你如何存儲它。看到我的編輯,讓我知道如果這回答了你的問題。 – Mike

+0

真棒非常感謝你。這是一個很好的解釋! – accraze

1

首先我必須假設你的意思是struct Video Collection[MAX];否則你的上半部分是無效C.

二:你正在讀1個字節爲收藏。

嘗試 fread(Collection, sizeof(struct Video), MAX, fileName);

這將讀到的sizeof(struct Video)字節MAX倍塊到集合。

+0

所以在我的寫法...我也應該使用'sizeof(struct Video)'而​​不是'sizeof(Collection)'? – accraze

+0

理想情況是。原因是,如果你的寫緩衝區不夠大,不能立刻保存你的整個集合,寫入將會失敗,所以用'struct Video'塊寫入是一個更安全的選擇。通常,每當使用讀/寫時,你總是必須仔細檢查整個緩衝區是否被實際讀取/寫入。 –

4

fread實際上設計爲從文件中讀取結構數組,但必須正確使用它。

fread的四個參數如下:

void * ptr, size_t size, size_t count, FILE * stream 

第一個參數是在哪裏放置數據(在你的情況下,Collection)。第二個參數是每個數組元素的大小:在你的情況下,你想把sizeof(struct Video)。第三個參數是你想要讀取的元素的數量,在你的情況下,MAX。第四個參數是要讀取的文件。

如果您想要讀入像struct Video Collection[MAX]這樣的數組,您可以使用fread(Collection, sizeof(struct Video), MAX, file)fread將返回讀取元素的總數,這將是≤MAX

+0

繼續前進,並嘗試這....但它仍然打印出一個空的數組。我在上面添加了我的寫入方法代碼....它正在將數據寫入文件,但我不確定它是否正確。 – accraze

+0

你如何打印數組? – nneonneo

+0

在上面添加了我的打印代碼...它在寫入/讀取tho之前打印數組時有效... – accraze