Lenguaje C: Ensayo 11 - Operación de archivos

 Los archivos suelen residir en medios externos (como discos, etc.) y se transfieren a la memoria cuando se utilizan.

Clasificación de documentos: Según la organización de los datos:

(1) Archivo ASCII (archivo de texto): ponga un código ASCII para cada byte.

(2) Archivo binario: Los datos de la memoria se envían al disco para su almacenamiento de acuerdo con su forma de almacenamiento en la memoria.

Por ejemplo, la forma de almacenamiento del entero 10000D (D representa decimal) en la memoria y la salida en forma ASCII y forma binaria se muestran en la siguiente figura:

El número hexadecimal correspondiente a ASCII 1 es 32H (H significa hexadecimal), decimal es 49 y binario es 110001.

El archivo ASCII es conveniente para el procesamiento carácter por carácter y para la salida de caracteres. Sin embargo, generalmente ocupa mucho espacio de almacenamiento y lleva tiempo convertir (porque la memoria se intercambia directamente con la CPU y ASCII se usa para almacenamiento, por lo que el binario debe convertirse a ASCII (porque la CPU lee binario)). (Por ejemplo, lo anterior se procesa un carácter por un carácter, trata 1 como un carácter, 0 como un carácter y un total de cuatro 0 se tratan como 4 caracteres respectivamente) 

Los archivos binarios pueden ahorrar espacio de almacenamiento externo y tiempo de conversión, pero un byte no corresponde a un carácter, y la forma del carácter no se puede generar directamente (porque debe convertirse a ASCII y luego enviarse). (Debido a que mostramos una cosa en código ASCII, ingresamos una cosa en forma de código ASCII y luego se convierte a binario) 

Sistema de archivos con búfer y sistema de archivos sin búfer.

Las lecturas y escrituras en archivos en lenguaje C se realizan a través de funciones de biblioteca (sistema de archivos de búfer).

1. Apertura y cierre de expedientes

(1) Variable de puntero de archivo

FILE *fp;//FILE是一个结构,是一个FILE(文件型)结构。FILE是一个文件的名称。用这个结构来定义一个指针,这个指针就是指向一个文件。
 //fp是一个指向FILE类型结构体的指针变量(那么什么是一个FILE类型结构体呢?)。

La estructura de tipo FILE se define en nuestro archivo de encabezado de entrada y salida estándar stdio.h,

  

// Primero defina una estructura input / outputbuffer (buffer), y luego cambie el nombre de la estructura iobuf con typedef type FILE. Luego uso FILE para definir un fp (FILE * fP;) que es equivalente a struct _iobuf * fp; de esta manera, nuestro puntero fp apunta a la estructura superior. Necesitamos llenar este puntero con algo similar a esta estructura. 

Hacemos que fp apunte a la variable de estructura de un determinado archivo, de modo que se pueda acceder al archivo a través de la información del archivo en la variable de estructura.

Si hay n archivos, generalmente se deben establecer n variables de puntero para que apunten a n archivos respectivamente para lograr el acceso a los archivos.

¿Cómo usarlo? Podemos usar una matriz de tipo FILE:

FILE f [5]; define una matriz de estructura f, que tiene 5 elementos y puede usarse para almacenar la información de 5 archivos.

(1) Abra el archivo (función fopen)

//函数调用://定义一个指向FILE结构体的指针fp
FILE *fp;
fp=fopen(文件名,使用文件方式);//将这个指针的值赋予什么呢?用fopen打开,其实用fopen打开他之后它就会填充这个结局体, 然后把他赋给fp,fp指向他。
//注意:(1)需要打开的文件名,也就是准备访问的文件的名字。(要加上他的路径是在D盘还是F盘等)
//注意:(2)使用文件的方式(“读”还是“写”等)具体的打开方式见下, 
//注意:(3)让哪一个指针变量指向被打开的文件。(我们这里使用的是fp指向,要保证有指向)

Cómo utilizar el archivo:

Cuando se abre "ab" de esta manera, el puntero apunta al final del archivo.

