黑马程序员------C语言基础 预处理指令、文件操作及其他

 ------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

预处理指令、文件操作及其他

 以""号开头的预处理指令,如命令#include,宏定义命令#define等。在源程序中这么命令都放在函数之外,而且都放在源文件前面,他们称为预处理部分

 所谓预处理是指在进行编译的第一遍(词法扫描和语法分析)之前的工作。

  x 语言多种预处理指令功能:宏定义、文件包含、条件编译

                             .o      .out

 源程序->预处理(宏替换)编译 -链接-> 执行程序

 一、预处理指令

1、宏定义

     宏:在c语言中我们自定义的标示符,习惯大写

    #include 宏名 宏字符串 (可以是常量、变量、表达式)

    注意:预处理指令,经常写在函数之前

 宏替换:源程序在编译之前,由预处理程序对我们写的源代码进行处理:会把源代码中所出现 宏名 的地方一律使用 宏的字符串 去替换

  宏使用的注意事项:

    1.宏是有作用域的 #undef 宏名 可以取消宏定义

     #include R 4

        int a= R

      #define R M  这里取消宏定义,下面的代码用不了宏了

 

    2.在字符串中出现的宏名不会被替换

 

    3.宏定义可以嵌套使用

    #define R 4

    #define PI 3.14

    #define AREA PI*R*R //嵌套定义

    4,使用宏起别名

        #include INT1 int

       这样就可以 这么定义整型

       INT1 a=10;

 

    5.有参数宏和无参数宏

      无参数宏 #include M 10

      有参数宏 #define SUM(a) aa

        有参数宏的使用注意事项:

       宏的形参之间可以出现空格 ,但是宏名和形参之间不能空格

        有参数宏 宏的参数最好用括号括起来

 应用使用有参宏求最大值

 #include <stdio.h>

  //定义一个有参宏 求两个数的最大值

 #define MAX(a,b) a>b?a:b

  int main(int argc, const char * argv[]) {

 // 调用宏

  int c =MAX(3, 4);

 printf("最大值是%d",c);

 

 return 0;

 }

 

  6 typedef 和#include 的区别

 当 #include INT1 int 

    typedef int INT2;

   这里 INT1 a,b      ab都是定义的整型变量

        INT2 a,b     也一样是整型变量

  定义指针时

    #include INT3 int*

     typedef int*  INT4 ;

     INT1 f1,f2 =NULL;  这里f1 zhiz  f2只是个整型变量 说明宏的定义知识单纯的文本复制的替换

     INT4 f1,f2 = NULL; 这里 f1f2 都是指针。

2.条件编译指令

   1. if -#elseif

   条件编译 :

   发生在预处理阶段 ,在编译之前做的事情

 核心:根据条件编译指定的代码

  条件不同,编译的部分也不同,生成的目标文件(.o)大小也不一样

   传统方式 

   int score =76;

  判断成句属于哪个成绩

    ifscore<60){

        printf("E\n");

    }else if(score<= 69){

        printf("d\n");

    }else if(score<= 79){

        printf("c\n");

    }else if(score<= 89){

        printf("b\n");

    }else {

        printf("A\n")

 }

 #if score <60

  printf("E\n");

 #elif scoe <=69

 printf("d\n");

 #elif scoe <=79

 printf("c\n");

 #elif scoe <=89

  printf("b\n");

 #else 

     printf("a\n");

 #endif

   这里只选择一个符合要求的score 进行一段代码的预编译

 2.ifdef 有来判断某个宏是否定义

  #include DEBUG1 1

 int a=0;

  #ifdef DEBUG1    DEBUG11是执行 a10 

        a=10;         否则执行 a100

 #else

        a=100;

 #endif

 3.使用条件编译指令调试bug

    #if DEBUG1 ==1   10 1显示调试信息  0不显示调试信息

  //显示调试信息

  #define Log(format,....)printf(format,##__VA_ARGS__);

 #else 

   #define Log(format,.......)

 //不显示调试信息

 #endif

二、文件操作

1。文件概念

 文件; 指存储在外部介质上数据的集合,这个数据有一个名称,叫做文件名

文件的分类 从用户角度 文件分为普通文件和设备文件

            从文件编码 文件分ascii码文件和二进制文件

 文件操作的步骤

   1)引入头文件<stdio.h>

   2)定义文件指针

   3)打开文件

   4)文件读写

   5)关闭文件

 对文件读和写是最常用的文件操作,在c语言中提供了多种文件读写的函数

    字符读写函数 fgetcfputc

    读写字符串函数 fgetsfputs

    数据快读写函数 fread fwrite

    格式化读写 fscanf fprintf

  c语言文件指针

    在c语言中用一个指针变量指向一个文件,这个指针称为文件指针

  文件指针

    FILE *指针变量表示符;

 2。文件的打开和关闭函数

  文件操作步骤 

  1)引入头文件 stdio.h

  2)建立文件指针  FILE *fp =NULL;

  3)打开文件   fopen(文件名,操作方式)

     如果文件打开成功返回文件收地址,失败返回NULL

 4)操作文件

