请教:反复使用一个struct可以实现吗?

mcmay 2013-10-20 03:19:12
我想试验一下能否反复使用一个struct而不用使用struct数组,写了一个代码,作用是将一个英语词的各个信息存入一个struct然后将这个struct的内容写入file,重复这个过程直到输入者自行退出,最后也是只用一个struct读取file中的内容到屏幕上。代码如下,但达不到预期效果。

/* use struct repeatedly to write and read from a file */

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

#define LEN 41
#define PART 21
#define MAX 256

struct words {
char word[LEN];
char partofspeech[PART];
char meaning[MAX];
char example[MAX];
};

struct words *refreshstruct(void); //通过再次调用刷新struct的内容以供下一次循环使用
void getwordinfo(FILE *);
void showwordinfo(FILE *);

int main(void)
{
struct words * pwords;
FILE * fp;

if((fp = fopen("words.dat", "a+b")) == NULL)
{
fprintf(stderr, "Error opening %s", "wordbank.dat");
exit(EXIT_FAILURE);
}
getwordinfo(fp);
showwordinfo(fp);
fclose(fp);

system("PAUSE");

return 0;
}

struct words *refreshstruct(void)
{
struct words wordinfo; //由于wordinfo是auto类型的,所以每次调用函数都会重新产生
//从而达到刷新struct内容的目的,不知这样行不行
struct words * info = &wordinfo;

return info; //将stuct指针传递给主调函数
}
void getwordinfo(FILE *fp)
{
struct words * info;
puts("Enter the new word to be recorded.");
puts("To quit, press Enter at the beginning of a line.");

info = refreshstruct(); //初次使用struct
while(gets(info->word) != NULL && info->word[0] != '\0')
{
puts("Enter the part of speech: ");
gets(info->partofspeech);
puts("Enter the meaning:");
gets(info->meaning);
puts("Enter example(s): ");
gets(info->example);
fwrite(info, sizeof (struct words), 1, fp);
info = refreshstruct(); //刷新已使用过的struct以备下次使用
puts("Enter the new word to be recorded.");
puts("To quit, press Enter at the beginning of a line.");
}
}

void showwordinfo(FILE *fp)
{
struct words * info;

info = refreshstruct();
rewind(fp);
while(fread(info, sizeof (struct words), 1, fp) == 1)
{
printf("\n%s %s\nMeaning: %s\nExample(s): %s\n",
info->word, info->partofspeech, info->meaning, info->example);
info = refreshstruct();
}
}

以上代码的效果是:
1.可以写入文件,但文件中几乎都是乱码;
2.有的编译器编译出来的可执行文件能够显示文件中的内容,但也是乱码,有的无法显示,有的歇菜。

请问重复使用一个struct在以上的情况中可以实现吗?如果可以,如何实现。如果不行,为什么?我不想用struct数组,一来很浪费内存空间,二来有的编译器无法支持很有较大数目元素的struct数组,例如像以上这样输入词汇信息的struct数组,要是需要一次输入1000词以上,那么建立一个有1000个元素的struct数组就比较麻烦了。
...全文
230 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2013-10-21
  • 打赏
  • 举报
回复
When a file is opened with the "a" or "a+" access type, all write operations occur at the end of the file. The file pointer can be repositioned using fseek or rewind, but is always moved back to the end of the file before any write operation is carried out. Thus, existing data cannot be overwritten. The "a" mode does not remove the EOF marker before appending to the file. After appending has occurred, the MS-DOS TYPE command only shows data up to the original EOF marker and not any data appended to the file. The "a+" mode does remove the EOF marker before appending to the file. After appending, the MS-DOS TYPE command shows all data in the file. The "a+" mode is required for appending to a stream file that is terminated with the CTRL+Z EOF marker. When the "r+", "w+", or "a+" access type is specified, both reading and writing are allowed (the file is said to be open for “update”). However, when you switch between reading and writing, there must be an intervening fflush, fsetpos, fseek, or rewind operation. The current position can be specified for the fsetpos or fseek operation, if desired.
wb_rock 2013-10-21
  • 打赏
  • 举报
回复