Existen las siguientes instrucciones para el uso de archivos:

  • Al abrir un archivo con "r", el archivo ya debe existir y solo se puede leer desde el archivo. (Si el archivo no existe, no se puede abrir. Solo puede devolver un puntero nulo. Si se usa un puntero NULL, no hay forma de hacerlo).
  • Abrir un archivo con "w" solo puede escribir en ese archivo. Si el archivo abierto no existe, el archivo se crea con el nombre de archivo especificado. Si el archivo abierto ya existe, se eliminará y se creará uno nuevo.
  • Si desea agregar nueva información a un archivo existente, solo puede abrir el archivo en modo "a". Pero en este momento el archivo debe existir, de lo contrario se producirá un error.
  • Al abrir un archivo, si ocurre un error, fopen devolverá un puntero nulo NULL. Esta información se puede utilizar en el programa para determinar si se debe completar el trabajo de apertura del archivo y tratarlo en consecuencia.
  • Al leer un archivo de texto en la memoria, el código ASCII debe convertirse en código binario, y cuando el archivo se escribe en el disco en modo texto, el código binario también debe convertirse en código ASCII, por lo que la lectura y escritura del archivo de texto costará más. Tiempo de conversión. No existe tal conversión para leer y escribir archivos binarios.

Código de muestra:

#include<stdio.h>
#include<stdlib.h>
void main()
{
    FILE *fp;
    if(!(fp=fopen("F:\\1.txt","rb")))//注意要“\”  //b是二进制的形式
    {
        printf("Can not open F:\\1 file!\n");
        system("pause");//让系统暂停在这,接受用户的操作
    }
    else
    {
        printf("Open success!\n");
    }
}

(2) Cierre del expediente

Mientras el archivo esté abierto se mapeará a la memoria, si no lo cerrara o desconectara el puntero, siempre ocuparía ese espacio.
 

//函数调用:
fclose(文件指针);
//函数功能:使文件指针变量不再指向该文件,也就是文件指针变量与文件“脱钩”,此后不饿能再通过该指针对原来与其相联系的文件进行读写操作。
//返回值:关闭成功返回值为0;否则返回EOF在C语言中定义为-1.

Leer es leer el contenido del archivo y leerlo en el búfer. Escribir es escribir contenido nuevo en un archivo.

Hay una variedad de funciones de lectura y escritura de archivos en C:

//字符读写函数:fgetc和fputc//其中f是file的缩写,c是char的缩写
//字符串读写函数:fgets和fputs 。
//数据块读写函数:freed和fwrite。
//格式化读写函数:fscanf和fprintf//就是按照一定的格式,有点像我们的scdnf和printf,前边加上f表示他是关于文件的。
//以上函数都要包含头文件stdio.h。

(1) Funciones de entrada y salida de caracteres (fputc () y fgetc ())

//fputc()函数调用:
fputc(ch,fp);//fp是一个指针
//函数功能:将字符(ch的值)输出到fp所指向的文件中去。(比如字符‘a’他的ASCII码是65,那就把65输入进去,因为我们是纯文本输入,是输入ASCII的)
//用写或者读写方式打开一个已存在的文件时将清除原有的文件内容,写入字符从文件首开始。如需保留原有文件内容,希望写入的字符以文件末开始存放,必须以追加方式打开文件。被写入的文件若不存在,则创建该文件。
//每写入一个字符,文件内部位置指针向后移动一个字节。
//fputc函数有一个返回值,如写入成功则返回写入的字符,否则返回一个EOF。可以用来判断写入是否成功。

