目录
IO:输入输出
操作对象:文件
Linux系统一切皆是文件:
文件分类:
1.block b 块设备文件 按块扫描设备信息的文件
2.char c 字符设备文件 按字符扫描设备信息的文件
3.directory d 目录文件 保存或管理文件
4. - 普通文件 保存数据信息的文件(代码、图片、音视频、压缩包等)
5.link l 链接文件 指向其他文件的文件(类似与window系统的快捷方式)
6.socket s 套接字文件 用于进程间通信
7.pipe p 管道文件 用于进程间通信
1.标准IO
stdio.h
主要操作普通文件 ,步骤如下。
1.打开文件 :fopen
2.读写文件 :fgetc/fputc、fgets/fputs、fscanf/fprintf、fread/fwrite
3.关闭文件 :fclose
2.特殊的流
默认打开的流(不需要fopen手动打开的流)
stdin 标准输入流 行缓存
stdout 标准输出流 行缓存
stderr 标准错误流 不缓存
这三个流是默认和终端(显示屏,键盘等)建立的流
gets、getchar、scanf是基于stdin实现的
puts、putchar、printf是基于stdout实现的
perror是基于stderr
3.缓存:
这里我们发现,./a.out的时候并没有打印hello world,因为我们交给库函数之后,要先缓存,当在hello world后面加\n的时候,就会打印出来,因为这是行缓存刷新的标志。
1.全缓存
4096 (4k)
缓存区满刷新
与文件建立的缓存一般为全缓存
刷新条件:
1.缓存区存满了刷新
2.fflush函数接口刷新
fflush(文件流)
3.关闭流时会刷新(fclose)
flcose(文件流)
全缓存遇到\n,不会刷新。
2.行缓存
1024 (1k)
遇到\n刷新
与终端建立的缓存都是行缓存
刷新条件:
1.缓存区满刷新
2.遇到\n刷新
3.fflush函数刷新
4.关闭流时会刷新
3.不缓存
0 0k
立即刷新
刷新条件:
1.立即刷新
1.对设备的操作不允许缓存(鼠标,键盘等)
2.通信不允许缓存
3.出错处理不缓存
4.函数接口
1.fopen
FILE *fopen(const char *pathname, const char *mode);
功能:
打开pathname对应的文件并建立一个文件流(方向性,连续性)
参数:
pathname:文件路径
mode:打开方式
r 只读 如果文件存在则只读打开
如果文件不存在报错
r+ 读写 如果文件存在则读写打开
如果文件不存在报错
w 只写 如果文件存在则清0,只写打开
如果文件不存在则创建
w+ 写读 如果文件存在则清0,读写打开
如果文件不存在则创建
a 追加只写 如果文件存在则追加只写打开
如果文件不存在则创建
a+ 追加读写 如果文件存在则追加读写打开
如果文件不存在则创建
返回值:
成功返回FILE*的指针(所以要定义一个FILE类型的指针去接收返回的指针)
失败返回NULL并且将错误码置位
#include <stdio.h>
int main(void)
{
FILE *fp = NULL; //定义一个指针去接受返回的指针
fp = fopen("a.txt", "r"); //打开当前目录下的a.txt,只读的方式
if (NULL == fp)
{
perror("打开 a.txt 文件失败"); //perror会显示打开失败的原因
return -1;
} //判断是否打开失败
return 0;
}
2.fclose
只打开不关闭会造成内存泄漏
int fclose(FILE *stream);
功能:
关闭流
参数:
stream:文件流
返回值:
成功返回0
失败返回EOF(-1)
3.setvbuf
int setvbuf(FILE *stream, char *buf, int mode, size_t size);
功能:
改变流的缓存类型
参数:
stream:文件流
buf:缓存区的首地址
mode:
_IOFBF 全缓存(块缓存,文件流的时候)
_IOLBF 行缓存(终端的时候)
_IONBF 不缓存
size:缓存区大小
返回值:
成功返回0
失败返回非0
#include <stdio.h>
int main(void)
{
char tmpbuff[4096] = {0}; //全缓存内存为4K,所以定义一个4k大小的缓存区。
#if 0
setvbuf(stdout, tmpbuff, _IOFBF, 4096);
printf("stdout被切换为全缓存\n"); //改变为全缓存,这时候运行不会打印
setvbuf(stdout, NULL, _IONBF, 0);
printf("stdout被切换为不缓存\n"); //改变为不缓存,这时候运行有\n的会被打印,没有的也会打印
#endif
setvbuf(stdout, tmpbuff, _IOLBF, 1024); //改编为行缓存,这时候运行有\n的会被打印,没有不会打印
printf("hello world!\n");
while (1)
{
} //while循环是为了不让代码结束这样才能看到全缓存的效果
return 0;
}
4.fputc
int fputc(int c, FILE *stream);
功能:
向流中写入一个字符
参数:
c:写入的字符(这里可以直接写字符,也可以写指针所指向的字符(*p就是这字符))
stream:文件流指针
返回值:
成功返回写入字符的ASCII码值
失败返回EOF(-1)
#include <stdio.h>
int main(void)
{
FILE *fp = NULL;
char ch = 'A';
/* 打开文件 */
fp = fopen("a.txt", "w");//接收文件的地址
if (NULL == fp)
{
perror("fopen a.txt failed");
return -1;
}
/* 读写文件 */
fputc('a', fp);
fputc(ch, fp);
fputc(ch+32, fp);
/* 关闭文件 */
fclose(fp);
return 0;
}
结果就会给a.txt写入:
练习:
1.编写程序利用fputc将"hello world"写入到file.txt文件中
#include <stdio.h>
int main(void)
{
FILE *fp = NULL;
char str[32] = {"hello world"};
char *p = str;
fp = fopen("file.txt", "w");
if (NULL == fp)
{
perror("fail to fopen");
return -1;
}
while (*p != '\0')//字符串的结尾就是\0,p是指针,*p就是指针指向的内容
{
fputc(*p, fp);
p++;
}//用循环将所有的字符全部写入
fclose(fp);
return 0;
}
5.fgetc
int fgetc(FILE *stream);
功能:
从流中读取一个字符 (定义一个整型的变量去接收,因为返回值是ascii码)
参数:
stream:文件流指针
返回值:
成功返回读到字符的ASCII码值(所以接收数据的变量定义为int型)。
失败或者读到文件末尾返回EOF
#include <stdio.h>
int main(void)
{
FILE *fp = NULL;
int ch = 0;//因为返回的是ASCII的值,所以定义为int型
fp = fopen("file.txt", "r");
if (NULL == fp)
{
perror("fail to fopen");
return -1;
}
while (1)
{
ch = fgetc(fp);
if (EOF == ch)//失败或者读到末尾返回EOF
{
break;
}
printf("%c", ch);//因为是自动获取下一个所以不需要地址跳转下一个地址的代码
}
fclose(fp);
return 0;
}
输出的结果如下,和cat一样,所以cat的实现方式也是这样的。
需要注意的是:
fgetc不会重复的获取,获取完一个会自动跳到下一个。所以用一个fgetc,然后循环会接收到不同的字符。
等价
ch = getchar();//在终端中得到字符
ch = fgetc(stdin);//在stdin文件流中得到字符
putchar(ch);//给终端输入字符
fputc(ch, stdout);//给stdout文件流输入字符
作业:
1.编写一个程序将a.txt文件中的所有内容拷贝到b.txt文件中
#include <stdio.h>
#include "software.h"
int main(void)
{
char srcfile[256] = {0};
char dstfile[256] = {0};
int ret = 0;
printf("请输入源文件路径:\n");
gets(srcfile);
printf("请输入目的文件路径:\n");
gets(dstfile);
ret = CopyAsciiFileContent(dstfile, srcfile);
if (-1 == ret)
{
printf("拷贝内容失败\n");
}
printf("拷贝内容成功\n");
return 0;
}
#include "software.h"
#include <stdio.h>
/***************************************************
* 函数名:CopyAsciiFileContent
* 功 能:
* 将srcfile中的文件内容拷贝到dstfile文件中
* 参 数:
* dstfile:目的文件的文件路径
* srcfile:源文件的文件路径
* 返回值:
* 成功返回0
* 失败返回-1
* 注意事项:
* 1.该函数只能拷贝ASCII普通文件内容
**************************************************/
int CopyAsciiFileContent(const char *dstfile, const char *srcfile)
{
FILE *fsrc = NULL;
FILE *fdst = NULL;
int temp = 0;
fsrc = fopen(srcfile, "r");
if (NULL == fsrc)
{
goto err2;
}
fdst = fopen(dstfile, "w");
if (NULL == fdst)
{
goto err1;
}
while (1)
{
temp = fgetc(fsrc);
if (EOF == temp)
{
break;
}
fputc(temp, fdst);
}
fclose(fsrc);
fclose(fdst);
return 0;
err1:
fclose(fsrc);
err2:
return -1;
}
#ifndef __SOFTWARE_H__
#define __SOFTWARE_H__
extern int CopyAsciiFileContent(const char *dstfile, const char *srcfile);
#endif
2.编写一个程序,从终端输入文件名,统计出该文件内容(纯英文)中出现频率最高的字符及其出现次数
a.txt
#include <stdio.h>
int GetMaxFreqChar(const char *filename, char *pmaxchar, int *pmaxcnt)
{
FILE *fp = NULL;
int temp = 0;
int cnt[256] = {0};
int max = 0;
int i = 0;
fp = fopen(filename, "r");
if (NULL == fp)
{
return -1;
}
while (1)
{
temp = fgetc(fp);
if (EOF == temp)
{
break;
}
cnt[temp]++;
}
fclose(fp);
max = 0;
for (i = 0; i < 256; i++)
{
if (cnt[i] > cnt[max])
{
max = i;
}
}
if (0 == cnt[max])
{
return -1;
}
*pmaxchar = max;
*pmaxcnt = cnt[max];
return 0;
}
int main(void)
{
char filename[256] = {0};
char maxchar = 0;
int maxcnt = 0;
int ret = 0;
printf("请输入文件名:\n");
scanf("%s", filename);
ret = GetMaxFreqChar(filename, &maxchar, &maxcnt);
if (-1 == ret)
{
printf("查找出错\n");
return -1;
}
printf("出现频率最高的字符:%c , 共出现 %d 次\n", maxchar, maxcnt);
return 0;
}
6.fgets
char *fgets(char *s, int size, FILE *stream);
功能:
从流中读取一行字符串(遇到\n就会停止,并且会把\n也存起来,最后末尾会自动加\0表示字符串的结尾) 遇到\0也停止。
参数:
s:用于存放读取到的字符串
size:字符串的长度(最大可以存放的数,不是要接收多少,遇到\n就会停止)
stream:文件流指针
返回值:
成功返回存放字符串空间首地址(所以要定义一个指针去接收返回的值,来判断是否接收成功)
失败或者读到文件末尾返回NULL
#include <stdio.h>
int main(void)
{
FILE *fp = NULL;
char *pret = NULL;
char tmpbuff[4096] = {0};
fp = fopen("file.txt", "r");
if (NULL == fp)
{
perror("fail to fopen");
return -1;
}
while (1)
{
pret = fgets(tmpbuff, sizeof(tmpbuff), fp);
if (NULL == pret)
{
break;
}
printf("%s", tmpbuff);//不加\n,是因为读取会把原有的\n也加上
}
fclose(fp);
return 0;
}
注意:这里的sizeof(tmpbuff)是最大可以存放的数,不是要接收多少。
在文本文件取字符串之后的情况如下:左文本,右存放的地方
假如sizeof(tmbuff)的大小为5个,那么实际的读取4个,因为要在末尾留一个\0的位置。
7.fputs
int fputs(const char *s, FILE *stream);
功能:
向流中写入一个字符串( 遇到\0停止)
参数:
s:字符串的首地址
stream:文件流指针
返回值:
成功返回非负数
失败返回EOF
#include <stdio.h>
int main(void)
{
FILE *fp = NULL;
char tmpbuff[1024] = {"how are you"};
fp = fopen("file.txt", "w");
if (NULL == fp)
{
perror("fail to fopen");
return -1;
}
fputs("hello world", fp);
fputs(tmpbuff, fp);
fclose(fp);
return 0;
}
练习:利用fgets和fputs实现将一个文件中的内容拷贝到另一个文件中
#include <stdio.h>
/***************************************************
* 函数名:CopyAsciiFileContent2
* 功 能:
* 将srcfile中的文件内容拷贝到dstfile文件中
* 参 数:
* dstfile:目的文件的文件路径
* srcfile:源文件的文件路径
* 返回值:
* 成功返回0
* 失败返回-1
* 注意事项:
* 1.该函数只能拷贝ASCII普通文件内容
**************************************************/
int CopyAsciiFileContent2(const char *dstfile, const char *srcfile)
{
FILE *fsrc = NULL;
FILE *fdst = NULL;
char tmpbuff[4096] = {0};
char *pret = NULL;
fsrc = fopen(srcfile, "r");
if (NULL == fsrc)
{
goto err1;
}
fdst = fopen(dstfile, "w");
if (NULL == fdst)
{
goto err2;
}
while (1)
{
pret = fgets(tmpbuff, sizeof(tmpbuff), fsrc);
if (NULL == pret)
{
break;
}
fputs(tmpbuff, fdst);
}
fclose(fsrc);
fclose(fdst);
return 0;
err2:
fclose(fsrc);
err1:
return -1;
}
int main(void)
{
char srcfile[256] = {0};
char dstfile[256] = {0};
int ret = 0;
ret = CopyAsciiFileContent2("a.txt", "stdio.h");
if (-1 == ret)
{
printf("拷贝内容失败\n");
}
printf("拷贝内容成功\n");
return 0;
}
注意:
puts(tmpbuff);
fputs(tmpbuff, stdout);
puts会多打印一个\n字符
gets(tmpbuff);
fgets(tmpbuff, sizeof(tmpbuff), stdin);
gets会去掉用户输入\n字符,并加上\0,也就是把\n换成\0。
fgets不会去掉用户输入的\n字符,并且在末尾再加个\0。
那么fgets怎么将\n换成\0呢?
#include <stdio.h>
#include <string.h>
int main(void)
{
char tmpbuff[1024] = {0};
gets(tmpbuff);
printf("tmpbuff = %s\n", tmpbuff);
fgets(tmpbuff, sizeof(tmpbuff), stdin);
tmpbuff[strlen(tmpbuff)-1] = '\0';//去掉fgets接受的\n,强行转为\0.
printf("tmpbuff = %s\n", tmpbuff);
#if 0
puts("hello world");
fputs("hello world", stdout);
#endif
return 0;
}
结果如下:
8.fscanf
int fscanf(FILE *stream, const char *format, ...);
功能:
从流中读取格式化字符串
fscanf(stdin, ...);
scanf(...);
返回值:
返回值是一个整型。
#include <stdio.h>
int main(void)
{
FILE *fp = NULL;
int num1 = 0;
int num2 = 0;
fp = fopen("file.txt", "r");
if (NULL == fp)
{
perror("fail to fopen");
return -1;
}
fscanf(fp, "num1 = %d, num2 = %d", &num1, &num2);
fclose(fp);
printf("num1 = %d, num2 = %d\n", num1, num2);
return 0;
}
文件中的格式:
注意:fscanf目标文件的内容的时候,格式必须和文件里的内容一致,使用起来比较繁琐。就和scanf类似一样,代码写成啥格式,在终端输入的时候也要用一样的格式输入,
9.fprintf
int fprintf(FILE *stream, const char *format, ...);
功能:
向流中写入格式化字符串
参数:
stream:文件流指针
... :是可变参函数。
返回值:
成功返回实际打印的字节数。
失败返回-1。
#include <stdio.h>
int main(void)
{
FILE *fp = NULL;
int num1 = 100;
int num2 = 200;
fp = fopen("file.txt", "w");
if (NULL == fp)
{
perror("fail to fopen");
return -1;
}
fprintf(fp, "hello world\nnum1 = %d, num2 = %d\n", num1, num2);
fclose(fp);
return 0;
}
结果如下:
如下俩个等价:
fprintf(stdout, ...);
printf(...);
练习:
将score.csv中每个学生的成绩获得平均值逐行写入到avg.csv中
#include <stdio.h>
int main(void)
{
FILE *fsrc = NULL;
FILE *fdst = NULL;
int score1 = 0;
int score2 = 0;
int score3 = 0;
double avgscore = 0;
int ret = 0;
fsrc = fopen("score.csv", "r");
if (NULL == fsrc)
{
perror("fail to fopen");
return -1;
}
fdst = fopen("avg.csv", "w");
if (NULL == fdst)
{
perror("fail to fopen");
fclose(fsrc);
return -1;
}
while (1)
{
ret = fscanf(fsrc, "%d,%d,%d", &score1, &score2, &score3);
if (EOF == ret)
{
break;
}
avgscore = (score1 + score2 + score3) / 3.0;
fprintf(fdst, "%.2lf\n", avgscore);
}
fclose(fsrc);
fclose(fdst);
return 0;
技巧:在使用fprintf和fscanf的时候,可以先像写printf和scanf的时候的格式写,之后在补充目标文件流。
10.fread
可以操作二进制文件,图片,压缩包等,前面的都是ascii码文件。
ascii中的一个字节一个字节的存放,2对应的ascii码的大小为48,48在二进制中为00110010。ascii码文件是一种特殊的二进制文件。
二进制文件2024是以整体的形式,也就是整型,4个字节,一个字节8位,总共32位。
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:
从流中读取nmemb个对象,每个对象size个字节,在ptr指向的空间中存放
参数:
ptr:存放数据空间的首地址
size:每个对象的大小
nmemb:写入对象的个数
stream:文件流指针
返回值:
成功返回实际读取对象的个数(最好用size_t 类型的变量接收)
失败或者读到文件末尾返回0
#include <stdio.h>
typedef struct student
{
char name[32];
char sex;
int age;
int score;
}stu_t;
int main(void)
{
FILE *fp = NULL;
stu_t temp;
stu_t s[4];
int i = 0;
size_t nret = 0;
fp = fopen("file.txt", "r");
if (NULL == fp)
{
perror("fail to fopen");
return -1;
}
nret = fread(s, sizeof(stu_t), 4, fp);//一次性读4组。
for (i = 0; i < nret; i++)//这里接收到多少也就是nret,就循环多少次。
{
printf("姓名:%s\n", s[i].name);
printf("性别:%c\n", s[i].sex);
printf("年龄:%d\n", s[i].age);
printf("成绩:%d\n", s[i].score);
}
#if 0
while (1)
{
nret =fread(&temp,sizeof(stu t),1, fp);//一次性读1组,读4次。
if(0 == nret)
{
break;
}
printf("姓名:%s\n"temp.name);
printf("性别:名c\n",temp.sex);
printf("年龄:%d\n",temp.age);
printf("成绩:%d\n",temp.score);
}
#endif
fclose(fp);
return 0;
}
11.fwrite
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:
向流中写入nmemb个对象,每个对象size个字节,要写入的内容在ptr指向的空间中存放
参数:
ptr:写入数据空间的首地址
size:每个对象的大小
nmemb:写入对象的个数
stream:文件流指针
返回值:
成功返回实际写入对象的个数,返回类型位size_t类型。
失败返回0
#include <stdio.h>
typedef struct student
{
char name[32];
char sex;
int age;
int score;
}stu_t;
int main(void)
{
FILE *fp = NULL;
stu_t a = {"张三", 'm', 19, 100};
stu_t b = {"李四", 'f', 18, 90};
stu_t s[2] = {
{"王二", 'm', 16, 90},
{"赵五", 'f', 14, 30},
};
size_t nret = 0;
fp = fopen("file.txt", "w");
if (NULL == fp)
{
perror("fail to fopen");
return -1;
}
nret = fwrite(&a, sizeof(a), 1, fp);
printf("nret = %ld\n", nret);
nret = fwrite(&b, sizeof(b), 1, fp);
printf("nret = %ld\n", nret);
nret = fwrite(s, sizeof(stu_t), 2, fp);
printf("nret = %ld\n", nret);
fclose(fp);
return 0;
}
首先写入的是结构体的大小
第二个char是一个字节,要内存对齐,所以空出来3个字节。
所以总共占176个字节。
一次性写入多个内容,那么要把写入的内容放在一起,也就是类似上面s[2]一个数组可以有多个内容,因为fwrite的地址只有一个。fwrite(s, sizeof(stu_t), 2, fp);
作业:
1.从终端输入一个单词,打印出该单词的含义
练习:
1.利用fread和fwrite实现文件的拷贝
char tmpbuff[4096];
图片的拷贝
#include <stdio.h>
int main(void)
{
FILE *fsrc = NULL;
FILE *fdst = NULL;
size_t nret = 0;
char tmpbuff[4096] = {0};
//打开源文件
fsrc = fopen("src.jpg", "r");
if (NULL == fsrc)
{
perror("fail to fopen");
return -1;
}
//打开目的文件
fdst = fopen("dst.jpg", "w");
if (NULL == fdst)
{
perror("fail to fopen");
fclose(fsrc);
return -1;
}
while (1)
{
nret = fread(tmpbuff, 1, sizeof(tmpbuff), fsrc);//每次读一个对象,读sizeof大小个。
if (0 == nret)
{
break;
}
fwrite(tmpbuff, 1, nret, fdst);
}
fclose(fsrc);
fclose(fdst);
return 0;
}
12.fseek
流的定位
偏移量:读和写都在偏移量的位置进行
int fseek(FILE *stream, long offset, int whence);
功能:
设置流的偏移量
参数:
stream:文件流指针
offset:偏移量
whence:
SEEK_SET 文件开头
SEEK_CUR 当前位置
SEEK_END 文件结尾
返回值:
成功返回当前偏移量
失败返回-1
#include <stdio.h>
int main(void)
{
FILE *fp = NULL;
fp = fopen("file.txt", "w");
if (NULL == fp)
{
perror("fail to fopen");
return -1;
}
fseek(fp, 10, SEEK_SET);
fputc('a', fp);
fseek(fp, -5, SEEK_CUR);
fputc('b', fp);
fseek(fp, 0, SEEK_SET);
fputc('c', fp);
fclose(fp);
return 0;
}
结果如下:
od -c file.txt是以字符的形式展现
13.ftell
long ftell(FILE *stream);
功能:
获取流的偏移量
返回值:
整型的偏移量
如下利用ftell, 通过偏移量获得文件的大小。
#include <stdio.h>
int main(void)
{
FILE *fp = NULL;
long len = 0;
fp = fopen("/usr/include/stdio.h", "r");
if (NULL == fp)
{
perror("fail to fopen");
return -1;
}
fseek(fp, 0, SEEK_END);
len = ftell(fp);
printf("len = %ld\n", len);
fclose(fp);
return 0;
}
14.rewind
void rewind(FILE *stream);
功能:
将流的偏移量重新设置到开头
fseek(fp, 0, SEEK_SET);
练习:
编写程序随便给定一个bmp图片文件名获得图片的宽度和高度
#include <stdio.h>
int main(void)
{
FILE *fp = NULL;
int width = 0;
int height = 0;
fp = fopen("suibian.bmp", "r");
if (NULL == fp)
{
perror("fail to fopen");
return -1;
}
fseek(fp, 18, SEEK_SET);//存储文件大小的信息在18个字节之后,所以偏移18。
fread(&width, 4, 1, fp); //宽度占4字节,储存的类型是long类型,是二进制形式,所以要用fread。
fread(&height, 4, 1, fp); //高度占4字节
fclose(fp);
printf("宽度:%d 高度:%d\n", width, height);
return 0;
}
5.单词查询
用strncmp,strcmp+strtok,指针
#include <stdio.h>
#include <string.h>
int GetWordMean(const char *pfilename, char *pword, char *pmean)
{
FILE *fp = NULL;
char *pret = NULL;
int isexist = 0;
char tmpbuff[4096] = {0};
char *ptmp = NULL;
fp = fopen(pfilename, "r");
if (NULL == fp)
{
return -1;
}
while (1)
{
pret = fgets(tmpbuff, sizeof(tmpbuff), fp);
if (NULL == pret)
{
break;
}
#if 0
if (0 == strncmp(tmpbuff, pword, strlen(pword))) //读取一行,比较单词是否相同,相同则复制到pmean。
{
strcpy(pmean, tmpbuff);
isexist = 1;
break;
}
if (0 == strcmp(pword, strtok(tmpbuff, " "))) //strtok的使用。
{
strcpy(pmean, strtok(NULL, "\r"));
isexist = 1;
break;
}
#else
ptmp = tmpbuff;
while (*ptmp != '\0' && *ptmp != ' ')
{
ptmp++;
}
*ptmp = '\0';
ptmp++;
if (0 == strcmp(pword, tmpbuff))
{
while (*ptmp == ' ' && *ptmp != '\0')
{
ptmp++;
}
strcpy(pmean, ptmp);
isexist = 1;
break;
}
#endif
}
fclose(fp);
return isexist;
}
int main(void)
{
char word[256] = {0};
char mean[1024] = {0};
int ret = 0;
printf("请输入一个单词:\n");
fgets(word, sizeof(word), stdin);
word[strlen(word)-1] = '\0';
ret = GetWordMean("dict.txt", word, mean);
if (-1 == ret)
{
printf("查找出错\n");
}
else if (0 == ret)
{
printf("未找到\n");
}
else if (1 == ret)
{
printf("%s 含义: %s\n", word, mean);
}
return 0;
}
用内核链表
#include <stdio.h>
#include <string.h>
#include "list.h"
/* 定义链表节点类型 */
typedef struct word
{
struct list_head node; //节点
char word[256]; //单词
char mean[1024]; //含义
}word_t;
int GetWordMean(const char *pfilename, char *pword, char *pmean)
{
FILE *fp = NULL;
char *pret = NULL;
int isexist = 0;
char tmpbuff[4096] = {0};
/* 创建一个节点并对节点初始化 */
struct list_head head;
INIT_LIST_HEAD(&head);
fp = fopen(pfilename, "r");
if (NULL == fp)
{
return -1;
}
while (1)
{
pret = fgets(tmpbuff, sizeof(tmpbuff), fp);
if (NULL == pret)
{
break;
}
/* 申请一个节点,存入数据,插入链表中 */
word_t *ptmp = malloc(sizeof(word_t)); //用word_t tmp是局部变量,会被回收,所以要用malloc来申请一个空间。
if (NULL == ptmp)
{
return -1;
}
strcpy(ptmp->word, strtok(tmpbuff, " "));
strcpy(ptmp->mean, strtok(NULL, "\r")); //存入数据
list_add_tail(&ptmp->node, &head); //插入到链表中
}
fclose(fp);
/* 查找单词 */
struct list_head *ptmp = NULL; //定义一个指针去遍历
list_for_each(ptmp, &head)
{
if (0 == strcmp(pword, ((word_t *)ptmp)->word))
{
strcpy(pmean, ((word_t *)ptmp)->mean);
isexist = 1;
break;
}
}
/* 销毁链表中所有已存在的节点 */
list_for_each(ptmp, &head)
{
struct list_head *p = ptmp->prev;
list_del(ptmp);
free(ptmp);
ptmp = p;
}
return isexist;
}
int main(void)
{
char word[256] = {0};
char mean[1024] = {0};
int ret = 0;
printf("请输入一个单词:\n");
fgets(word, sizeof(word), stdin);
word[strlen(word)-1] = '\0';
ret = GetWordMean("dict.txt", word, mean);
if (-1 == ret)
{
printf("查找出错\n");
}
else if (0 == ret)
{
printf("未找到\n");
}
else if (1 == ret)
{
printf("%s 含义: %s\n", word, mean);
}
return 0;
}