void refreshstruct(FILE *fp) 
{
	struct words wordinfo;     
	struct words *pw = &wordinfo;       
	getwordinfo(pw, fp);     
	showwordinfo(pw, fp); 
}
改为

void refreshstruct(FILE *fp) 
{
	struct words wordinfo;    
	getwordinfo(&wordinfo, fp);     
	showwordinfo(&wordinfo, fp); 
}
mcmay 2013-10-20
  • 打赏
  • 举报
回复
刚刚发上去的代码又改了一下,这里重发。不知何时开始不让在原帖上编辑了,也不知如何申请,所以只有浪费网页资源了。事先考虑不周,不好意思。
/* use struct repeatedly to write and read from a file */

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

#define LEN 	41
#define PART 	21
#define MAX     256

struct words {
	char word[LEN];
	char partofspeech[PART];
	char meaning[MAX];
	char example[MAX];
};

void refreshstruct(FILE *);
void getwordinfo(struct words *, FILE *);
void showwordinfo(struct words *, FILE *);

int main(void)
{
	FILE * fp;
	 char choice;

	if((fp = fopen("words.dat", "a+b")) == NULL)
    {
        fprintf(stderr, "Error opening %s", "wordbank.dat");
        exit(EXIT_FAILURE);
    }
	while(1)
    {
        refreshstruct(fp);
        puts("\nContinue? (Y/N)");
	    choice = getchar();
	    choice = toupper(choice);
	    if(choice == 'N')
            break;
        else if(choice == 'Y')
        {
            while(getchar() != '\n')
                continue;
            continue;
        }
        else
        {
            puts("Wrong input! Input again:");
            puts("\nContinue? (Y/N)");
            choice = getchar();
            choice = toupper(choice);
            while(choice != 'Y' && choice != 'N')
            {
                puts("Wrong input! Input again:");
                puts("\nContinue? (Y/N)");
                choice = getchar();
                choice = toupper(choice);
                while(getchar() != '\n')
                    continue;
            }
        }
    }
    fclose(fp);

    system("PAUSE");

	return 0;
}

void refreshstruct(FILE *fp)
{
    struct words wordinfo;
	struct words *pw = &wordinfo;

	getwordinfo(pw, fp);
	showwordinfo(pw, fp);
}

void getwordinfo(struct words *info, FILE *fp)
{
	puts("Enter the new word to be recorded.");
	puts("To quit, press Enter at the beginning of a line.");

	while(gets(info->word) != NULL && info->word[0] != '\0')
	{
		puts("Enter the part of speech: ");
		gets(info->partofspeech);
		puts("Enter the meaning:");
		gets(info->meaning);
		puts("Enter example(s): ");
		gets(info->example);
        fwrite(info, sizeof (struct words), 1, fp);
		puts("Enter the new word to be recorded.");
		puts("To quit, press Enter at the beginning of a line.");
	}
}

void showwordinfo(struct words *info, FILE *fp)
{
    rewind(fp);
	while(fread(info, sizeof (struct words), 1, fp) == 1)
        printf("\n%s %s\nMeaning: %s\nExample(s): %s\n",
               info->word, info->partofspeech, info->meaning, info->example);
}
mcmay 2013-10-20
  • 打赏
  • 举报
回复
感谢wangdahu888,angel_su还有始终都热心助人的zhao4zhong1兄的指正!我一开始就对那个函数返回值问题有点没把握,果然是症结所在。我后来又想了想,改了一种办法,如下:
/* use struct repeatedly to write and read from a file */

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

#define LEN 	41
#define PART 	21
#define MAX     256

struct words {
	char word[LEN];
	char partofspeech[PART];
	char meaning[MAX];
	char example[MAX];
};

void refreshstruct(FILE *); //这里去掉了struct words *返回类型
void getwordinfo(struct words *, FILE *);
void showwordinfo(struct words *, FILE *);

int main(void)
{
	FILE * fp;

	if((fp = fopen("words.dat", "a+b")) == NULL)
    {
        fprintf(stderr, "Error opening %s", "wordbank.dat");
        exit(EXIT_FAILURE);
    }
	while(1) //反复调用refreshstruct以便其中的struct word wordinfo变量不断地重生
    {
        refreshstruct(fp);
        break;    //当refreshstruct停止被调用则退出循环
    }
    fclose(fp);

    system("PAUSE");

	return 0;
}