//示例文件的写入:
#include<stdio.h>
#include<stdlib.h>
void main()
{  
   FILE *fp;//指针fp指向FILE结构,也就是说指针指向的内存它是以FILE结构来读取的
   char ch,filename[20];
   printf("Please input the filename you want to write:");
   scanf("%s",filename);//filename是数组名表示首地址//表示将要创建的文件的名称
   if(!(fp=fopen(filename,"wt+")));//wt+表示读写打开或建立一个文本文件,允许读和写
   {//打开错误就是返回NULL,那么!NULL就是1,进入if语句,输出不能打开文件
       printf("Cannot open the file!\n");
       exit(0);//终止程序
   }
   printf("Please input the sentences you want to write:");
   ch=getchar();
   ch=getchar();//有两个getchar()函数?(如果只写一个ch=getchar();语句写入的文件就会在内部的一行出现一个空行?为什么?)
   while(ch!=EOF)//如果输入的不是EOF //EOF一般是我们ASCII编码的文件的结束标志,怎么输入EOF呢?(EOF输入是ctl+z组合键)
   {
      fputc(ch,fp);
      ch=getchar();//再次接收来自键盘的输入,然后继续循环把他给写入,直到我们输入EOF
   }
   fclose(fp);//关掉文件
}
//fgetc()函数调用:
ch=fgetc(fp);
//函数功能:其意义是从打开的文件fp中读取一个字符并送入ch中。
//在fgetc函数调用中,读取的文件必须是以读或读写方式打开。
//在文件内部有一个位置指针。用来指向文件当前读写子节。(因为我们读取一个之后等一下要读取第二个,指针要指向第二个你才能读取,如果一直指向第一个的话你就只能永远读取的第一个。所以有一个指针你读了第一个之后他会自动指向第二个。有一个这样的机制 )
//在文件打开时,该文件总是指向文件的第一个子节。使用fgetc函数后,该位置指针将向后移动一个字节。因此连续多次使用fgetc函数,读取多个字符。
//应注意文件指针(FILE *fp)和文件内部的位置指针(是windows系统内部自动匹配自动调用的我们不需要管)不是一回事。
//文件指针是指向整个文件的,须在程序中定义说明,只要不重新赋值,文件指针的值是不变的。
//文件内部的位置指针用以指示文件内部的当前读写位置,每读写一次,该指针均向后移动,它不需要在程序中定义说明,而是由系统自动设置的。 

//示例文件的写入:
#include<stdio.h>
#include<stdlib.h>
void main()
{  
   FILE *fp;//指针fp指向FILE结构,也就是说指针指向的内存它是以FILE结构来读取的
   char ch,filename[20];
   printf("Please input the filename you want to write:");
   scanf("%s",filename);//filename是数组名表示首地址//表示将要创建的文件的名称
   if(!(fp=fopen(filename,"r")));
   {
       printf("Cannot open the file!\n");
       exit(0);//终止程序
   }
   while(ch!=EOF)
   {
      ch=fgetc(fp);//读出的字符保存在ch中
      putchar(ch);//把ch显示在屏幕上 
   }
   fclose(fp);//关掉文件
}

//补充1 :
//从一个文本文件顺序读入字符并显示在屏幕上。
ch=fgetc(fp);
while(ch!=EOF)
{
    putchar(ch);
    ch=fgetc(fp);
}
//注意:EOF不是可输出字符,因此不能在屏幕上显示。由于字符的ASCII码不可能出现-1(ASCII码是从0开始),因此EOF定义为-1是合适的。当读入的字符值等于-1时,表示读入的已不是正常的字符而是文件结束符。
//补充2:
//从一个二进制文件顺序读入字符 ;(就不是-1的问题了,因为二进制文件你想什么数都可以,因为CPU处理的是二进制文件,没有任何约定,任何数都是二进制文件,那么它就没有一个EOF我们可以定了,那么我们怎么知道它结束了呢?我们用一个函数feof(),eof就是end of file的缩写,feof()是文件结束的一个函数)
while(!feof(fp))//feof()函数作用:Tests for end-of-file on a stream.测试是否文件的结尾
{
    ch=fget(fp);
}
//因此ANSIC提供一个feof()函数来判断文件是否真的结束。如果文件结束,函数feof(fp)的值为1(真);否则为0(假)。这个也适用于文本文件的读取。//但是在二进制文件中不能使用EOF(因为二进制文件中有-1这个数)。

Escriba un archivo binario para leer y escribir: (imagen, sintetizador de archivos)

