其他分享
首页 > 其他分享> > 20201307梁辰鱼第二周学习总结

20201307梁辰鱼第二周学习总结

作者:互联网

1.知识点总结

1.1常用系统调用函数与I/O库函数

系统调用函数 I/O库函数 作用
open() fopen() 打开文件
read() fread() 读文件
write() fwrite() 写文件
lseek() fseek() 移动文件指针
close() fclose() 关闭文件

1.2 I/O库函数的算法

1.2.1 fread算法

在第一次调用fread()时,FILE结构体的缓冲区是空的,fread()使用保存的文件描述符fd发出一个

n = read(fd, fbuffer, BLKSIZE); 

系统调用,用数据块填充内部的fbuf[]。然后,它会初始化fbufl]的指针、计数器和状态变量,以表明内部缓冲区中有一个数据块。接着,通过将数据复制到程序的缓冲区,尝满足来自内部缓冲区的 fread()调用。如果内部缓冲区没有足够的数据,则会再发出一 read()系统调用来填充内部缓冲区,将数据从内部缓冲区传输到程序缓冲区,直到满足所的字节数(或者文件无更多数据)。将数据复制到程序的缓冲区之后,它会更新内部缓冲区的指针、计数器等,为下一个fread()请求做好准备。然后,它会返回实际读取的数据对象数量。

1.2.2 fwrite算法

fwrite()算法与fread()算法相似,只是数据传输方向不同。最开始,FILE结构体的内缓冲区是空的。在每次调用fwrite()时,它将数据写入内部缓冲区,并调整缓冲区的指针、计数器和状态变量,以跟踪缓冲区中的字节数。 如果缓冲区已满,则发出write()系统调用,将整个缓冲区写入操作系统内核。

1.2.3 fclose算法

若文件以写的方式被打开,fclose()会先关闭文件流的局部缓冲区。然后,它会发出一个close(fd)系统调用来关闭 FILE 结构体中的文件描述符。最后,它会释放 FILE 结构体,并将FILE指针重置为NULL。

1.3 I/O库模式

fopen()中的模式参数可以指定为:"r"、"w"、"a",分别代表读、写、追加。每个模式字符串可包含一个+号,表示同时读写,或者在写入、追加情况下,如果文件不存在则创建文件。

模式 功能
r+ 表示读/写,不会截断文件。
w+ 表示读/写,但是会先截断文件;如果文件不存在,会创建文件。
a+ 表示通过追加进行读/写;如果文件不存在,会创建文件。
1.3.1 字符模式I/O
int fgetc(FILE *fp);  			//get a char from fp, cast to int.
int ungetc(int c, FILE *fp);  	//push a previously char got by fgetc() back to stream
int fputc(int c, FILE *fp); 	//put a char to fp

注意,fgetc()返回的是整数,而不是字符。这是因为它必须在文件结束时返回文件结束符。文件结束符通常是一个整数-1,将它与文件流中的任何字符区分开。
对于fp=stdin或stdout,可能会使用c=getchar();sputchar(c);来代替。对于运行时效来说,getchar()和putchar()通常不是getc()和putc()的的缩小版本。相反,可以将它们实现为宏,以避免额外的函数调用。

1.3.2 行模式I/O
char *fgets(char buf, int size, FILE *fp);   	    //从fp中读取最多为一行(以n结尾)的字符。
int fputs(char *buf, FILE *fp);             		//将buf中的一行写入 fp 中。

当fp是stdin或stdout时,也可以使用以下函数,但他们并非fgets()和fputs()的缩减版本。

get(char *buf);					// input line from stdin but without checking length
puts(char *buf);				// write line to stdout
1.3.3 格式化I/O

格式化输入:(FMT=格式字符串)

scanf(char *FMT, &items);  			// from stdin
fscanf(fp, char *FMT, &items);  	// from file stream

格式化输出:

printf(char *FMT, &items);       // to stdin
fprintf(fp, char *FMT, &items);  // to file stream
1.3.4 内存中的转换函数
sscanf(buf, FMT, &items);	// input from buf[ ] in memory	
sprintf(buf, FMT, items);	// print to buf[ ] in memroy	

注意,sscanf()和sprintf()并非I/O函数,而是内存中的数据转换函数。例如,atoi()是一个标准库函数,将一串ASCII数字转换成整数,但是大多数Unix/Linux系统没有itoA()函数,因为转换可由sprintf()完成,所以不需要它。

1.3.5 其他I/O库函数
函数 功能
fseek()、ftell()、rewind() 更改文件流中的读/写字节位置。
feof()、ferr()、fileno() 测试文件流状态。
fdopen() 用文件描述符打开文件流。
freopen() 以新名称重新打开现有的流。
setbuf()、 setvbuf() 设置缓冲方案。
popen() 创建管道,复刻子进程来调用sh。
1.3.6 限制混合fread-fwrite