void refreshstruct(FILE *fp)
{
    struct words wordinfo;
	struct words *pw = &wordinfo;

	getwordinfo(pw, fp);
	showwordinfo(pw, fp);
}

void getwordinfo(struct words *info, FILE *fp)
{
	puts("Enter the new word to be recorded.");
	puts("To quit, press Enter at the beginning of a line.");

	while(gets(info->word) != NULL && info->word[0] != '\0')
	{
		puts("Enter the part of speech: ");
		gets(info->partofspeech);
		puts("Enter the meaning:");
		gets(info->meaning);
		puts("Enter example(s): ");
		gets(info->example);
        fwrite(info, sizeof (struct words), 1, fp);
		puts("Enter the new word to be recorded.");
		puts("To quit, press Enter at the beginning of a line.");
	}
}

void showwordinfo(struct words *info, FILE *fp)
{
    char choice;

    rewind(fp);
	while(fread(info, sizeof (struct words), 1, fp) == 1)
        printf("\n%s %s\nMeaning: %s\nExample(s): %s\n",
               info->word, info->partofspeech, info->meaning, info->example);

	puts("\nContinue? (Y/N)");
	choice = getchar();
	choice = toupper(choice);
	while(choice != 'N')  //这个循环用以退出main()中的循环
    {
        choice = getchar();
        choice = toupper(choice);
    }

}
赵4老师 2013-10-20
  • 打赏
  • 举报
回复
推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。 不要把 fopen("...","...");fscanf,fprintf,fclose //读时把\r\n替换成\n,写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fread,fwrite,fclose //不作以上替换,遇到\x1a仍继续读;读写的内容当字节看待 弄混了 电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址; 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……
hooked 2013-10-20
  • 打赏
  • 举报
回复
用binary写的文件显然就不是你该用记事本之类去看的,那都是内存里的东西写进去的,更何况你的内存一是没初始化,二是本身用的就有问题,当然是些乱码。

/* use struct repeatedly to write and read from a file */

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

#define LEN 	41
#define PART 	21
#define MAX     256

struct words {
    char word[LEN];
    char partofspeech[PART];
    char meaning[MAX];
    char example[MAX];
};

struct words *refreshstruct(void);   //通过再次调用刷新struct的内容以供下一次循环使用
void getwordinfo(FILE *);
void showwordinfo(FILE *);

int main(void)
{
    struct words * pwords;
    FILE * fp;

    if((fp = fopen("words.dat", "a+b")) == NULL)
    {
        fprintf(stderr, "Error opening %s", "wordbank.dat");
        exit(EXIT_FAILURE);
    }
    getwordinfo(fp);
    showwordinfo(fp);
    fclose(fp);

    system("PAUSE");

    return 0;
}

void getwordinfo(FILE *fp)
{
    puts("Enter the new word to be recorded.");
    puts("To quit, press Enter at the beginning of a line.");

    char word[LEN] = {};
    while(gets(word) != NULL && word[0] != '\0')
    {
        struct words info = {};
        strcpy(info.word, word);
        puts("Enter the part of speech: ");
        gets(info.partofspeech);
        puts("Enter the meaning:");
        gets(info.meaning);
        puts("Enter example(s): ");
        gets(info.example);
        fwrite(&info, sizeof (struct words), 1, fp);
        puts("Enter the new word to be recorded.");
        puts("To quit, press Enter at the beginning of a line.");
    }
}

void showwordinfo(FILE *fp)
{
    struct words info;

    rewind(fp);
    while(fread(&info, sizeof (struct words), 1, fp) == 1)
    {
        printf("\n%s %s\nMeaning: %s\nExample(s): %s\n",
            info.word, info.partofspeech, info.meaning, info.example);
    }
}

angel_su 2013-10-20
  • 打赏
  • 举报
回复
简单在getwordinfo、showwordinfo定义“一个”结构变量即可,没必要使用指针。refreshstruct是个典型的错误,返回值指向该函数栈上的数据,结果不可预期,去掉该函数吧...
mcmay 2013-10-20
  • 打赏
  • 举报
