我正在慢慢学习C,但不是很好。我一直在阅读有关阅读和写作的无数主题和问题,但我还没有能够找到任何使我点击这一切的内容。
我收到了以下代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100
struct YouTubeVideo {
char video_name[1024]; // YouTube video name
int ranking; // Number of viewer hits
char url[1024]; // YouTube URL
};
struct YouTubeVideo Collection[MAX];
int tail = 0;
//-- Forward Declaration --//
void printall();
void insertion();
void branching(char option);
void menu();
int main()
{
char ch;
// TODO: Add code to load save data from file
printf("\n\nWelcome to CSE240: YouTube Classic Hits\n");
do {
menu();
fflush(stdin); // Flush the standard input buffer
ch = tolower(getchar()); // read a char, convert to lower case
branching(ch);
} while (ch != 'q');
return 0;
}
void menu()
{
printf("\nMenu Options\n");
printf("------------------------------------------------------\n");
printf("i: Insert a new favorite\n");
printf("p: Review your list\n");
printf("q: Save and quit\n");
printf("\n\nPlease enter a choice (i, p, or q) ---> ");
}
void branching(char option)
{
switch(option)
{
case 'i':
insertion();
break;
case 'p':
printall();
break;
case 'q':
// TODO: Add code to save data into a file
break;
default:
printf("\nError: Invalid Input. Please try again...");
break;
}
}
void insertion()
{
if(tail < MAX)
{
printf("\nWhat is the name of the video? (No spaces characters allowed)\n");
scanf("%s", Collection[tail].video_name);
printf("\nHow many viewer hits does this video have?\n");
scanf("%d", &Collection[tail].ranking);
printf("\nPlease enter the URL: ");
scanf("%s", &Collection[tail].url);
tail++;
}
else
{
printf("\nERROR: Your collection is full. Cannot add new entries.\n");
}
}
void printall()
{
int i;
printf("\nCollections: \n");
for(i = 0; i < tail; i++)
{
printf("\nVideo Name: %s", Collection[i].video_name);
printf("\nRanking (Hits): %d", Collection[i].ranking);
printf("\nURL: %s", Collection[i].url);
printf("\n");
}
}
我想编写将集合存储到文件中的代码,以及将加载文件并从中读取的代码。
感谢TA非常有帮助,我能够为每个
制定以下代码void store()
{
FILE * fileName;
fileName = fopen ( "Ranking.dbm" , "wb" );
fwrite ( Collection, sizeof(struct YouTubeVideo), MAX, fileName);
fclose (fileName);
}
和
void read()
{
FILE *fileName;
fileName = fopen("ranking.dbm", "rb");
if (fileName != NULL){
fread ( Collection, sizeof(struct YouTubeVideo), MAX, fileName);
}
else {
printf("ERROR");
}
}
我相信这些都能发挥作用,但真正的问题是我不认为我完全理解如何,我相信因为我甚至不知道它们是如何运作的,所以我不知道如何在代码中使用它们。
我在给定代码中添加了两种方法并提出了这个:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX 100
struct YouTubeVideo {
char video_name[1024]; // YouTube video name
int ranking; // Number of viewer hits
char url[1024]; // YouTube URL
};
struct YouTubeVideo Collection[MAX];
int tail = 0;
//-- Forward Declaration --//
void printall();
void insertion();
void branching(char option);
void menu();
void store();
void read();
int main()
{
char ch;
read();
printf("\n\nWelcome to CSE240: YouTube Classic Hits\n");
do {
menu();
fpurge(stdin); // Flush the standard input buffer
ch = tolower(getchar()); // read a char, convert to lower case
branching(ch);
} while (ch != 'q');
return 0;
}
void menu()
{
printf("\nMenu Options\n");
printf("------------------------------------------------------\n");
printf("i: Insert a new favorite\n");
printf("p: Review your list\n");
printf("q: Save and quit\n");
printf("\n\nPlease enter a choice (i, p, or q) ---> ");
}
void branching(char option)
{
switch(option)
{
case 'i':
insertion();
break;
case 'p':
printall();
break;
case 'q':
store();
break;
default:
printf("\nError: Invalid Input. Please try again...");
break;
}
}
void insertion()
{
if(tail < MAX)
{
printf("\nWhat is the name of the video? (No spaces characters allowed)\n");
scanf("%s", Collection[tail].video_name);
printf("\nHow many viewer hits does this video have?\n");
scanf("%d", &Collection[tail].ranking);
printf("\nPlease enter the URL: ");
scanf("%s", &Collection[tail].url);
tail++;
}
else
{
printf("\nERROR: Your collection is full. Cannot add new entries.\n");
}
}
void printall()
{
int i;
printf("\nCollections: \n");
for(i = 0; i < tail; i++)
{
printf("\nVideo Name: %s", Collection[i].video_name);
printf("\nRanking (Hits): %d", Collection[i].ranking);
printf("\nURL: %s", Collection[i].url);
printf("\n");
}
}
void store()
{
FILE * fileName;
fileName = fopen ( "Ranking.dbm" , "wb" );
if (fileName != NULL)
{
fwrite ( Collection, sizeof(struct YouTubeVideo), MAX, fileName);
fclose (fileName);
}
else {
perror("Following error occurred(): ");
}
}
void read()
{
FILE *fileName;
fileName = fopen("Ranking.dbm", "rb");
if (fileName != NULL)
{
fread ( Collection, sizeof(struct YouTubeVideo), MAX, fileName);
fclose(fileName);
}
else {
perror("Following error occurred with fopen(): ");
}
}
现在我确信任何读过这篇文章的人可能已经面对自己,因为他们看到了问题,但我没有。代码不会创建要写入的文件,同样也没有什么可读的,所以我甚至无法开始看到它有什么问题。 现在我不是在寻找一个给定的答案,但我真的想知道我做错了什么,我似乎不理解的概念,以及如何解决这些问题。我已经对此进行了几个小时的研究,我发现它是基本的,但我真的很想学习。教授说这个话题令人沮丧,只需花费几个小时才能完成。
答案 0 :(得分:2)
您确实应该检查fopen()
对NULL
的返回值 - 如果打开文件时出现问题,它将返回NULL
并设置errno
。这可能是一个权限错误,通过检查返回值并打印错误(如果设置了一个错误),您将获得有关错误的更多信息。
答案 1 :(得分:0)
我相信你可能会遇到read
函数的问题,它不会在文件句柄上调用fclose
(顺便说一下,调用它fileName
有点误导)。
因为您将文件保持打开状态,所以当您最终调用store
时,您很可能无法覆盖该文件。如果无法在该功能中打开文件,则您没有输出任何错误消息,因此很容易在雷达下滑动......至少在您想知道为什么您的文件日期不会改变之前。
否则代码看起来没问题。它只是将数组的全部内容转储出内存并再次读回来。您可能想要做的是写出tail
的值,因为它记录了您保留的元素数量。因此,只需更改代码,请执行以下操作:
fwrite ( &tail, sizeof(int), 1, fileName);
fwrite ( Collection, sizeof(struct YouTubeVideo), MAX, fileName);
当然,您fread
方法中对read
的相应调用。
fread ( &tail, sizeof(int), 1, fileName);
fread ( Collection, sizeof(struct YouTubeVideo), MAX, fileName);
重申:不要忘记关闭文件!!!!
fclose(fileName);
答案 2 :(得分:0)
轻微:确保更频繁地检查诸如fopen,fread,fwrite等的返回值。
温和:你的文件名中有一个潜在的拼写错误(某些操作系统有区分大小写的文件名)
严重:read()没有为尾部设置值......:)