熬夜整理的C语言/C++万字总结(六)

简介: 熬夜整理的C语言/C++万字总结

1.2.4.2 行读写函数


int fputs(const char * str, FILE * stream);

功能:将 str 所指定的字符串写入到 stream 指定的文件中, 字符串结束符 '\0' 不写入文件。


参数:


str:字符串。 stream:文件指针


返回值:


成功:0。 失败:-1


char * fgets(char * str, int size, FILE * stream);

功能:从 stream 指定的文件内读入字符,保存到 str 所指定的内存空间,直到出现换行字符、读到文件结尾或是已读了 size - 1 个字符为止,最后会自动加上字符 '\0' 作为字符串结束。


参数:


str:字符串。


size:指定最大读取字符串的长度(size - 1)。


stream:文件指针


void test(){
 //写文件
 FILE* fp_write= NULL;
 //写方式打开文件
 fp_write = fopen("./mydata.txt", "w+");
 if (fp_write == NULL){
  perror("fopen:");
  return;
 }
 char* buf[] = {
  "01 this is a test for pfutc!\n",
  "02 this is a test for pfutc!\n",
  "03 this is a test for pfutc!\n",
  "04 this is a test for pfutc!\n",
 };
 for (int i = 0; i < 4; i ++){
  fputs(buf[i], fp_write);
 }
 fclose(fp_write);
 //读文件
 FILE* fp_read = NULL;
 fp_read = fopen("./mydata.txt", "r");
 if (fp_read == NULL){
  perror("fopen:");
  return;
 }
 //判断文件结尾
 while (!feof(fp_read)){
  char temp[1024] = { 0 };
  fgets(temp, 1024, fp_read);
  printf("%s",temp);
 }
 fclose(fp_read);
}


1.2.4.3 块读写函数


size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

功能:以数据块的方式给文件写入内容。


参数:


ptr:准备写入文件数据的地址


size: size_t 为 unsigned int类型,此参数指定写入文件内容的块数据大小


nmemb:写入文件的块数,写入文件数据总大小为:size * nmemb


stream:已经打开的文件指针


返回值:


成功:实际成功写入文件数据的块数,此值和nmemb相等


失败:0


size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

功能:以数据块的方式从文件中读取内容


参数:


ptr:存放读取出来数据的内存空间


size: size_t 为 unsigned int类型,此参数指定读取文件内容的块数据大小


nmemb:读取文件的块数,读取文件数据总大小为:size * nmemb


stream:已经打开的文件指针


返回值:


成功:实际成功读取到内容的块数,如果此值比nmemb小,但大于0,说明读到文件的结尾。


失败:0


typedef struct _TEACHER{
 char name[64];
 int age;
}Teacher;
void test(){
 //写文件
 FILE* fp_write= NULL;
 //写方式打开文件
 fp_write = fopen("./mydata.txt", "wb");
 if (fp_write == NULL){
  perror("fopen:");
  return;
 }
 Teacher teachers[4] = {
  { "Obama", 33 },
  { "John", 28 },
  { "Edward", 45},
  { "Smith", 35}
 };
 for (int i = 0; i < 4; i ++){
  fwrite(&teachers[i],sizeof(Teacher),1, fp_write);
 }
 //关闭文件
 fclose(fp_write);
 //读文件
 FILE* fp_read = NULL;
 fp_read = fopen("./mydata.txt", "rb");
 if (fp_read == NULL){
  perror("fopen:");
  return;
 }
 Teacher temps[4];
 fread(&temps, sizeof(Teacher), 4, fp_read);
 for (int i = 0; i < 4;i++){
  printf("Name:%s Age:%d\n",temps[i].name,temps[i].age);
 }
 fclose(fp_read);
}


1.2.4.4 格式化读写函数


int fprintf(FILE * stream, const char * format, ...);

功能:根据参数format字符串来转换并格式化数据,然后将结果输出到stream指定的文件中,指定出现字符串结束符 '\0' 为止。 参数:


stream:已经打开的文件


format:字符串格式,用法和printf()一样


返回值:


成功:实际写入文件的字符个数


失败:-1


int fscanf(FILE * stream, const char * format, ...);

功能:从stream指定的文件读取字符串,并根据参数format字符串来转换并格式化数据。


参数:


stream:已经打开的文件


format:字符串格式,用法和scanf()一样


返回值:


成功:实际从文件中读取的字符个数


失败: - 1


注意:fscanf遇到空格和换行时结束。