回复
引用 3 楼 hooked 的回复:
你打开文件是用binary方式打开,写进去的都是binary的,当然不是可读的。另外,你在refreshstruct里把一个局部变量的地址传出去,这会有内存问题的
谢谢提点!这里的问题不是用binary写进去的问题,只要是char,就算是binary都一样的能在notepade之类的程序里显示字符。只有当写进去的是数值时才有可能显示乱码。这个代码写出的文件里的乱码如下,显然不是用binary格式写文件造成的,倒像是把内存里的代码读了出来。 @> ` . u s e s t r u c t r e p e a t 贲抾?搢 ,? ,? ? 椠" 棾亅,? 鲁亅 8 ` 4 ;  ` ?脀 \? . 堼" ,噟u s e s t r u c t r e p e a t e d l y . e x e > x> j軖|?亅 ? ? @$脀 er 4? i锟w @$脀V蹇w?> p? =鹂w Z鹂w 帱聎 H? 棹" 擻纖?緒Z鹂w4砝w > > 帱聎羹" ?羨 P?a狏 ?> " e羨伏" > 帱聎a狏 ? P?酏" 玄" 瘙" ?" 擻纖繤緒 @> ` . u s e s t r u c t r e p e a t 贲抾?搢 ,? ,? ? 椠" 棾亅,? 鲁亅 8 ` 4 ?  ` ?脀 \? . 堼" ,噟u s e s t r u c t r e p e a t e d l y . e x e > x> j軖|?亅嬧 ? ? $? 皻億瘸亅鲁亅?€| He quitted his job just yesterday. " 旫" 皻億H渶|?€|Aw ?脀 \? @$脀 $ # V蹇w,> " 0w Mw酏" €w酏" # |? L> 棹" 擻纖@%緒 P?a狏 ?> " e羨饵" > 帱聎a狏 ? P?酏" 玄" 瘙" ?" 擻纖繤緒 @> ` . u s e s t r u c t r e p e a t 贲抾?搢 ,? ,? ? 椠" 棾亅,? 鲁亅 8 ` 4 hH  ` ?脀 \? . 堼" ,噟u s e s t r u c t r e p e a t e d l y . e x e > x> j軖|?亅嬧 ? ? $? 皻億瘸亅鲁亅?€| Press the button on the left. day. " 旫" 皻億H渶|?€|Aw ?脀 \? @$脀 V蹇w,> " 0w Mw酏" €w酏" |? L> 棹" 擻纖@%緒 P?a狏 ?> " e羨饵" > 帱聎a狏 ? P?酏" 玄" 瘙" ?" 擻纖繤緒 至于说将本地的变量的地址传了出去,这倒更像是问题的关键,但就不知道错在那里,如何解决。谢谢继续参与!
hooked 2013-10-20
  • 打赏
  • 举报
回复
你打开文件是用binary方式打开,写进去的都是binary的,当然不是可读的。另外,你在refreshstruct里把一个局部变量的地址传出去,这会有内存问题的
mcmay 2013-10-20
  • 打赏
  • 举报
回复
引用 1 楼 wangdahu888 的回复:
将一个英语词的各个信息存入一个struct然后将这个struct的内容写入file,重复这个过程直到输入者自行退出,最后也是只用一个struct读取file中的内容到屏幕上. 你以上述代码实现这样的功能不对吧,要用到序列化与反序列化 建议你读一下<<深入浅出MFC>> 看一下MFC中的序列化与反序列化是怎么实现的
谢谢你的指点!但我还没有学C++,看侯老的那本书无异于看天书。这个问题不知是否还有其他解决办法。
  • 打赏
  • 举报
回复
将一个英语词的各个信息存入一个struct然后将这个struct的内容写入file,重复这个过程直到输入者自行退出,最后也是只用一个struct读取file中的内容到屏幕上. 你以上述代码实现这样的功能不对吧,要用到序列化与反序列化 建议你读一下<<深入浅出MFC>> 看一下MFC中的序列化与反序列化是怎么实现的

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