当某文件流同时用于读/写时,就会限制使用混合fread()和fwrite()调用。规范要求每对fread()和fwrite()之间至少有一个fseek()和ftell()。

1.4 文件流缓流

每个文件流都有一个FILE结构体,其中包含个一内部缓冲区。对文件流进行读写需要遍历FILE结构体的内部缓存区。文件流可以使用三种缓冲方案中的一种。

通过fopen()创建文件流之后,在对其执行任何操作之前,用户均可发出一个

getvbuf(FILE *stream, char *buf, int node, int size)

调用来设置缓冲区(buf)、缓冲区大小(size)和缓冲方案(mode),它们必须是以下一个宏:

1.5 变参函数

在I/O库函数中,printf()相当独特,因为多种不同类型的可变数量参数可以调用它。这是允许的,因为最初的C语言不是一种类型检查语言。目前,C语言和C + +会强执行类型检查,但是为了方便,这两种语言仍然允许参数数量可变的函数。这些函数必须至少个一个参数进行声明,后跟3个点,如:

int func(int m, int n...)        //n=last specified parameter 

在函数内部,可以通过C语言库宏访问参数:

enter code hervoid va_start(va_list ap, last); 	 // start param list from last parameter
type va_arg(va_list ap, type);   				 // type = next parameter type 
va_end(va_list ap);   							 // clear parameter list

2.实践内容

2.1 文本文件操作

2.1.1 打印文件内容
#include <stdio.h>
#include <string.h>
void main()
{
    FILE *fp;
    char ch;
    fp = fopen("C:/lcy/ccode/1.txt", "r");
    if (fp == NULL)
        printf("can not open!\n");
    else
    {
        fscanf(fp, "%c", &ch);
        while (!feof(fp))
        {
            putchar(ch);
            fscanf(fp, "%c", &ch);
        }
        fclose(fp);
    }
    printf("\n");
}

2.1.2 编写一个C程序,将文本文件中的字母由小写转换为大写

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{
    FILE *fp;
    char Filename[50]="1.txt", ch;
    if ((fp = fopen(Filename, "r")) == NULL)
    {
        printf("File open failed!\n");
        exit(0);
    }
    while (!feof(fp))
    {
        ch = fgetc(fp);
        if (ch != EOF)
        {
            if (ch >= 'a' && ch <= 'z')
            {
                ch -= 32;
            }
            printf("%c", ch);
        }
    }
}

2.1.3编写一个C程序,计算文本文件的行数
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    FILE *fp;
    char Filename[50] = "1.txt", ch;
    int a = 1;
    if ((fp = fopen(Filename, "r")) == NULL)
    {
        printf("File open failed!\n");
        exit(0);
    }
    while (!feof(fp))
    {
        ch = fgetc(fp);
        if (ch != EOF)
        {
            if (ch == '\n')
            {
                a++;
            }
        }
    }
    printf("%d\n", a);
    return 0;
}

2.1.4编写一个C程序,计算文本文件的单词数,单词由空格分隔。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    FILE *fp;
    char Filename[50] = "1.txt", ch;
    int a = 1;
    if ((fp = fopen(Filename, "r")) == NULL)
    {
        printf("File open failed!\n");
        exit(0);
    }
    while (!feof(fp))
    {
        ch = fgetc(fp);
        if (ch != EOF)
        {
            if (ch == ' ' || ch == '\n')
            {
                a++;
            }
        }
    }
    printf("%d\n", a);
    return 0;
}

2.1.5 文件的写入
//C语言按字符串写入文件 
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define maxn 1024

int main(){
	char *str=(char*)malloc(sizeof(char)*maxn);
	char *source="t.txt";

	char *op="w+t";
	FILE *fp=NULL;
	fp=fopen(source,op);
	puts("请输入信息:");
	while(1){
		if(strcmp(gets(str),"-1")==0) break;//输入-1结束
		strcat(str,"\n");
		fputs(str,fp);
	} 
	if(ferror(fp)) puts("文件写入错误!");
	fclose(fp);
	return 0;
}

2.2 二进制文件操作

2.2.1 二进制文件的读写
#include<stdio.h>
int main()
{
	// 文件指针pd
    FILE *pd = NULL;
    unsigned __int8 a[100];
    unsigned __int8 b[100];
    int i; 
    for (i = 0; i < 16; i++)
    {
        a[i] = 0xaf;
    }
    // 写入二进制文件
    // 文件名:"test.bin", 访问方式:"wb"
    pd = fopen("test.bin", "wb");
    // 数据块首地址: "&a",元素大小: "sizeof(unsigned __int8)", 元素个数: "16", 文件指针:"pd"
    fwrite(&a, sizeof(unsigned __int8), 16, pd);
    fclose(pd);

    // 读取二进制文件
    // 文件名:"test.bin", 访问方式:"rb"
    pd = fopen("test.bin", "rb");
    // 数据块首地址: "&b",元素大小: "sizeof(unsigned __int8)", 元素个数: "16", 文件指针:"pd"
    fread(&b, sizeof(unsigned __int8), 16, pd);
    for (i = 0; i < 16; i++)
    {
        printf("b[%d] = 0x%x\n", i, b[i]);
    }
    fclose(pd);
}