Se incluye un archivo ejecutable (.rar) con la imagen (una imagen jpg se cambia a rar y se generará un archivo comprimido. Agregar una imagen jpg a un archivo .rar es una versión compuesta de las dos)

#include<stdio.h>
#include<stdlib.h>
void main()
{
    FILE *f_pic,*f_file,*f_finish;//需要三个指针文件,打开两个,再写入一个新的
    char ch,pic_name[20],file_name[20],finish_name[20]; //声明变量
    printf("请输入需要合成的图片和文件名称:\n");
    printf("图片:");
    scanf("%s",pic_name);//w文件的名称是什么?字符串,必须把它把他赋值到一个变量里边去。//所以上边要声明变量
    printf("文件:");
    scanf("%s",file_name);
    printf("生成为:");
    scanf("%s",finish_name);
    //打开pic1
    if(!(f_pic=fopen(pic_name,"rb")))//以二进制读写方式打开,并存放在f_pic这个文件指针里
    {
        printf("Cannot open the picture %s",pic_name);//打不开
        return;
    }
    //打开file2
    if(!(f_file=fopen(file_name,"rb")))//以二进制读写方式打开,并存放在f_pic这个文件指针里
    {
        printf("Cannot open the picture %s",file_name);//打不开
        return;
    }
    //打开3第三个是要写入的,是原本不存在的,我们新建的。//我们将要生成的
    if(!(f_finish=fopen(finish_name,"wb")))//以二进制读写方式打开,并存放在f_pic这个文件指针里
    {
        printf("Cannot open the file %s",finish_name);//打不开 
        return;
    }
    //先把打开的1读出来然后写进3。写完之后再把2的内容写进3.
    //我们要写一个文件,必须要判断文件内部指针有没有指向结尾,才知道什么时间结束,所以使用内置函数feof()//函数返回值如果返回0表示现在的位置不是文件尾部,返回非0说明是文件的结尾了。
    while(!feof(f_pic))
    {
        ch=fgetc(f_pic);//上边定义的ch是用来暂时存放读取的那个数据//fgetc()这个函数就会读取f_pic这个文件里面的一个字节,然后把他当作返回值赋值给ch.
        fputc(ch,f_finish); //然后将ch给了finish_name这个文件.(参数1:需要写入的字符;参数2:需要写入的文件的指针)
    }
    //进行到文件尾部就会退出while,所以我们要关掉这个文件指针
    fclose(f_pic);
    //现在把压缩文件接到后边去(当要接一个文件后边继续添加内容时:(就比如上边已经拷贝进去一个了要接着在文件中在后边再添加一个)这时这里的文件内部指针不用去管它,当他拷贝到文件后面呢最后一个位置时他的指针现在是指向文件最后一个格的(也就是最后一个字节的))
    while(!feof(f_file))
    {
        ch=fgetc(f_file);//上边定义的ch是用来暂时存放读取的那个数据//fgetc()这个函数就会读取f_pic这个文件里面的一个字节,然后把他当作返回值赋值给ch.
        fputc(ch,f_finish); //然后将ch给了finish_name这个文件.(参数1:需要写入的字符;参数2:需要写入的文件的指针)
    }
    //进行到文件尾部就会退出while,所以我们要关掉这个文件指针
    fclose(f_file);
    fclose(f_finish);//都关掉
    system("pause");

}

----- Lo anterior son las funciones de lectura y escritura que leen la cadena de caracteres actual una por una: fgets y fputs

Funciones de entrada y salida de cadenas fputs () y fgets ().

//fgets()函数
//函数调用形式如:fgets(str,n,fp);//有三个参数
//函数作用:从fp所指的文件中读出n-1个字符送入字符数组str中,因为在最后加一个'\0'(字符串的标志结尾0,C语言规定字符串的结尾是以\0来标志的,其他语言有所不同).
//函数返回值:返回str的首地址。

Ejemplo de lectura:

