当前位置: 首页 > article >正文

c语言进阶(简单的函数 数组 指针 预处理 文件 结构体)

c语言补充

格式

void函数头 {} 中的是函数体

sum函数名

() 参数表

#include <stdio.h>

void sum(int begin, int end) {
	int i;
	int sum = 0;
	for (i = begin ; i <= end ; i++) {
		sum += i;
	}
	printf("%d到%d的和是%d\n", begin, end, sum);
}

int main() {
	sum(1, 10);
	sum(20, 30);
	return 0;
}

调用函数时 需要函数名和参数表 如上表中 用sum(x,x)来调用函数

+++

返回值还是不返回值

ps 上方使用void的句子表示无返回值,若想有返回值 如下:

#include <stdio.h>

int max(int a, int b) {  //实际的函数头  //声明
	int ret;
	if (a > b) {
		ret = a;

	} else {
		ret = b;
	}
	return ret;
}

int main() {            //定义
	int a, b, c;
	scanf("%d %d", &a, &b);
	c = max(a, b);
	c =  max(c, 23);

	printf("%d\n", max(a, b));

其中将输入的a,b的值调用给函数并比较大小 ,通过return ret将大的值返回,将大的值赋值给c,再和23比较,最终输出大的值

+++

将函数定义的式子摆在后面的方法(函数的原型声明)

也就是直接将函数的头放在前面就可以了:

void sum(int begin,int end);

注意要将分号加上!!!

(begin end 可以省略掉)

+++

参数的传递 和 本地变量

定义函数里面叫做形参 声明里面的是 实参 他们里面的值没有任何联系,就算相同的 字母也没联系

形参和实参他们两个部分都有自己的变量空间 变量空间互不干扰 离开本地的块他的作用域就没有了 限制块的方式是夹在**{}**中

+++

总结输入输出函数

输入函数:

gets  \\得到一连串的字符 直到遇到\n结束
getchar  \\一个一个的读取 遇到EOF结束
fgets     \\读取一连串字符  遇到\n结束

输出函数:

puts  \\输出内容到屏幕 并且自动在末尾添加换行符
putchar  \\将一个字符标准输出

取地址符&

作用:

取得变量的地址,引文地址会存放在内存中

#include <stdio.h>

int main(void) {
	int i = 0;
	printf("%p\n", &i);
	return 0;
}

%p是直接以地址符的形式输出

堆栈

例如字母i,p分配在堆栈中,在dev c++中通过取地址符知道了他们所处的地址 i是xxx6c,p是xxx68,i与p紧挨,且i在p的上方,因此堆栈是从上往下的

+++

指针

保存地址的变量

int* p= &i ; 相当于是有一个专门存放地址的箱子, 就是p (*p不可以被赋值)

​ 现在p里面就存放了i的地址了

格式

int* p= &i; 
还有一种写法
int *p;
int* p,q;
(其中q只是普通的一个int,不是地址)

实操:

#include <stdio.h>

void f(int *p) {
}


int main(void) {
	int a;
	int i = a;
	f(&i);
	printf("%p", &i);
	return 0;
}

结果
    000000000065FE4C

*p可以直接表示其地址符所代表的真实的数 ps

#include <stdio.h>

void f(int *p) {
	printf("%p\n", p);
	printf("%d\n", *p);
}


int main(void) {
	int i = 10;
	printf("%p\n", &i);
	f(&i);
	return 0;
}

**printf(“%d\n”, *p);**它可以直接输出p的地址符所代表的数字也就是10

指针的使用

1.交换变量

#include <stdio.h>

void swap(int *pa, int *pb) {
	int t = *pa;
	*pa = *pb;
	*pb =  t;
}

int main() {
	int a = 5;
	int b = 6;
	swap(&a, &b);
	printf("a = %d\n b = %d ", a, b);
	return 0;
}
结果
a = 6
 b = 5

2.比较大小

#include <stdio.h>

void minmax(int a[], int length, int *max, int *min);

int main(void) {
	int a[] = {1, 2, 3, 4, 5, 6, 7, 20, 9, 10, 78, 49, 98, 100};
	int min, max;
	minmax(a, sizeof(a) / sizeof(a[0]), &min, &max);
	printf("%d\n %d\n", min, max);
	return 0;
}

void minmax(int a[], int length, int *max, int *min) {
	int i;
	*min = *max = a[0];
	for (i = 1; i < length; i++) {
		if ( a[i] > *max) {
			*max = a[i];
		}
		if (a[i] < *min) {
			*min = a[i];
		}
	}
	printf("%d\n %d\n", *min, *max);
}

结果
   1
    100
   1
    100

3.异常的机制 9.1.3

指针与数组的关系

  1. 函数参数表中的数组其实就是指针

  2. 数组变量是const的指针 也就是一个常量指针int b[]----->int *const b

  3. 保护数组值

  4. 因为数组传入函数时是传递的地址。所以函数内部可以修改数组的值

    为了保护数组不被破坏

    可以 : int sum(const int a[],int length)

    +++

    老师讲的

    int *p;
    int a[10];
    p = a
    //way1   表示列
    int (*p)[10];
    int a[3][10];
    p = a;
    //way2  表示行
    int (*p)()  //指针变量p的声明
    p = maxl
    //strcmp比大小函数 判断name[i]是否小于name[k]
    if (strcmp(name[j], name[k]) < 0)
    //将c的内容赋值到b中
    strcpy(b,c)
    

    值的交换

    void swap(int *a,int *s){
    int *t;
    t= r;
    r = s;
    s = t;
    }
    main(){
    p = &a;
    q = &b;
    sewp(p,q);
    printf("%d "%d",*p,*q);
    //无法交换
    
    
    }
    

预处理

定义在文件编译前对源文件进行简单的处理。因为c语言源文件需经过编译和链接才能生成可执行问就按,编译将源文件转化为目标文件,如vs->.obj gcc->.o 编译针对单个源文件,链接是将编译后的多个目标文件以及系统中的库,组等合并成一个可执行文件

对象:处理以#开头的命令

功能:1. 文件包含:#include

        2. 宏定义#define
           3. 条件编译 #if   #elif  #endif  

作用:合理地使用它们会使编写的程序便于阅读、修改、移植和调试,也有利于模块化程序设计。

+++

include

定义:叫做文件包含命令,用于将头文件的内容插入到引用该命令的位置。

用法:include <stdheader.h> include “myheader.h”

区别:头文件的搜索路径不同 。尖括号是在系统路径下寻找头文件,双引号是在当前目录下查找,再在系统路径下查找。

可以同时用尖括号和双引号的函数是stdio.hstdlib.h 但是自己编写的头文件只可以用双引号 如: include “my.h”

  • printf():格式化输出到标准输出(通常是屏幕)。
  • scanf():从标准输入(通常是键盘)读取格式化输入。
  • fprintf():格式化输出到文件。
  • fscanf():从文件读取格式化输入。
  • fgets():从文件或标准输入读取一行。
  • fputs():向文件或标准输出写入一行。
  • fopen()fclose()fread()fwrite()fseek()ftell() 等文件操作函数。
  • malloc()calloc()realloc()free():动态内存分配和释放。
  • exit():终止程序执行。
  • system():执行外部命令。
  • atoi()atol()strtod()strtol()strtoul():字符串到数值的转换。
  • rand()srand():随机数生成。
  • qsort()bsearch():排序和二分查找。
  • getenv():获取环境变量的值。
  • abs()div()labs()ldiv()llabs()lldiv():整数运算和除法。

注意:一个include 只能包含一个头文件 ,一个同文件也可以多次被引用,因为include中有防重复机制。。。且包含中文件可以包含其他文件

宏定义

定义 :#define组成,他用一个标识符表示一个字符串。

形式:#define 宏名 字符串 例: #define n 100 则后面的100都可以写成n 例:#define M (nn+3n)

注意:1. 字符串可以是数字、表达式、if 语句、函数等,它和c语言中的字符串并不等同

  1. 宏定义不是说明或者语句,不必在行末加分号 如果加了分号定义的时也在定义中加了分号;

  2. 宏定义必须写在函数之外,从开始定义到源程序结束起作用如果要终止,就是用**#undef 宏名**

  3. 如果宏名被引号包围,则宏定义不起作用

    #include <stdio.h>
    #define OK 100
    int main () {
        printf("OK\n");
        return 0;
    }
    
     //printf 直接输出ok,不输出100
    
  4. 宏定义允许嵌套

    #define PI 3.14
    #define S PI*y*y
    
  5. 宏名一般习惯用大写字母 与变量区分

  6. 宏定义可以表示数据类型

    #include <stdio.h>
    #define PINT1 int *
    typedef int *PINT2;
    int main () {
        PINT1 a, b;
        PINT2 c, d;
        /* Code */
        return 0;
    }
    
    
    //所以其实就是int *a,b   代表a是指针,b是整数
    //但是typedef 是关键字 代表c,d全是指针
    

**参数:**形参和实参(与函数类似)

#define 宏名(形参列表) 字符串

#define M(y) y*y+3*y
......
k=M(5)
//这里的5替代了y
也就是 k=5*5+3*5

​ 或者

#define MAX(a,b) (a>b) ? a:b
......
scanf("%d %d",&a,&b);
max=MAX(x,y)
//也就是max=(x>y) ? x:y

这里的x,y就是实际参数,ab就是形式参数

ps宏名和形参列表不能有空格否则系统会默认将形参列表和字符串绑在一起 这样形参列表就没用了

注意1. 形参不必指明数据类型,但是在实参前需要声明实参的数据类型,因为在主函数中这只是简单的数值替换

  1. 字符串外最好加上括号,因为宏定义只是简单的字符的替换,可能因为优先级的问题导致出错

    #define SQ(y) (y)*(y)
    //但有时这样都会出错 所以还需要整体加一个括号
    #define SQ(y) ((y)*(y))
    
  2. 与函数的区别:宏展开仅仅是字符串的替换。不会对表达式进行计算,宏在编译之前就被处理掉了,他没有机会参与编译,也不会占用内存。但是这一切函数都可以

    #include <stdio.h>
    #define SQ(y) ((y)*(y))
    int main () {
        int i = 1;
        while (i <= 5) {
            printf("%d^2=%d\n",i,SQ(i++));
        }
        return 0;
    }
    
    //这里while语句仅仅执行2次,因为 printf(.....,i,(i++)*(i++))    所以先是1*2 再 3*4 再之后因为没有6可能就停止了
    
    1. 带参数的宏也可以定义多个语句

      #include <stdio.h>
      #define SSSV(s1, s2, s3, v) s1=l*w; s2=l*h; s3=w*h; v=l*w*h;
      int main () {
          int l = 3, w = 4, h = 5, sa, sb, sc, vv;
          SSSV(sa, sb, sc, vv);  
          printf("sa=%d, sb=%d, sc=%d, vv=%d\n", sa, sb, sc, vv);
          return 0;
      }
      
      //结果为sa = 12, sb = 15, sc = 20, vv = 60
      

      +++

结构体

  1. **定义:**一种聚合类型,可以将不同类型的用来描述同一件事物的变量放到结构体中

    结构:struct 结构体名{

    结构体包含的变量后数组

    }

    struct stu {
        char *name; //姓名
        int num; //学号
        int age; //年龄
        char group; //小组
        float score; //成绩
    };   //可以多个类型的数据
    
    也可以是复杂结构体
        struct stu stu1,stu2;
    

    复杂结构体

    struct {    
        char *name; //姓名
        int num; //学号
        int age; //年龄
        char group; //小组
        float score; //成绩
    } stu1, stu2;
    这样stu1和stu2就都包含这5个信息了
    

    占用:stu1和2在占用内存时靠近

    使用

    1. 获取结构体中变量的名字 或者给变量赋值 借用上述材料

      stu.name="tom";
      stu.age=12;
      //也可以一起 这和数组类似
      #include <stdio.h>
      int main () {
          struct {
              char *name; //姓名
              int num; //学号
              int age; //年龄
              char group; //所在小组
              float score; //成绩
          } stu1, stu2 = {"Tom", 12, 18, 'A', 126};
      
      #include <stdio.h>
      int main () {
          struct {
              char *name; //姓名
              int num; //学号
              int age; //年龄
              char group; //所在小组
              float score; //成绩
          } stu1, stu2 = {"Tom", 12, 18, 'A', 126};
      

      注意:结构体本身不占用内存空间,它里面的变量才占用

      +++

结构体数组与结构体指针

结构体数组

  1. 定义结构体数组和和结构体变量形式相似
struct stu{
       char *name;
       int num;
       int age;
       char group;
}class[4] = {
    {"ji",5,17,1},
    {"zhu",5,19,2},
    {"ren",6,18,1},
    {"ma",5,20,1}
};
//形式就是这样

当然也可以[]中什么也不填写,但需要对数组中的元素全部赋值才可以。

  1. 获取结构体数组中的信息

    class[3].age就是获取ma的年龄

结构体指针

  1. 定义

    struct stu{
      char *name;
      int num;
      int age;
    }stu1 = {"Tom",4,19};
    /*结构体指针*/
    struct stu *pstu = &stu1;
    //这句话可以借助pstu间接得到stu1中的信息
    

    但是stu1前一定要加**&**取地址符

  2. 通过通过结构体指针访问结构体成员

    //1
    pointer->memberage;   
    //2
    (*pointer).membergae;
    

实战

struct stu{
  char *name;
  int num;
  int age;
}stu1 = {"Tom",4,19},*pstu=&stu1;
/* 输出成员名字 学号 年龄*/
printf("%s %d %d",pstu->name,pstu->num,pstu->age);


  1. 通过指针给结构体成员添加数据

    	pstu->age = 30;
    

为数据类型重命名

typedef 好处 利于编码

**用法:**typedef old name new name;

//用法1:
 typedef struct stu STU;
//用法2
typedef struct stu {
   成员列表
}STU;
STU body1.b

这样用这个stu定义一个结构体变量可以: STU stu1;

范围:int char float,数组 指针 结构体

typedef int INTM;
IMTA a,b,c;
//相当于宣告a,b,c是int类型
typedef char ARRAT20[20];
ARRAY a1,a2;
//相当于char a1[20],a2[20];

为指针类型定义别名:

typedef int (*PTR_TO_ARR)[400];
PTR_TO_ARR p1,p2;
//PTR_TO_ARR是一个类型int *[4](含4个int类型的数据)的别名

为函数指针类型定义别名:

typedef int (*PTR_TO_FUNC)(int, int);
PRT_TO_FUNC pfunc;
......
printf("max: %d\n", (*pfunc)(10, 20));

+++

结构体链表

定义:他是一种数据类型,可以动态的进行存储分配 可以避免浪费空间

组成:一条链表有链首有表尾,也就是他自己的开头和结尾,链首保存了一个地址,专门用于链表的开始地址。我们可以访问到链表中的第1,2,3…个元素,他们都分别被放在不同的结点中,每个节点点分为i两个部分,一部分储存实际数据,叫做数据域,一部分用于保存访问下一个结点的地址,叫做地址域.

应用:

typedef struct_node{   //node常被用做自定义标识符,typedef是为已有的数据类型定义新的别名
        int value;
        struct _node *next; //这是将链表中的每一个结点链接起来+
}NODE;/*意思就是说node是一个代表这一整个结构体的名称,便于后续对结构体的直接使用和操作*/
#endif
 #include <stdlib.h>
 #include "node.h"
 #include <stdio.h>
int main(int argc,char const *argv[])
{
    Node * head = NULL;  //因为是链表的头部分 所以什么都没有
    int number;
    do{
        scanf("%d",&number);
        if (number!=-1){
            //add to linked-list
            Node *p = (Node*)malloc(sizeof)(Node));
            //malloc函数可以给分配指定的存储空间
            p->value = number;
            p->next = NULL;
            //find the last
            Node *last = head;
            if (last ){
            while (last->next){
                last = last->next;
                }
            //attach
            last->next = p;
            } else{
                head =p;
             }
        }
    }while(number != -1);
    return 0;
}
//静态链表
#include <stdio.h>

struct stu {
	int num;
	float score;
	struct stu *next;
};

int main() {
	struct stu a, b, c;
	struct stu *p;
	p = &a;

	a.next = &b;
	b.next = &c;
	c.next = NULL;
	a.num = 100;
	a.score = 98;
	b.num = 101;
	b.score = 69;
	c.num = 102;
	c.score = 100;
	while (p != NULL) {
		printf("%d %f", p->num, p->score);
		p = p->next;
	}



	return 0;
}

//老师讲的 静态链表

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

共用体

格式:union 共用体名字{

成员列表

}

与结构体的区别

共用体中的所有成员占用同一段内存,且占用的最大内存由其中的最大的成员占用的内存决定,结构体占用分别不同的内存。。同一内存段中可以存放不同类型的成员.

使用情景1

union data{
      int n;
      char ch;
      double f;  //占用的字节最多 所以a,b,c也都占用8个内存
}a,b,c   //后者在下一行写  
    data a,b,c;

使用情景2:

同时统计老师和学生的信息,但两者有的信息如年龄,班级的数据类型是相同,但是

应用(单片机中应用较多)


外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

枚举类型的定义和使用

结构

enum typeNAME {valueName1,valueName2,....};

好处:比如一周七天,要通过switch使输入英文后出现对应的星期,可以使用宏定义一个个定义,如#define MON 1…凡是很麻烦 所以

enum week {MON=1,Tue,Wed,Thu,Fri};
//因为{}中的赋值是从0开始的,但MON=1,所以要先直接定义MON=1,之后就是2,3....Le 
case 1: puts("Monday"); break;
        case 2: puts("Tuesday"); break;
        case 3: puts("Wednesday"); break;
//他们会直接被替换为1,2,3....

注意

  1. MON,Tue,Wed等全是常量(不是变量) 不能对他们赋值 可以让他们对别人赋值
  2. Mon.Tue等的作用范围在main函数内部,不可以再定义和其相同的名字

3.枚举可以当成编译阶段的值,它只有替换的作用.

+++

位域

用处:用来指定变量所占有的字节

struct bs {
      unsigned m;
      unsigned int n: 4;         也就是n的最多是4个字节也就是32位的Bit
      unsigned char ch:6;
      };

注意:位域的宽度不能超过它所依附的数据类型的长度

适用范围:正常只有int . unsigned int, bool.,扩展中加了char, signed,unsigned char,enum

+++

位运算

种类 (对象:只可以是整形或者字符型)

  1. & 按位与 1&1 = 1 1&0 = 0 两个都为1结果才为1 否则为0

它 可以对参与的两个数的二进制进行一位一位的比较 如9&5

  1. **| **按位或 两个中只要有一个为1就为1 否则为0……

  2. **^**按位异或 两个不同结果为1 相同结果为0

  3. **~**取反运算 ~1=0 ~0=1

  4. **<< **左移运算 将操作数的各个二进制位左移若干位,高位丢弃,低位补0

如 5<<2是将整数5的二进制位左移两位

6.**>>**右移运算 将操作符的各个二进制位全部右移若干位,高位补0,低位补1

文件

组成:文件由数据流形式组成,可按数据的存放形式分为二进制文件和文本文件。

分布:不同的硬件设备也被看作一个文件,对这些文件操作,等同于对磁盘上普通文件的操作,如把显示器叫做输出文件,键盘叫做输入文件

读取:文件可以一个字符一个的读取,也可以读取一整行 或者若干个字节,也可以从头读取,从中间读取。

访问文件:三步:打开 读取 关闭

打开读取和关闭文件

打开函数

fopen()函数
  /* 原型 */
FILE *fopen (char *filename,char *mode);
//fileneme 包括文件名 文件路径
//mode是打开方式 

作用:获取文件信息 文件名 文件状态等之后保存到FILE类型的结构体中,然后将该变量的地址返回

判断文件打开成功还是失败

if ((fp=fopen("D:/demo.txt","rt"))== NULL){
    puts("fail to open");
    exit(0)
}

接受fopen的返回值 需要定义一个FILE类型的指针

FILE *fp = fopen("demo.txt","r");
/*意思是以只读的形式打开demo.txt 文件 并将fp指向该文件 这样就可以通过fp操作demo.txt了*/
//way 2
FILE *fp = fopen("D:\\demo.txt","rb+")
 /*以二进制方式打开d盘下的deom,txt 文件允许读写

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

上述图片是控制读写权限的打开方式

注意:以r,w,w++形式读取文件若文件中已经有内容,则会清空之前的内容,以a形式打开若文件已经存在会保存在文件的末尾

还有控制读写类型的打开方式t b t是以txt形式打开 b是二进制形式打开 如果不写,就默认t形式打开

读写类型只能放在读写权限的中间或者尾部

“rb”,“wt”,“ab”,“r+b”,“w+t”,“a+t”

关闭文件(一定要关闭的 防止文件中内容等出错)

fclose(fp)
/*原型 */
int fclose(FILE *fp);

+++

以字符形式读写文件

读取函数

fgetc()
/* 读取一个字符,读取成功就成功,读取失败返回eof(end of file) */
char ch;
FILE *fp = fopen("D:/demo,txt","r+")
ch = fgetc(fp);
/*表是从demo.txt中读取一个字符,且fgetc用一次后,文件内部的位置指针就会从第一个开始移动一次 因此可以多此使用fgetc函数读取多个字符*/ while ((ch=fgetc(fp)) != EOF) {
        putchar(ch);//这就是一个个读取字符

ps: eof在读取出错或者结束时都会有,要判断是哪一种 需要stdio.h中的两个函数**feof() **(判断文件内部指针是否指向文件末尾 )ferror(判断文件操作是否出错误)

if (ferror(fp)) puts("读取出错");

写入函数

fputc()函数
FILE *fp = fopen("D:/demo,txt","r+");
char ch = 'a';
fputc(ch,fp);
/*意思是将a写入所指的fp中*/
while ((ch=getchar()) != '\n'){
      fputs(ch,fp);
}
/*就是循环将写下的字符存入指定文件中,直到按下回车键才结束

+++

fprintf()函数

用于将指定的格式化的数据输出到指定的文件流中

fprintf(fp,"%d %d\n",30,40);

+++

perror函数

专门打印一条错误信息

perror("error opening file");

atoi函数

将字符串转化为整数

a1 = atoi(str1);
/*这里是将str1中的内容转化为整数并且存储在a1中

feof函数

检测文件指针是否到达了文件末尾 若返回值是0,则没有到到达;若返回值为1,则到达

feof(f)

exit(0)函 数和return 1函数的区别

  • eixt函数会直接强制退出程序,在代码任何位置都可以使用,但是return 1 只可以在main函数使用,并且退出后会返回给操作系统
  • exit函数操作后会清理全局内存,return 1会清理局部变量

+++

以字符串形式读写文件

读字符串的函数

fgets()
/* 读取成功返回字符串首地址 失败返回null*/
/* 凡是fgets读取到的字符串都会在末尾自动添加一个\0 所以如果是在数组中读取,想要写入100个字符,就先要定义101大小的数组*/
/* 这个函数读取时遇到换行或者到文件末尾就会结束*/
# define N 101
char str[N];
FILE *fp = fopen("demo.txt","r"); 
fgets(str,N,fp)    //字符类型 多少个  从哪里读取文件
/*表示从demo中读取100个字符 并保存到字符数组str中

写入函数

fputs()
/*写入成功返回非负数,失败返回nof */
fputs(str,fp)
/*将字符串str写入到fp路径下的文件*/

+++

以数据块形式读写文件

数据块:若干个字节的数据 一个字符 字符串 或者多行数字

读写数据块的函数

fread(void *ptr,size_t size,size_t count,FILE *fp);
/*从指定文件中读取数据块*/
fwrite(a,size,N,fp);
/* a是你要求写入的数据所在的内存区域的首地址,size是每个数据快的字节大小,count是要写入的元素个数,fp是指向了目标文件的地址 */

先写入后读时要先调整位置指针

fewind(fp) 
/*将位置指针重新定位到文件开头*/
#define N 5;
for(i=1;i<5;i++){     scanf("%d",&a[i])           };
fwrite(a,size,N,fp);
fewind(fp);
fread(b,size,N,fp);

+++

格式化读写文件

fscanf()
/*从磁盘文件中格式化写入/读取 数据*/
/* 原型*/
int scanf(FILE *fp||stdin,char *format,...) //stdin代表从键盘读取数据,加上他就跟scanf一样了
fprintf()
/*从磁盘文件中格式化写读数据*/
fprint(stdout,"%s %d % d %s",pa->name, &pa->num, &pa->age, &pa->score);
//stdout向显示器输出数据

实际操作fscanf

for (i = 0; i < N; i++, pa++) {
        fscanf(stdin, "%s %d %d %f", pa->name, &pa->num, &pa->age, &pa->score);
    }

+++

文件定位函数

(之前的读写方式都是从文件开头一点一点读,但实际开发需要从中间打开,因此需要移动文件内部的位置指针)

定位文件的指针

ftell();
/*原型*/
long int ftell (FILE *p);
/*成功则返回位置标识符的当前值,错误返回-1l*/

移动指针(2 way)

rewind()
//用来将位置指针移动到文件的开头
fseek()
//用来将位置指针移动到任意位置
/*原型*/
int fseek (FILE *fp,long offset,int origin);
//offset是要移动的字节数,+时向后移动,-时向前移动
/* oigin是起始位置 起始位置有三种
文件开头 SEEK_SRT 它的值是0
当前位置 SEEK_CUR 它的值是1
文件末尾 SEEK_END 它的值是2

例子

fseek(fp,100,0);
/*表示将位置指针移动到离文件开头有100个字节处

注意:fseek函数用于二进制文件,所以使用此函数需将文本文件转化为二进制文件

malloc函数

ps1 = (char *)malloc(10 * sizeof(char));
/* 10 * sizeof(char)就是我要的存储空间的大小*/

这里给ps1分配了一块动态的存储字符串的空间

之后还要释放内存

free(ps1)

+++

三元便利数组

(可以把一堆数字中按照三个一组全部便利一遍)

for(i=0;i<N-2;i++){
   for(j=i+1;j<N-1;j++){
       for(k=j+1;k<N;k++){
       }
    } 
}

+++

memset函数

(将一个数组或内存中的数全部变为0,这也叫做初始化)

场景:例如要让你走在一个棋盘之中,你走过的路径都要标记为1,没有走过的都是0,那么你一开始就要memset();

memset(要设置的区域的起始地址,要设置的value,sezeof(数组))
                                         //要设置的字节数

+++

dfs函数

(深度遍历要走的路径,直到找到满意的路径,使用递归和回溯)

场景:例如要让你走在一个棋盘当中,你要走每一个格子,并且要找到出去的最优解(格子中有丈量你走的价值的东西),这时候就要用到dfs


拼接函数

`模仿strcat

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    int i;
    char x[100000] = ""; // 用于存储拼接结果的字符数组

    // 注意:连接数字时需要先把数字转成字符串
    for (i = 1; i <= 2023; i++) {
        char temp[50]; // 临时存储数字的字符串
        sprintf(temp, "%d", i); // 将数字 i 转换为字符串
        strcat(x, temp); // 拼接到 x 后面

        // 如果需要将 i++ 放在不同的字符串中,可以这样做
        sprintf(temp, "%d", i + 1); // 将 i+1 转换为字符串
        strcat(x, temp); // 拼接到 x 后面
    }

    // 打印最终结果
    printf("%s\n", x); 

    return 0;
}
  /*sprintf函数用于将某种类型转化为字符类型,因为strcat函数是要拼接字符串类型的数据的sprintf(转化的东西所在的位置,转化前的类型,要转化的内容)

非常妙的用函数交换两个数的大小

void fun_c(int *x,int *y) {*x=*x+*y; *y=*x-*y; *x=*x-*y;}

+++

str开头的常用函数

  1. 复制
strcpy  //复制字符串
strcmp(x,y);//将y的内容直接顶替掉x的内容  
          //注意!!!会一直复制b中的内容知道遇到\0才结束
  1. 复制指定字符

    strncpy
    strncpy(x,y,size);  //将y的内容的n的字符顶替掉x的内容
    
  2. 比较两个字符

strcmp
strcmp(x,y);   //x<y 则返回负值
               //x=y则返回0
               //x>y则返回正值
  1. 连接两个字符
strcat
strcat(x,y);     //将y的内容追加到x的后面
  1. 查找字符第一次出现
strchr
strchr(str,int c);   //str是所在字符数组的名称,c是要找的字符
char *p = strchr(str,'1');
printf("你找到的1在str中的位置是:%d",p-str);

//这里是要看str数组中是否有1这个数子
//然后输出1在str中的第几个位置

拼接函数

`模仿strcat

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    int i;
    char x[100000] = ""; // 用于存储拼接结果的字符数组

    // 注意:连接数字时需要先把数字转成字符串
    for (i = 1; i <= 2023; i++) {
        char temp[50]; // 临时存储数字的字符串
        sprintf(temp, "%d", i); // 将数字 i 转换为字符串
        strcat(x, temp); // 拼接到 x 后面

        // 如果需要将 i++ 放在不同的字符串中,可以这样做
        sprintf(temp, "%d", i + 1); // 将 i+1 转换为字符串
        strcat(x, temp); // 拼接到 x 后面
    }

    // 打印最终结果
    printf("%s\n", x); 

    return 0;
}
  /*sprintf函数用于将某种类型转化为字符类型,因为strcat函数是要拼接字符串类型的数据的sprintf(转化的东西所在的位置,转化前的类型,要转化的内容)

非常妙的用函数交换两个数的大小

void fun_c(int *x,int *y) {*x=*x+*y; *y=*x-*y; *x=*x-*y;}

+++

str开头的常用函数

  1. 复制
strcpy  //复制字符串
strcmp(x,y);//将y的内容直接顶替掉x的内容  
          //注意!!!会一直复制b中的内容知道遇到\0才结束
  1. 复制指定字符

    strncpy
    strncpy(x,y,size);  //将y的内容的n的字符顶替掉x的内容
    
  2. 比较两个字符

strcmp
strcmp(x,y);   //x<y 则返回负值
               //x=y则返回0
               //x>y则返回正值
  1. 连接两个字符
strcat
strcat(x,y);     //将y的内容追加到x的后面
  1. 查找字符第一次出现
strchr
strchr(str,int c);   //str是所在字符数组的名称,c是要找的字符
char *p = strchr(str,'1');
printf("你找到的1在str中的位置是:%d",p-str);

//这里是要看str数组中是否有1这个数子
//然后输出1在str中的第几个位置

http://www.kler.cn/a/529166.html

相关文章:

  • C++并发编程指南08
  • Linux-CentOS的yum源
  • 网络原理(3)—— 传输层详解
  • 仿真设计|基于51单片机的温湿度、一氧化碳、甲醛检测报警系统
  • 《解锁AI黑科技:数据分类聚类与可视化》
  • 【2025年更新】1000个大数据/人工智能毕设选题推荐
  • 安全防护前置
  • Kafka中文文档
  • Theorem
  • LeetCode LCR180文件组合
  • 进阶数据结构——双向循环链表
  • 8.攻防世界Web_php_wrong_nginx_config
  • pandas中的str使用方法
  • 【回溯+剪枝】电话号码的字母组合 括号生成
  • 五.简单函数
  • 【学习笔记】深度学习网络-正则化方法
  • 【NLP251】Transformer中的Attention机制
  • 【Proteus】NE555纯硬件实现LED呼吸灯效果,附源文件,效果展示
  • 设计心得——平衡和冗余
  • C语言:输入正整数链表并选择删除任意结点
  • ComfyUI安装调用DeepSeek——DeepSeek多模态之图形模型安装问题解决(ComfyUI-Janus-Pro)
  • 一文学会HTML编程之视频+图文详解详析
  • Selenium 使用指南:从入门到精通
  • 17.2 图形绘制8
  • ASP.NET Core与配置系统的集成
  • redex快速体验