2.3 二进制文件与文本文件之间的转化

2.3.1 文本文件转换为二进制
#include <stdio.h>
#include <string.h>
#define NSIZE 8

void text2bin(const char* sIn, const char* sOut) {
	int count = 0;
	int ch,a;
	char temp;
	FILE * fin = fopen(sIn, "r");
	FILE * fout = fopen(sOut, "w");
	while(fscanf(fin, "%c", &temp)!=EOF) {
		ch=temp;
		for (a = 7; a >= 0; a--) 
        {
            fprintf(fout, "%d", ch >> a & 1);
        }
        fprintf(fout,"\n");
	}
	fclose(fin);
	fclose(fout);

}

int main() {
	text2bin("ascii.txt", "bin.txt");
    printf("changing successfully!\n");
	return 0;
}

2.3.2 二进制数据转化为文本文件
#include <stdio.h>
#include <string.h>
#define NSIZE 8

void bin2text(const char* sIn, const char* sOut) {
	FILE * fin = fopen(sIn, "r");
	FILE * fout = fopen(sOut, "w");
	int i = 0, j = 0, iTemp = 0, flag = 0;
	int ibina[NSIZE];
	char cRead[NSIZE];
	char str[8];
	char cChar;
	int a=0;
	while(fscanf(fin, "%c", &str[a%8])!=EOF) {
		if(a%8==7) {
			iTemp = 1;
			cChar = 0;
			for (j = 7; j >= 0; j--) {
				cChar += (str[j]-'0') * iTemp;
				iTemp *= 2;
			}
			fprintf(fout, "%c", cChar);
		}
		a++;
	}
	fclose(fin);
	fclose(fout);

}

int main() {
	bin2text("bin.txt", "ascii1.txt");
    printf("changing successfully!\n");
	return 0;
}

2.4 数据结构文件的读写

2.4.1 申请节点空间
node *head =(node*)malloc(sizeof(node));
2.4.2 初始化链表
node *setLink()
{
	node *p,*s,*s1;
	s=(node*)malloc(sizeof(node));
	s->data=4;
	strcpy(s->name,"密码"); 
	s1=(node*)malloc(sizeof(node));
	s->next=s1;	
	s1->data=1;
	strcpy(s1->name,"网空");
	s1->next=NULL;
	return s;  //返回链表头节点 
} 
2.4.3 将链表中的数据储存在文件中
void save(node *head)
{
   node *p=head;
   FILE *w =fopen("data.txt","w");
   if(w==NULL)
   {
       printf("打开文件失败!");
       return; 
   }
   while(p)
   {
       fprintf(w,"%d %s",p->data,p->name);
       p=p->next; 
	   fprintf(w,"\n"); 	         
   }     
   printf("\n");
   fclose(w);
   return;
}
2.4.4 从文件中读取数据储存在链表中
node *take()  //尾插法
{
    node *head =(node*)malloc(sizeof(node));
    int t;
    char name[6];
    node *p;
    node *q;//始终指向为下一个节点 
    p=q=head;
    FILE * r= fopen("data.txt","r");
    if(r==NULL)
    {
        printf("打开文件失败!");
        return NULL; 
    }               
    while(fscanf(r,"%d %s",&t,name)!=EOF)
    {  
       q= (node*)malloc(sizeof(node));
       q->data=t;
       strcpy(q->name,name);
       p->next=q;
       p=q;
    }
    p->next=NULL;
    return head;
}
2.4.5 运行结果

3.问题与解决思路

问题:在学习对于文件任意位置的读写时,我有点搞不清楚,如何实现这个功能,我有点无从下手
解决思路:

我通过了该网站学习了文件的读写规则:学习链接
在程序看来,文件就是由一连串的字节组成的字节流,每个字节都有一个位置编号,在第n个字节后面有一个文件结束标志EOF(Eed Of File)。

文件是一个字节流,读写哪个字节必须要指定这个字节的位置,这是由文件指针来决定的。如字节流有n个字节,p是指针位置(0<=p<=n-1),那么读写规则如下:

所以通过文件指针的改变,就可以对文件的任意位置进行读写

标签:fp,文件,ch,梁辰鱼,int,char,第二周,FILE,20201307
来源: https://www.cnblogs.com/yu15141310373/p/16684992.html