//有一个1.txt文件,我想把它读出来,然后打印到屏幕上
#include<stdio.h>
#include<stdlib.h>
#define LEN 11//用宏定义方便后期改字节,不用一个个去改
void main()
{
    FILE *fp;
    char buffer[LEN];//定义一个字符缓冲区,该字符缓冲区有LEN这么长,也就是下边可以读取LEN-1个字节,因为最后一个字节他会自动加上‘\0’,表示字符串结束。
    if(!fp=fopen("1.txt","rt"))//fp指向的是1.txt这个文件 
    {
       printf("\nCannot open file strike any key exit!");
       exit(1);
    }
    fgets(buffer,LEN,fp);//从fp拿到LEN-1这么长的东西,给了buffer这个缓冲区
    printf("%s\n",buffer);//把buffer缓冲区的内容以字符串的形式打印出来 
    fclose(fp);//关闭

}

Escriba cadenas de fputs () en un archivo:

//fputs函数
//函数调用方式:fputs("FISHC",fp);//将FISHC输入到我们fp所指向的这个文件中
//函数作用:把字符串"FISHC"写入fp所指的文件之中。
//函数返回值:输入成功的话,返回值为0;输入失败的话,返回值时EOF。

Ejemplo de función de escritura:

//从屏幕上输入一个字符串,然后程序截取这个字符串,把他给放到这个文件的结尾处
#include<stdio.h>
#include<stdlib.h>
#define LEN 20
void main()
{
    FILE *fp;
    char ch,buffer[LEN];//建立20个长度的缓冲区用来放入从屏幕上输入的字符串
    if(!fp=fopen("1.txt","at+"))//这里以“at+”的形式写入,粘贴在后面(意思就是将1.txt这个文件打开,将内部的文件指针指向了结尾处,然后我们从这里写入的话是从文件的结尾开始写)
    {
       printf("\nCannot open file strike any key exit!");
       exit(1);
    }
    printf("Please input a string:\n",buffer);
    //正常做法输入字符串用scanf()
    //scanf("%s",buffer);//接收一个字符串,然后把他存在buffer这个缓冲区里面
    //因为scanf这个函数使用%s接收字符串的话,当他遇到空格和回车的时候,他都是自动声明这个接收已经结束了,后边的就不再接收了。
   //前边讲过fgets()是从文件中获取字符串,那为什么这里可以从我们的键盘获取?(因为我们的键盘实际上也是夜歌特殊的文件,叫做stdin文件,标准输入文件,我们从键盘上输入的东西会放入stdin这个文件,作为一个缓冲区存放到里面去,那么我们就从stdin这里面读就可以了)
    fgets(buffer,LEN,stdin);//写入的话用fgets()来写,而不用scanf().//为什么不用scanf()?stdin又是啥?
    fputs(buffer,fp);//把buffer写入到fp这个文件里面去(fputc如果是c的话参数Buffer就得表示一个字节,fputs如果是s的话参数buffer就得是一个字符串,但是fp都是一个指向的文件。)
    rewind(fp);//(写完之后)重新定义文件内部指针去指向到开头处(这样是比较优良的做法,不这样做也没问题)(这里之所以这么做,因为我还想把他再打印出来,这样可以让我们看到整个文件写进去之后有所改变)
    ch=fgetc(fp);
    while(ch!=EOF)//这里使用一个循环,只要他不是文件结尾他就会把它输出到屏幕上
    {
        putchar(ch);
        ch=fgetc(fp);
    }
    printf("\n");
    fclose(fp);//关闭

}

Funciones de lectura y escritura de bloques de datos fread () y fwrite (). // Puede utilizar fread y fwrite para realizar operaciones de datos.

¿Qué es un bloque de datos? Fue una serie de lecturas hace un momento, pero ahora estamos leyendo una por una.

//函数调用:
//fread(buffer,size,count,fp);
//fwrite(buffer,size,coubt,fp);
//参数说明:
//buffer:是一个指针。(对fread来说,他是一个读入数据的存放地址;对fwrite来说,是要输出数据的地址(均指起始地址))(是一个缓冲区)
//size要读写的字节数。(这个块非常灵活,你可以当他是一个字节一个字节或者10个字节一个块也行)
//count:要进行读写多少个size字节的数据项。(次数/个数。比如我的size是10个字节,count是2,那就是你读取了20个字节。(就是以10个字节分为1块,读取count2个块))
//fp:是一个文件的指针。