void test(){
 //写文件
 FILE* fp_write= NULL;
 //写方式打开文件
 fp_write = fopen("./mydata.txt", "w");
 if (fp_write == NULL){
  perror("fopen:");
  return;
 }
 fprintf(fp_write,"hello world:%d!",10);
 //关闭文件
 fclose(fp_write);
 //读文件
 FILE* fp_read = NULL;
 fp_read = fopen("./mydata.txt", "rb");
 if (fp_read == NULL){
  perror("fopen:");
  return;
 }
 char temps[1024] = { 0 };
 while (!feof(fp_read)){
  fscanf(fp_read, "%s", temps);
  printf("%s", temps);
 }
 fclose(fp_read);
}


1.2.5.5 随机读写函数


int fseek(FILE *stream, long offset, int whence);

功能:移动文件流(文件光标)的读写位置。


参数:


stream:已经打开的文件指针


offset:根据 whence 来移动的位移数(偏移量),可以是正数,也可以负数,如果正数,则相对于 whence 往右移动,如果是负数,则相对于 whence 往左移动。如果向前移动的字节数超过了文件开头则出错返回,如果向后移动的字节数超过了 文件末尾,再次写入时将增大文件尺寸。


whence:其取值如下:


SEEK_SET:从文件开头移动offset个字节


SEEK_CUR:从当前位置移动offset个字节


SEEK_END:从文件末尾移动offset个字节


返回值:


成功:0


失败:-1


long ftell(FILE *stream);

功能:获取文件流(文件光标)的读写位置。


参数:stream:已经打开的文件指针


返回值:


成功:当前文件流(文件光标)的读写位置


失败:-1


void rewind(FILE *stream);

功能:把文件流(文件光标)的读写位置移动到文件开头。


参数:stream:已经打开的文件指针


返回值:无返回值


typedef struct _TEACHER{
 char name[64];
 int age;
}Teacher;
void test(){
 //写文件
 FILE* fp_write = NULL;
 //写方式打开文件
 fp_write = fopen("./mydata.txt", "wb");
 if (fp_write == NULL){
  perror("fopen:");
  return;
 }
 Teacher teachers[4] = {
  { "Obama", 33 },
  { "John", 28 },
  { "Edward", 45 },
  { "Smith", 35 }
 };
 for (int i = 0; i < 4; i++){
  fwrite(&teachers[i], sizeof(Teacher), 1, fp_write);
 }
 //关闭文件
 fclose(fp_write);
 //读文件
 FILE* fp_read = NULL;
 fp_read = fopen("./mydata.txt", "rb");
 if (fp_read == NULL){
  perror("fopen:");
  return;
 }
 Teacher temp;
 //读取第三个数组
 fseek(fp_read , sizeof(Teacher) * 2 , SEEK_SET);
 fread(&temp, sizeof(Teacher), 1, fp_read);
 printf("Name:%s Age:%d\n",temp.name,temp.age);
 memset(&temp,0,sizeof(Teacher));
 fseek(fp_read, -(int)sizeof(Teacher), SEEK_END);
 fread(&temp, sizeof(Teacher), 1, fp_read);
 printf("Name:%s Age:%d\n", temp.name, temp.age);
 rewind(fp_read);
 fread(&temp, sizeof(Teacher), 1, fp_read);
 printf("Name:%s Age:%d\n", temp.name, temp.age);
 fclose(fp_read);
}


1.4 文件读写案例


读写配置文件


配置文件格式如下:


正式的数据以 ‘:’ 冒号进行分割,冒号前为 key 起到索引作用,冒号后为 value 是实值。# 开头的为注释,而不是正式数据


#英雄的Id heroId:1 #英雄的姓名 heroName:德玛西亚 #英雄的攻击力 heroAtk:1000 #英雄的防御力 heroDef:500 #英雄的简介 heroInfo:前排坦克  