5)关闭文件 fclose(文件指针);

 #include <stdio.h>
 int main(int argc, const char * argv[]) {
 //定义文件指针
 FILE *fp =NULL;
 //打开文件  是文件操作方式
 fp =fopen("a.txt", "r");
 //fopen成功,返回的是文件首地址
 //fopen失败 返回NULL
 if(fp!=NULL){
 //文件操作
 printf("文件打开成功\n");
 }else{
 
 //给用户提示
 printf("文件打开失败,请任意键退出\n");
 //按任意键推出
 getchar();//要求从键盘接受一个字符
 //退出
 exit(1);//非正常退出
 
 }
 //文件关闭
 
 fclose(fp);
 
 return 0;
 }

 3文件使用的方式及注意事项

  文件使用方式

 4字符读写函数 fgetcputc

     字符读写函数是以字符(字节)为单位的读写函数。每次可以从文件读出或向文件写入一个字符

     fputc() 写入一个字符到文件中

        假设把 ch写到 fputc1.txt 文件中

       char ch 'x''

#include <stdio.h>
 void test(){
 
 char ch ='x';
 //打开文件 打开fputc1.txt 以w方式(写,如果文件不存在可创建)
 FILE *fp=fopen("fputc1.txt", "w");
 //判断文件是否打开成功
 if (fp != NULL) {
 //将ch 要写入的字符  文件指针
 //写到fput1.txt文件中
 fputc(ch,fp);
 printf("写入成功\n");
 }
 //关闭文件
 fclose(fp);
 
 }
 
 int main(int argc, const char * argv[]) {
 FILE *fp=fopen("fputc1.txt", "r");
 //判断文件是否打开成功
 c = fgetc(fp);

 if (fp != NULL) {
 //字符文件要读取到的位置 c 文件指针
 //写到fput1.txt文件中
 printf("%c\n",c);
 printf("文件打开成功\n");
 }
 //关闭文件
 fclose(fp);
   return 0;
 
 }
 
 使用 fgetc 和fputc 读取和写入字符串
 #include <stdio.h>
 #include <string.h>
  int main(int argc, const char * argv[]) {
 //定义文件指针,打开文件 futcString.txt 以w写入
 FILE *fp=fopen("fputcString.txt","r");
 if(fp!=NULL){
 //        char ch[]="i love china";
 //        for(int i=0;i <strlen(ch);i++){
 //            fputc(ch[i], fp);
 //            printf("文件写入成功]\n");
 //        }
 //
 char s =fgetc(fp);
 //EOF是文件的末尾的标志
 //s ==EOF 可以理解为,已经读取到文件的最后了
 while (s!=EOF) {
 putchar(s);//输出字符
 s = fgetc(fp);//又从文件中读取下一个字符。这里fgetc 会自动转换指针指向下一个字符。
 }
 
 
 }
    fclose(fp);
 return 0;
 }
 
 保存键盘输入的字符串
 #include <stdio.h>
   int main(int argc, const char * argv[]) {
 FILE *fp =fopen("string1.txt","w+");
 if (fp!=NULL) {
 printf("请输入一个字符串\n");
 char ch;
 ch = getchar();
<pre class="csharp" name="code">5.字符串读写函数 fgets 和fputs
 #include <stdio.h>
 
 int main(int argc, const char * argv[]) {
 //把字符串写入到文件中去
 char str[]="welcome to yilake";
 FILE *fp = fopen("fputsstring.txt", "w+");
 if (fp!=NULL) {
 int count =0;
 // 写入字符串到文件中 ,count 返回读取的字符数
 count = fputs(str,fp );
 printf("写入成功,本次写入%d个字节]\n",count);
 
 rewind(fp);
 char str1[20];
 //从文件中读取字符到字符数组str1中
 //  数组名   长度     文件指针
 
 fgets(str1, sizeof(str1),fp);
 // fgets读取的时候,当文件读取完会自动的给字符后面加'\0'
 //fgets读取的时候,遇到\n或者EOF ,读取完毕
 printf("输入的字符串是%s",str1);
 }
 //关闭文件指针
 fclose(fp);
  return 0;
 }

int count = 0; while (ch!='\n') { count++; fputc(ch, fp);//把字符保存到文件中 ch = getchar();//获取下一个字符串 } printf("本次一共写入了%d个字符\n",count); printf("1----------\n"); rewind(fp);//作用是把问价指针,重新指向文件首地址 int k = 0; //从文件中读取一个字符 ch = fgetc(fp); while (ch!=EOF) { k++; //显示到控制台 putchar(ch); //读取一个字符 ch =fgetc(fp); } printf("本次共输出了%d个字符\n",k); } fclose(fp); //关闭读取文件 return 0; }
 

 6.数据快的读写函数fread fwrite

  一般形式fread(buffer,size,count,fp);

        fwrite(buffer,size,count,fp);

  buffer时指针用来存放数据输入的首地址 表示存放数据输出的首地址

  size 表示数据块字节数

 count 表示要读写的数据块块数

 fp  表示文件指针

 #include <stdio.h>
 #include <string.h>
 
 int main(int argc, const char * argv[]) {
 //fwrite 写一个数据块
 //先写一个字符串
 FILE *fp =fopen("fwrite.txt", "w+");
 if (fp!=NULL) {
 //        写文件
 char *str ="helloworld!";
 //fwrite(地址,块大小,数据,文件指针);
 fwrite(str,strlen(str),1,fp);
 printf("文件写入成功\n");
 rewind(fp);
 char str1[12];
 //读出一个到字符数组str1中
 fread(str1, sizeof(str1), 1, fp);
 printf("%s",str1);
 }
 fclose(fp);
 return 0;
 }
 应用读写结构体
 #include <stdio.h>
 struct Student{
 char name[21];
 int age;
 float score;
 
 
 };
 int main(int argc, const char * argv[]) {
 struct Student stu[2]={{"李白",18,88.88f},{"杜甫",23,99.99f}};
 FILE *fp =fopen("studentScore.data","wb+");
 if (fp!=NULL) {
 for (int i=0; i<2; i++) {
 //从文件中读取一个元素(32)到stu中去
 //每次都写入一个元素
 fwrite(&stu[i], sizeof(struct Student), 1,fp);
 }
 
 printf("写入成功\n");
 printf("————————————————— ii\n");
 rewind(fp);
 struct Student stu1[2];
 //从文件循环读取
 for (int i=0; i<2; i++) {
 //从文件中读取一个元素(32)到stu中去
 fread(&stu1[i], sizeof(struct Student), 1,fp);
 }
 //查看读取数据
 for (int i = 0; i<2; i++) {
 printf("姓名%s 年龄%d 成绩%.2f\n",stu1[i].name,stu1[i].age,stu1[i].score);
 }
 }
 
 fclose(fp);
 return 0;
 }


 

7.格式化读写函数 fscanf和 fprintf

  两个函数调用的格式

    fscanf(文件指针,格式字符串,输入列表);

    fprintf(文件zhiz,格式化字符串,输出列表);

 列如要求 把数据照这个样格式 

    0#1;

    1#2;

    2#3;

#include <stdio.h>

  int main(int argc, const char * argv[]) {
 
 FILE *fp =fopen("fprintf.txt", "w+");
 if (fp!=NULL) {
 int a= 3,b=4;
 fprintf(fp,"%d#%d;",a,b );
 printf("写入成功\n");
 
 rewind(fp);//指针回到文件首地址
 int m=0,n=0;
 //从文件中读取数据到变量中
 fscanf(fp, "%d#%d;",&m,&n);
 printf("%d,%d",m,n);
 
 }
 fclose(fp);
 return 0;
 }

8.读取和写入一个二维数组

#include <stdio.h>
 int main(int argc, const char * argv[]) {
 int a[3][2]={1,2,3,4,5,6};
 FILE *fp =fopen("arr.txt", "w+");
 if (fp!=NULL) {
 for (int i=0; i<3; i++) {
 fprintf(fp, "%d,%d#", a[i][0],a[i][1]);
 }
 printf("写入成功\n");
 rewind(fp);
 int c[3][2];
 for (int i=0; i < 3; i++) {
 fscanf(fp, "%d,%d#",&c[i][0],&c[i][1]);
 }
 for (int i=0; i<3; i++) {
 for (int j=0; j <2 ;j++ ) {
 printf("%d\t",c[i][j]);
 }
 }
 
 }
 fclose(fp);
 return 0;
 }


 

9文件的随机读写实现

   fseek(文件zhiz,位移量 ,起始点);

    位移量 表示移动的字节数,要求位移量是long类型数据,要求加后缀“L

    起始点 表示从何处开始计算位移量,规定的起始点有三种,文件首,当前位置和文件尾。

   文件首     SEEK_SET  0

   当前位置    SEEK_CUR  1

    文件末尾    SEEK_END  2

只输出第二个人的信息

 #include <stdio.h>
 struct  Student{
 char*name;
 int age;
 float score;
 };
 int main(int argc, const char * argv[]) {
 struct Student gril[3]={{"zsf",18,34.55f},{"lzl",23,88.88f},{"lzz",22,99.99f}};
 FILE *fp =fopen("student.data", "w+");
 if (fp!=NULL) {
 for (int i =0; i<3; i++) {
 fwrite(&gril[i], sizeof(struct Student), 1, fp);
 }
 printf("写入成功\n");
 
 rewind(fp);
 //         移动的字节数             起始点
 struct Student gril1;
 // 文件定位 从起始点开始移动(32个字节)
 fseek(fp, sizeof(struct Student), SEEK_SET);
 
 fread(&gril1, sizeof(struct Student),1, fp);
 printf("姓名 %s 年龄%d 成绩%.2f\n",gril1.name,gril1.age,gril1.score);
 }
 
 return 0;
 }

 10.文件结束检函数feof

     feoffp)也就是找文件结束的标志。

    读写出错函数 ferror (文件指针);

    能检查文件在输入输出时读写是否出错 如果ferror返回的时0就表示没有出错,否则表示文件有错。

    文件出错标志和文件结束标志函数

    clearerr(文件指针) 用于清除错误标志和文件结束标志,使他们为0




 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值