Ejemplo: la siguiente estructura:

struct  student_type
{   
   char name[20];   
   int num;
   int age;
   char addr[30];
}stud[40];//定义了40个学生,每个学生都是一个这样的结构

//读取方式
for(I=0;i<40;i++)
{
    fread(&stud[i],sizeof(struct student_type),1,fp);//声明要读取到std这个变量里边去,每次读取的大小是sizeof,每次读一次就是一个学生,从fp这个文件
}
//写入也一样每次写入一个学生的内容(你如果按照原来一个字节一个字节的来写,那么各个学生就会打乱了)
for(I=0;i<40,i++)
{
    fwrite(&stud[i],sizeof(struct student-type),1,fp);
}

Requisito: Ingrese los datos relevantes de 4 estudiantes desde el teclado y luego guárdelos en el archivo de disco en formato binario.

#include<stdio.h>
#include<stdlib.h>
define SIZE 4;
struct student
{
   char name[10];   
   int num;
   int age;
   char addr[15];
}stu[SIZE];
void save()
{
   FILE *fp;
   int i;
   if(!(fp=fopen("student-list","wb")))//student-list是一个二进制文件
   {
       printf("Cannot open the file!\n"); 
       return;  
   }
   for(i=0;i<size;i++)
   {
       if(fwrite(&stu[i],sizeof(struct studet),1,fp)!=1)
       {
          printf("File write error!\n");
          fclose(fp);
       }
       
   }
}
//写一个load()函数将该文件读取并显示
void load()
{
    FILE *fp;
    int i;
    if(!(fp=fopen("student-list","r")))//student-list是一个二进制文件
    {
       printf("Cannot open the file!\n"); 
       return;  
    }
    //读取方式
    for(i=0;i<40;i++)
    {
       fread(&stud[i],sizeof(struct student),1,fp);
     //printf("%s,%d,%d,%s",&stud[i].name,&stud[i].num,&stud[i].age,&stud[i].address);//不需要这一行(因为fread带显示)
       fclose(fp);
    }
void main()
{  
   int i;
   printf("Please input student's name,num,age,address:\n");
   for(i=0;i<40,i++)
   {
      scanf("%s %d %d %s",stud[i].name,&stud[i].num,&stud[i].age,&stud[i].address); 
   }//此时输入的都是输入到缓冲区文件里边去
   save();
   load();
}

----- Formateando funciones de lectura y escritura (fprintf () y fscanf ()) // (Es lo mismo que printf y scanf que se usan habitualmente. Hay una f adicional al frente para indicar que es un archivo de lectura y escritura) (si no hay f Si es para nuestro teclado y pantalla, escribir / escribir en la pantalla significa generar números y leer caracteres desde el teclado).

 //函数调用:
//fprintf(文件指针,格式字符串,输出表列);
//fscanf(文件指针,格式字符串,输出表列);
//函数功能:从磁盘文件中按照格式读入或输出字符。
//例如:
//fprintf(fp,"%d,%6.2f",i,t);// “%6.2f”表示6位的浮点数,两位的小数点,然后存放在这个t这个浮点型的变量里面。
//fscanf(fp,"%d,%f",&i,&t);

----- Lectura y escritura secuencial y lectura y escritura aleatoria

Lectura y escritura secuenciales: Todo lo anterior será lectura y escritura secuenciales (es decir, abrir el archivo y escribir / o leer desde el principio)

El puntero de posición se mueve en orden de posición de bytes.

Lectura y escritura aleatoria: después de leer y escribir un carácter (byte), no es necesario leer y escribir los caracteres siguientes (bytes), pero puede leer y escribir los caracteres requeridos (bytes) en cualquier posición del archivo (esta posición) Podemos controlarlo, luego tenemos que aprender una función fseek)

