回 帖 发 新 帖 刷新版面

主题:读写文件问题

由于对文件这块内容不是很了解
麻烦大虾帮我编写下以下两个读写文件的程序 让我参考下 谢谢:
1.编写一个程序,用来从键盘读取本班同学的期末成绩,并把成绩保存在score.txt文件中。score.txt文件内容如下:
number   Chinese    English    C
1        87         76         67
2        67         87         65
3        76         88         87
4        46         89         88
2.编写一个程序,用来读取上题创建的score.txt数据文件,并计算其平均成绩和期末总成绩。把计算结果存在statisti.txt文件中,并输出成绩有不及格的学生的学号。其格式如下:
number   Chinese    English    C       total  average
1        87         76         67      230    76.67
2        67         87         65      219    73
3        76         88         87      251    83.67
4        46         89         88      223    74.3

回复列表 (共12个回复)

沙发

用c或者c++都可以

板凳

QQ1285305730

3 楼

随手写的,可能有错。


#include <stdio.h>

#define NO_DATA 0  // 没有数据了
#define A_DATA  1  // 还有数据

typedef struct 
  { double   average;
    unsigned total;
    unsigned id;
    unsigned score[3];
  } Student;


int
read_data (Student *stu, FILE *f)
{                 /** 读取数据 **/         
  int n;
  unsigned * sco = stu -> score;

  n = fscanf (f, "%u", &stu->id);
  if (n != 1  || stu->id == 0)
    return NO_DATA;
 
  n = fscanf (f, "%u%u%u", sco, sco+1, sco+2);
  if (n != 3)
    return NO_DATA;
  stu -> total = sco[0] + sco[1] +sco[2];
  stu -> average = stu -> total / 3.0;
  return A_DATA;
}

void
write1_data (Student *stu, FILE *f)
{                 /** 向score.txt写入数据 **/     
  unsigned * sco = stu -> score;
  fprintf (f, "%-9u%-9u%-9u%-9u\n", stu->id, 
          sco[0], sco[1], sco[2] );
}
void 
write2_data (Student *stu, FILE *f)
{                 /** 向score.txt写入数据 **/ 
  unsigned * sco = stu -> score;
  fprintf (f, "%-9u%-9u%-9u%-9u%-9u%-.2lf\n", stu->id, 
          sco[0], sco[1], sco[2], stu->total, stu->average );
}

int main (void)
{
  char buf[1024];
  FILE *f1, *f2;
  Student stu;
  
  f1 = fopen ("score.txt", "w");
  fprintf (f1, "%-9s%-9s%-9s%-9s\n",
         "number", "Chinese", "English", "C");
  while (read_data (&stu, stdin) == A_DATA)
      write1_data (&stu, f1);
  
  fclose (f1);
  f1 = fopen ("score.txt", "r");
  f2 = fopen ("statisti.txt", "w");
  fprintf (f2, "%-9s%-9s%-9s%-9s%-9s%-9s\n",
         "number", "Chinese", "English", "C", "total", "average");
  fgets (buf, 1024, f1);
  while (read_data (&stu, f1) == A_DATA)
      write2_data (&stu, f2);
  
  fclose (f1);
  fclose (f2);
  return 0;
}

4 楼

这个还是自己锻炼写!我这有资料函数给你参考!!!

5 楼