struct ConfigInfo
{
 char key[64];
 char value[64];
};
//获取文件有效行数
int getFileLine(const char  * filePath)
{
 FILE * file = fopen(filePath, "r");
 char buf[1024] = {0};
 int lines = 0;
 while (fgets(buf,1024,file) != NULL)
 {
  if (isValidLine(buf))
  {
   lines++;
  }
  memset(buf, 0, 1024);
 }
 fclose(file);
 return lines;
}
//解析文件
void parseFile(const char  * filePath, int lines, struct ConfigInfo** configInfo)
{
 struct ConfigInfo * pConfig =  malloc(sizeof(struct ConfigInfo) * lines);
 if (pConfig == NULL)
 {
  return;
 }
 FILE * file = fopen(filePath, "r");
 char buf[1024] = { 0 };
 int index = 0;
 while (fgets(buf, 1024, file) != NULL)
 {
  if (isValidLine(buf))
  {
   //解析数据到struct ConfigInfo中
   memset(pConfig[index].key, 0, 64);
   memset(pConfig[index].value, 0, 64);
   char * pos = strchr(buf, ':');
   strncpy(pConfig[index].key, buf, pos - buf);
   strncpy(pConfig[index].value, pos + 1, strlen(pos + 1) - 1); // 从第二个单词开始截取字符串,并且不截取换行符
   //printf("key = %s\n", pConfig[index].key);
   //printf("value = %s\n", pConfig[index].value);
   index++;
  }
  memset(buf, 0, 1024);
 }
 *configInfo = pConfig;
}
//获取指定的配置信息
char * getInfoByKey(char * key, struct ConfigInfo*configInfo ,int lines)
{
 for (int i = 0; i < lines;i++)
 {
  if (strcmp(key, configInfo[i].key) == 0)
  {
   return configInfo[i].value;
  }
 }
 return NULL;
}
//释放配置文件信息
void freeConfigInfo(struct ConfigInfo*configInfo)
{
 free(configInfo);
 configInfo = NULL;
}
//判断当前行是否为有效行
int isValidLine(char * buf)
{
 if (buf[0] == '0' || buf[0] == '\0' || strchr(buf,':') == NULL)
 {
  return 0;// 如果行无限 返回假
 }
 return 1;
}
int main(){
 char * filePath = "./config.txt";
 int lines = getFileLine(filePath);
 printf("文件有效行数为:%d\n", lines);
 struct ConfigInfo * config = NULL;
 parseFile(filePath, lines, &config);
 printf("heroId = %s\n", getInfoByKey("heroId", config, lines));
 printf("heroName: = %s\n", getInfoByKey("heroName", config, lines));
 printf("heroAtk = %s\n", getInfoByKey("heroAtk", config, lines));
 printf("heroDef: = %s\n", getInfoByKey("heroDef", config, lines));
 printf("heroInfo: = %s\n", getInfoByKey("heroInfo", config, lines));
 freeConfigInfo(config);
 config = NULL;
 system("pause");
 return EXIT_SUCCESS;
}
相关文章
|
1月前
|
安全 编译器 C语言
C++入门1——从C语言到C++的过渡
C++入门1——从C语言到C++的过渡
48 2
|
1月前
|
C语言 C++
C 语言的关键字 static 和 C++ 的关键字 static 有什么区别
在C语言中,`static`关键字主要用于变量声明,使得该变量的作用域被限制在其被声明的函数内部,且在整个程序运行期间保留其值。而在C++中,除了继承了C的特性外,`static`还可以用于类成员,使该成员被所有类实例共享,同时在类外进行初始化。这使得C++中的`static`具有更广泛的应用场景,不仅限于控制变量的作用域和生存期。
45 10
|
2月前
|
算法 机器人 C语言
ROS仿真支持C++和C语言
ROS仿真支持C++和C语言
60 1
|
1月前
|
C语言 C++
实现两个变量值的互换[C语言和C++的区别]
实现两个变量值的互换[C语言和C++的区别]
16 0
|
3月前
|
编译器 Linux C语言
【C++小知识】为什么C语言不支持函数重载,而C++支持
【C++小知识】为什么C语言不支持函数重载,而C++支持
|
3月前
|
存储 编译器 C语言
C++内存管理(区别C语言)深度对比
C++内存管理(区别C语言)深度对比
82 5
|
2月前
|
编译器 C语言 C++
从C语言到C++
本文档详细介绍了C++相较于C语言的一些改进和新特性,包括类型检查、逻辑类型 `bool`、枚举类型、可赋值的表达式等。同时,文档还讲解了C++中的标准输入输出流 `cin` 和 `cout` 的使用方法及格式化输出技巧。此外,还介绍了函数重载、运算符重载、默认参数等高级特性,并探讨了引用的概念及其应用,包括常引用和引用的本质分析。以下是简要概述: 本文档适合有一定C语言基础的学习者深入了解C++的新特性及其应用。
|
4月前
|
程序员 编译器 C语言
云原生部署问题之C++中的nullptr相比C语言中的NULL优势如何解决
云原生部署问题之C++中的nullptr相比C语言中的NULL优势如何解决
53 10
|
5月前
|
存储 Linux C语言
c++进阶篇——初窥多线程(二) 基于C语言实现的多线程编写
本文介绍了C++中使用C语言的pthread库实现多线程编程。`pthread_create`用于创建新线程,`pthread_self`返回当前线程ID。示例展示了如何创建线程并打印线程ID,强调了线程同步的重要性,如使用`sleep`防止主线程提前结束导致子线程未执行完。`pthread_exit`用于线程退出,`pthread_join`用来等待并回收子线程,`pthread_detach`则分离线程。文中还提到了线程取消功能,通过`pthread_cancel`实现。这些基本操作是理解和使用C/C++多线程的关键。
|
4月前
|
编译器 C语言 C++
C++从遗忘到入门问题之C++持从C语言的过渡问题如何解决
C++从遗忘到入门问题之C++持从C语言的过渡问题如何解决