Función fseek (generalmente utilizada para archivos binarios) (la función es cambiar el puntero de posición del archivo)

//函数功能:
//改变文件的位置指针(这个函数主要是改变文件内部的指针,改变它我们就可以跳跃性的读写,比如说读了第一个字符之后我就用fseek把他跳跃到第以00个字符,之后我就从第100个字符开始读了)
//函数调用格式:
//fseek(文件类型指针,位移量,起始点);
//第三个参数:起始点:
//文件开头  SEEK_SET  0//如果起始点设置的是0的话,他的宏定义是SEEK_SET,他是从文件的开头位置开始读的
//文件当前位置  SEEK_CUR   1//如果起始位置设为1的话他是从文件的当前的文件指针的位置,因为我们每读过一次,他的文件指针都会向后移一格
//文件末尾   SEEK_END    2//如果是2的话,宏定义是SEEK_END的话,他是标志着从文件的末尾开始读取
//第二个参数:位移量
//位移量:以起始点为基点,向前移动的字节数(以这个起始点标志的位置以后的偏移量等于多少,就是这个位移量一般都是以long型的形式存在的)
//例如:fseek(fp,100L,0);//将位置指针移到离文件头100格字节处//L表示long型
//fseek(fp,50L,1);//将位置指针移到离当前位置50个字节处(这个当前位置就不一定是文件头了,说不定在之前已经read过多少次了,读过多少个字节了,那就从你现在接着的地方开始,50个字节处)
//fseek(fp,50L,2);//将文件指针从文件末尾处向后退50个字节(因为已经是最末尾了,不能再前进了,所以表示向后退) 
//fseek(fp,i*sizeof(struct stu),0)//这样的话我们就要通过表达式计算了,i是个变量

Ejemplo: lea los datos del segundo alumno en el archivo de alumno stu_list

struct student
{
   char name[10];
   int num;
   int age;
   char addr[15];
}boy;//student结构中的Boy变量
void main()
{
   FILE *fp;
   int i;//用于定位i个结构
   if(!(fp=fopen(student_list,"r")))
   {
       printf("Cannot open the file!\n");
       return;
   }
   rewind(fp);//设置内部文件指针指向头(也就是重置了文件指针)
   fseek(fp,i*sizeof(struct student),0);//这个时候文件内部指针已经指向了第二个学生的开头位置
   fread(&boy,sizeof(struct student),1,fp);//&boy第一个传给他缓冲区就是存放的一个地址。然后sizeof(struct student)存放多少(一块读取多少),1读取一块就行了,fp指向文件
   printf("name\tnumber  age   addr\n");//打印出来
   printf("%s\t%5d   %7d    %s\n",boy.name,boy.num,boy.age,boy.addr);
   fclose(fp);
   system("pause");
}

función ftell

//函数作用:得到流式文件(就是我们的文件流)中当前位置,用相对于文件开头的位移量来表示。
//返回值:返回当前位置(就是当前位置离文件开头的偏移量),出错时返回-1L,在文件头就是返回0,在文件头一个字节的地方他就是返回1。
//应用举例;
i=ftell(fp);
if(i==-1L)
{
   printf("erroe\n");
}

--- Función de error de detección de errores (para detectar la entrada y la salida se producirá un error)

//ferror函数
//调用形式:
ferror(fp);
//返回值:返回0,表示未出错;返回非0,表示出错。
//注意:在调用一个输入输出函数后立即检查ferror函数的值,否则信息会丢失(就是会被下一个覆盖掉)。再指向fopen函数时,ferror函数的初始值自动置为0(因为刚刚打开,打开成功的话初始值是设为0的)。

 ---- función más clara

//调用形式:
clearer(fp);
//函数作用:使文件错误标志和文件结束标志置为0.
//注意:只要出现错误标志,就一直保留,直到对同一文件调用clearerr函数或rewind函数,或任何其他一个输入输出函数。

para resumir:

   

 

 

Supongo que te gusta

Origin blog.csdn.net/m0_37957160/article/details/108750862
Recomendado
Clasificación