首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C语言 >

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

2013-11-04 
请教:反复使用一个struct可以实现吗?我想试验一下能否反复使用一个struct而不用使用struct数组,写了一个代

请教:反复使用一个struct可以实现吗?
    我想试验一下能否反复使用一个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数组就比较麻烦了。 struct c
[解决办法]
将一个英语词的各个信息存入一个struct然后将这个struct的内容写入file,重复这个过程直到输入者自行退出,最后也是只用一个struct读取file中的内容到屏幕上.

你以上述代码实现这样的功能不对吧,要用到序列化与反序列化

建议你读一下<<深入浅出MFC>> 看一下MFC中的序列化与反序列化是怎么实现的
[解决办法]
你打开文件是用binary方式打开,写进去的都是binary的,当然不是可读的。另外,你在refreshstruct里把一个局部变量的地址传出去,这会有内存问题的
[解决办法]
简单在getwordinfo、showwordinfo定义“一个”结构变量即可,没必要使用指针。refreshstruct是个典型的错误,返回值指向该函数栈上的数据,结果不可预期,去掉该函数吧...
------解决方案--------------------


用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);
    }
}


[解决办法]
推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。

不要把
fopen("...","...");fscanf,fprintf,fclose //读时把\r\n替换成\n,写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待

fopen("...","...b");fread,fwrite,fclose  //不作以上替换,遇到\x1a仍继续读;读写的内容当字节看待
弄混了

电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址;
人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……

[解决办法]
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.


[解决办法]


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); 
}

热点排行