关于文件操作的函数!!!
基于C的文件操作 



    在ANSI C中,对文件的操作分为两种方式,即流式文件操作和I/O文件操作,下面就分别介绍之。 
     ReadFile(fp,buffer,fileLen,&bufferLen,NULL);
    BOOL ReadFile(   HANDLE hFile, //文件的句柄  
     LPVOID lpBuffer, //用于保存读入数据的一个缓冲区 
      DWORD nNumberOfBytesToRead, //要读入的字符数  
     LPDWORD lpNumberOfBytesRead, //指向实际读取字节数的指针   LPOVERLAPPED lpOverlapped //如文件打开时指定了FILE_FLAG_OVERLAPPED,那么必须,用这个参数引用一个特殊的结构。该结构定义了一次异步读取操作。否则,应将这个参数设为NULL   );
    功能说明:
     从文件指针指向的位置开始将数据读出到一个文件中, 且支持同步和异步操作,   如果文件打开方式没有指明FILE_FLAG_OVERLAPPED的话,当程序调用成功时,它将实际读出文件的字节数保存到lpNumberOfBytesRead指明的地址空间中。   如果文件要交互使用的话,当函数调用完毕时要记得调整文件指针。   从文件中读出数据。与fread函数相比,这个函数要明显灵活的多。该函数能够操作通信设备、管道、套接字以及邮槽。
C参数说明:
HANDLE hFile, 需要写入数据的文件指针,这个指针指向的文件必须是GENERIC_READaccess 访问属性的文件。   LPOVERLAPPED lpOverlapped OVERLAPPED结构体指针,如果文件是以FILE_FLAG_OVERLAPPED方式打开的话,那么这个指针就不能为NULL。
返回值:
 调用成功,返回非0   调用不成功,返回为0   会设置GetLastError。如启动的是一次异步读操作,则函数会返回零值,并将ERROR_IO_PENDING设置成GetLastError的结果。如结果不是零值,但读入的字节数小于nNumberOfBytesToRead参数指定的值,表明早已抵达了文件的结尾。
BOOL WriteFile(   HANDLE hFile, // 文件句柄   
LPCVOID lpBuffer, // 数据缓存区指针   
DWORD nNumberOfBytesToWrite, // 你要写的字节数   
LPDWORD lpNumberOfBytesWritten, // 用于保存实际写入字节数的存储区域的指针   LPOVERLAPPED lpOverlapped // OVERLAPPED结构体指针   );
从文件指针指向的位置开始将数据写入到一个文件中, 且支持同步和异步操作,   如果文件打开方式没有指明FILE_FLAG_OVERLAPPED的话,当程序调用成功时,它将实际写入文件的字节数保存到lpNumberOfBytesWriten指明的地址空间中   如果文件要交互使用的话,当函数调用完毕时要记得调整文件指针
 HANDLE hFile, 需要写入数据的文件指针,这个指针指向的文件必须是GENERIC_WRITE access 访问属性的文件   LPOVERLAPPED lpOverlapped OVERLAPPED结构体指针,如果文件是以FILE_FLAG_OVERLAPPED方式打开的话,那么这个指针就不能为NULL
调用成功,返回非0   调用不成功,返回为0
HANDLE CreateFile(   LPCTSTR lpFileName, //指向文件名的指针   DWORD dwDesiredAccess, //访问模式(写/读)   DWORD dwShareMode, //共享模式   LPSECURITY_ATTRIBUTES lpSecurityAttributes, //指向安全属性的指针   DWORD dwCreationDisposition, //如何创建   DWORD dwFlagsAndAttributes, //文件属性   HANDLE hTemplateFile //用于复制文件句柄   ); 

参数列表   lpFileName String 要打开的文件的名或设备名。这个字符串的最大长度在ANSI版本中为MAX_PATH,在unicode版本中为32767。   dwDesiredAccess Long 如果为 GENERIC_READ 表示允许对设备进行读访问;如果为 GENERIC_WRITE 表示允许对设备进行写访问(可组合使用);如果为零,表示只允许获取与一个设备有关的信息   dwShareMode Long, 零表示不共享; FILE_SHARE_READ 和/或 FILE_SHARE_WRITE 表示允许对文件进行共享访问   lpSecurityAttributes SECURITY_ATTRIBUTES, 指向一个SECURITY_ATTRIBUTES结构的指针,定义了文件的安全特性(如果操作系统支持的话)   dwCreationDisposition Long,下述常数之一:   CREATE_NEW 创建文件;如文件存在则会出错   CREATE_ALWAYS 创建文件,会改写前一个文件   OPEN_EXISTING 文件必须已经存在。由设备提出要求   OPEN_ALWAYS 如文件不存在则创建它   TRUNCATE_EXISTING 讲现有文件缩短为零长度   dwFlagsAndAttributes Long, 一个或多个下述常数   FILE_ATTRIBUTE_ARCHIVE 标记归档属性   FILE_ATTRIBUTE_COMPRESSED 将文件标记为已压缩,或者标记为文件在目录中的默认压缩方式   FILE_ATTRIBUTE_NORMAL 默认属性

6 楼

FILE_ATTRIBUTE_HIDDEN 隐藏文件或目录   FILE_ATTRIBUTE_READONLY 文件为只读   FILE_ATTRIBUTE_SYSTEM 文件为系统文件   FILE_FLAG_WRITE_THROUGH 操作系统不得推迟对文件的写操作   FILE_FLAG_OVERLAPPED 允许对文件进行重叠操作   FILE_FLAG_NO_BUFFERING 禁止对文件进行缓冲处理。文件只能写入磁盘卷的扇区块   FILE_FLAG_RANDOM_ACCESS 针对随机访问对文件缓冲进行优化   FILE_FLAG_SEQUENTIAL_SCAN 针对连续访问对文件缓冲进行优化   FILE_FLAG_DELETE_ON_CLOSE 关闭了上一次打开的句柄后,将文件删除。特别适合临时文件   也可在Windows NT下组合使用下述常数标记:   SECURITY_ANONYMOUS, SECURITY_IDENTIFICATION, SECURITY_IMPERSONATION, SECURITY_DELEGATION, SECURITY_CONTEXT_TRACKING, SECURITY_EFFECTIVE_ONLY   hTemplateFileLong, 如果不为零,则指定一个文件句柄。新文件将从这个文件中复制扩展属性
如执行成功,则返回文件句柄。   INVALID_HANDLE_VALUE表示出错,会设置GetLastError。即使函数成功,但若文件存在,且指定了CREATE_ALWAYS 或 OPEN_ALWAYS,GetLastError也会设为ERROR_ALREADY_EXISTS

一、流式文件操作 
  这种方式的文件操作有一个重要的结构FILE,FILE在stdio.h中定义如下: 

typedef struct { 
int level; /* fill/empty level of buffer */ 
unsigned flags; /* File status flags */ 
char fd; /* File descriptor */  < type="text/javascript"> < type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js">  


unsigned char hold; /* Ungetc char if no buffer */ 
int bsize; /* Buffer size */ 
unsigned char _FAR *buffer; /* Data transfer buffer */ 
unsigned char _FAR *curp; /* Current active pointer */ 
unsigned istemp; /* Temporary file indicator */ 
short token; /* Used for validity checking */ 
} FILE; /* This is the FILE object */ 

  FILE这个结构包含了文件操作的基本属性,对文件的操作都要通过这个结构的指针来进行,此种文件操作常用的函数见下表函数功能 
fopen() 打开流 
fclose() 关闭流 
fputc() 写一个字符到流中 
fgetc() 从流中读一个字符 
fseek() 在流中定位到指定的字符 
Ftell()计算文件字节长度
fputs() 写字符串到流 
fgets() 从流中读一行或指定个字符 
fprintf() 按格式输出到流 
fscanf() 从流中按格式读取 
feof() 到达文件尾时返回真值 
ferror() 发生错误时返回其值 
rewind() 复位文件定位器到文件开始处 
remove() 删除文件 
fread() 从流中读指定个数的字符 
fwrite() 向流中写指定个数的字符 
tmpfile() 生成一个临时文件流 
tmpnam() 生成一个唯一的文件名 
Rewind()   功 能: 将文件内部的位置指针重新指向一个流(数据流/文件)的开头   注意:不是文件指针而是文件内部的位置指针,随着对文件的读写文件的位置指针(指向当前读写字节)向后移动。而文件指针是指向整个文件,如果不重新赋值文件指针不会改变。 
用法::Rewind(fp)
  下面就介绍一下这些函数 

1.fopen() 
  fopen的原型是:FILE *fopen(const char *filename,const char *mode),fopen实现三个功能 

为使用而打开一个流 
把一个文件和此流相连接 
给此流返回一个FILR指针 
参数filename指向要打开的文件名,mode表示打开状态的字符串,其取值如下表 

字符串 含义 
"r" 以只读方式打开文件 
"w" 以只写方式打开文件 
"a" 以追加方式打开文件 
"r+" 以读/写方式打开文件,如无文件出错 
"w+" 以读/写方式打开文件,如无文件生成新文件 

  一个文件可以以文本模式或二进制模式打开,这两种的区别是:在文本模式中回车被当成一个字符'\n',而二进制模式认为它是两个字符0x0D,0x0A;如果在文件中读到0x1B,文本模式会认为这是文件结束符,也就是二进制模型不会对文件进行处理,而文本方式会按一定的方式对数据作相应的转换。 

  系统默认的是以文本模式打开,可以修改全部变量_fmode的值来修改这个设置,例如_fmode=O_TEXT;就设置默认打开方式为文本模式;而_fmode=O_BINARY;则设置默认打开方式是二进制模式。 

  我们也可以在模式字符串中指定打开的模式,如"rb"表示以二进制模式打开只读文件,"w+t"或"wt+"表示以文本模式打开读/写文件。 

  此函数返回一个FILE指针,所以申明一个FILE指针后不用初始化,而是用fopen()来返回一个指针并与一个特定的文件相连,如果成败,返回NULL。 

例: 

  FILE *fp; 
  if(fp=fopen("123.456","wb")) 
    puts("打开文件成功"); 
  else 
    puts("打开文件成败"); 

7 楼

2.fclose() 
  fclose()的功能就是关闭用fopen()打开的文件,其原型是:int fclose(FILE *fp);如果成功,返回0,失败返回EOF。 

  在程序结束时一定要记得关闭打开的文件,不然可能会造成数据丢失的情况,我以前就经常犯这样的毛病。 

例:fclose(fp); 

3.fputc() 
  向流写一个字符,原型是int fputc(int c, FILE *stream); 成功返回这个字符,失败返回EOF。 

例:fputc('X',fp); 

4.fgetc() 
  从流中读一个字符,原型是int fputc(FILE *stream); 成功返回这个字符,失败返回EOF。 

例:char ch1=fgetc(fp); 

5. fseek() 
  此函数一般用于二进制模式打开的文件中,功能是定位到流中指定的位置,原型是int fseek(FILE *stream, long offset, int whence);如果成功返回0,参数offset是移动的字符数,whence是移动的基准,取值是 

符号常量 值 基准位置 
SEEK_SET 0 文件开头 
SEEK_CUR 1 当前读写的位置 
SEEK_END 2 文件尾部 
int fseek( FILE *stream, long offset, int origin );   第一个参数stream为文件指针   第二个参数offset为偏移量,正数表示正向偏移,负数表示负向偏移   第三个参数origin设定从文件的哪里开始偏移,可能取值为:SEEK_CUR、 SEEK_END 或 SEEK_SET   SEEK_SET: 文件开头   SEEK_CUR: 当前位置   SEEK_END: 文件结尾   其中SEEK_SET,SEEK_CUR和SEEK_END依次为0,1和2. 
ftell(fp);利用函数 ftell() 也能方便地知道一个文件的长。如以下语句序列: fseek(fp, 0L,SEEK_END); len =ftell(fp); 首先将文件的当前位置移到文件的末尾,然后调用函数ftell()获得当前位置相对于文件首的位移,该位移值等于文件所含字节数。


例:fseek(fp,1234L,SEEK_CUR);//把读写位置从当前位置向后移动1234字节(L后缀表示长整数) 

  fseek(fp,0L,2);//把读写位置移动到文件尾 

6.fputs() 
  写一个字符串到流中,原型int fputs(const char *s, FILE *stream); 

例:fputs("I Love You",fp); 

7.fgets() 
  从流中读一行或指定个字符,原型是char *fgets(char *s, int n, FILE *stream); 从流中读取n-1个字符,除非读完一行,参数s是来接收字符串,如果成功则返回s的指针,否则返回NULL。 

例:如果一个文件的当前位置的文本如下 

Love ,I Have 

But ........ 

如果用 

  fgets(str1,4,file1); 

则执行后str1="Lov",读取了4-1=3个字符,而如果用 

  fgets(str1,23,file1); 

则执行str="Love ,I Have",读取了一行(不包括行尾的'\n')。 

8.fprintf() 
  按格式输入到流,其原型是int fprintf(FILE *stream, const char *format[, argument, ...]);其用法和printf()相同,不过不是写到控制台,而是写到流罢了 

例:fprintf(fp,"%2d%s",4,"Hahaha"); 

9.fscanf() 
  从流中按格式读取,其原型是int fscanf(FILE *stream, const char *format[, address, ...]);其用法和scanf()相同,不过不是从控制台读取,而是从流读取罢了。 

例:fscanf(fp,"%d%d" ,&x,&y); 

10.feof() 
  检测是否已到文件尾,是返回真,否则返回0,其原型是int feof(FILE *stream); 

例:if(feof(fp))printf("已到文件尾"); 

11.ferror() 
  原型是int ferror(FILE *stream);返回流最近的错误代码,可用clearerr()来清除它,clearerr()的原型是void clearerr(FILE *stream); 

例:printf("%d",ferror(fp)); 

12.rewind() 
  把当前的读写位置回到文件开始,原型是void rewind(FILE *stream);其实本函数相当于fseek(fp,0L,SEEK_SET); 

例:rewind(fp); 

12.remove() 
  删除文件,原型是int remove(const char *filename); 参数就是要删除的文件名,成功返回0。 

例:remove("c:\\io.sys"); 

13.fread() 
  从流中读指定个数的字符,原型是size_t fread(void *ptr, size_t size, size_t n, FILE *stream);参数ptr是保存读取的数据,void*的指针可用任何类型的指针来替换,如char*、int *等等来替换;size是每块的字节数;n是读取的块数,如果成功,返回实际读取的块数(不是字节数),本函数一般用于二进制模式打开的文件中。 

例: 

  char x[4230]; 
  FILE *file1=fopen("c:\\msdos.sys","r"); 
  fread(x,200,12 ,file1);//共读取200*12=2400个字节 

14.fwrite() 
  与fread对应,向流中写指定的数据,原型是size_t fwrite(const void *ptr, size_t size, size_t n, FILE *stream);参数ptr是要写入的数据指针,void*的指针可用任何类型的指针来替换,如char*、int *等等来替换;size是每块的字节数;n是要写的块数,如果成功,返回实际写入的块数(不是字节数),本函数一般用于二进制模式打开的文件中。 

例: 

  char x[]="I Love You"; 
  fwire(x, 6,12,fp);//写入6*12=72字节 

  将把"I Love"写到流fp中12次,共72字节 

15.tmpfile() 
  其原型是FILE *tmpfile(void); 生成一个临时文件,以"w+b"的模式打开,并返回这个临时流的指针,如果失败返回NULL。在程序结束时,这个文件会被自动删除。 

例:FILE *fp=tmpfile(); 

16.tmpnam(); 
  其原型为char *tmpnam(char *s); 生成一个唯一的文件名,其实tmpfile()就调用了此函数,参数s用来保存得到的文件名,并返回这个指针,如果失败,返回NULL。

8 楼

自己慢慢看吧!!!

9 楼

楼上在哪儿粘的资料???
ANSI C里竟然有ReadFile?不带这么坑爹的!还有C/C++是大小写敏感的,不要把rewind写成Rewind。。。

再有就是:下划线开头的东西是标准不予以支持的“扩展”,需慎用。

10 楼

T1:
[code=c]
#include <stdio.h>
#include <stdlib.h>

#define MyFlush() getc(stdin)
#define N 20

typedef struct SCORE
{
    int num;
    int chi;
    int eng;
    int c;
}SCORE_STU[N];

int  Input_Score(SCORE_STU score_stu);
void Write_In_File(SCORE_STU score_stu, int stu_num);


int main(int argc, char *argv[])
{
        
    SCORE_STU score_stu;
    int ct = 0;
    
    ct = Input_Score(score_stu);
    
    if(ct > 0)
    {
        Write_In_File(score_stu, ct);
    }
    else
    {
        fprintf(stderr, "erro in inputing !\n");
        exit(EXIT_FAILURE);
    }
    return 0;
}

int  Input_Score(SCORE_STU score_stu)
{
    int ct;
    char check;
    
    ct = 0;
    
    puts("please input the score into the file...");
    
    while(1)
    {
        printf("input stu's num:");
        scanf("%d", &score_stu[ct].num);
        
        printf("input stu's chinese accomplishments:");
        scanf("%d", &score_stu[ct].chi);
        
        printf("input stu's english accomplishments:");
        scanf("%d", &score_stu[ct].eng);
        
        printf("input stu's C accomplishments:");
        scanf("%d", &score_stu[ct].c);    
        
        puts("=======================");
        ct++;    
        
        if(ct == N)
        {
            break;
        }
        
        printf("do you want to continue?('N' to quit):     \b\b\b");
        MyFlush();
         
        if((check = getchar()) == 'N')
        {
            break;    
        }
        
        putchar('\n');    
    }    
    
    return ct;
}

void Write_In_File(SCORE_STU score_stu, int stu_num)
{
    FILE  *fp;
    int  index;
    char get_ch;
    
    if((fp = fopen("score.txt", "a+")) == NULL)
    {
        fprintf(stderr, "can't create or open the file \"score.txt\"");
        exit(EXIT_FAILURE);
    }
     
     if(1)                           //多种判断数据是否有读入 的方法 ,这只是一种 
     {
         rewind(fp);
         if(fgetc(fp) == EOF)
         {
             fprintf(fp,"number   Chinese   English     C\n");
         }
         fseek(fp, 0L, SEEK_END);    
     }
    
    for(index = 0; index < stu_num; index++)
    {
        fprintf(fp, "%-10d%-10d%-10d%-10d\n", score_stu[index].num, 
                score_stu[index].chi, score_stu[index].eng, score_stu[index].c);
    }
    
    puts("succeed in inputing...");
    fclose(fp);    
}
[/code]

我来回复

您尚未登录,请登录后再回复。点此登录或注册