2012-09-29 98 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