1.指针
2.动态分配内存
3.结构体
4.文件读写
5.项目分析:计算器
6.项目分析: 字符串查找
1.指针
指针是c语言中专门用于存放存放内存地址的变量
指针的定义
数据类型 * 变量名,例如:int *a,定义了一个指向整型变量的指针;char *b,定义了一个指向字符型变量的指针
指针的初始化
int a = 10;
int *p = &a;//定义了一个指针变量p,它指向了a所对应的内存地址
char b = 'c';
char *pp;
pp = &b;//定义了一个指针变量pp,它指向了b所对应的内存地址
char *p = NULL;//定义了一个指向为空的指针
//以上是三种常用初始方法,定义完指针后一定要初始化,否则是很“危险”的
与指针相关的定义
int *array[10];/*定义了一个指针数组,可以这样理解:
中括号是数组的标识符,所以它定义了一个整型数组,
数组名字叫array,而array前有指针标识符*,
所以是个指针数组*/
int (*array)[10];/*定义了一个指针数组,可以这样理解:
小括号的优先级更高,所以它定义了一个整型指针,
指针名叫array,而后有有个数组,所以(*array)整体是数组的名字
数组指针是指针,指针数组是数组。
void *getchar(char);//指针函数
void (*getchar)(char);//函数指针
//在定义函数时,小括号是函数的标识符,指针函数与函数指针的理解与上相同
函数指针是指针,指针函数是函数
int **p;/*定义了一个指向指针的指针变量,这个指针变量的名字是p,
p所指向的仍然是指针,这个指针存放的是整型数据,这样用**定义的
指针称为二级指针,出了二级指针还可以定义多级指针*/
指针运算
image.png
运行结果如下:
image.png
说明,指针变量是可以运算的。在本机中,定义一个指向整型变量的指针,增一运算后,指针地址偏移4个字节,定义一个指向字符型变量的指针,增一运算后,指针地址偏移1个字节;偏移量与定义一个整型变量或字符型变量时,分配的内存大小是相同的。
2.动态分配内存
定义指针变量后要为所指向的地址分配内存,在我们不确定分配多少内存的时候,会担心分配过多,造成内存的浪费,分配过少又会不够用,这时我们需要动态分配内存,用代码让计算机动态分配内存,用多少分多少。要实现动态分配内存我们需要用到及格函数:malloc,free,realloc,他们被定义在<stdlib.h>这个头文件中。
char *name;
name = (char*)malloc( 10*sizeof(char));/*使用malloc申请了10个字节的的内存空间。
(*char)用于说明变量的类型,(10*sizeof(char))用sizeof(char)计算本机一个字符型
数据所占内存大小,计算完后乘以10,表示分配了相当于10个char类型变量的内存大小。*/
name = (char*)realloc(name,20*sizeof(char));//使用realloc为name,重新分配内存。
free(name);//释放内存
结构体
结构体可以定义c语言中不存在的数据类型。
结构体的定义
struct student{//用struct 定义一个student数据类型
int age;
int sex;
char name[10];
}
struct student LiMing;//声明一个student型的数据变量
struct student *p = &LiMing;//定义一个指针变量,指向LiMing所对应的地址
定义完的数据类型可以像一般数据类型一样使用,和int,char等类型定义
4.文件读写操作
FILE *fopen("文件路径/文件名","模式");
FILE *fp = fopen("文件路径/文件名","模式")
image.png
fputc(int c,FILE *fp);//向文件写入单个字符
fputs(char *s,int size,FILE *fp);//向文件写入整个字符串
fclose(fp);//关闭文件
正确的文件读写方法是将文件写入后关闭文件,否则写入的内容会留着缓冲区,不会保存到文件中。
5.头文件与实现文件
A.新建一个空项目将它命名为计算器
B.在新项目下创建几个文件
C.分别命名为mian.c;Calculator.c,Calculator.h
D.在每个文件中写入以下代码:
//Calculator.h
#include <stdio.h>
int add(int,int);
int minus(int,int);
int multiply(int,int);
int devide(int,int);
//Calculator.c
#include <stdio.h>
#include "Calculator.h"
int add(int a,int b){
return a+b;
}
int minus(int a,int b){
return a-b;
}
int multiply(int a,int b){
return a*b;
}
int devide(int a,int b){
if (b != 0){
return a / b;
}else{
return 0;
}
//main.c
#include <stdio.h>
#include "Calculator.h"
int main(){
printf("%d\n",add(1,2));
printf("%d\n",minus(5,3));
printf("%d\n", multiply(9,7));
printf("%d\n",devide(4,2));
return 0;
}
项目中main()函数为入口,到计算函数时,计算从头文件中查声明,到对应.c文件中查找函数主体,通过函数主体运算将运算结果返回给main函数
6.项目分析: 字符串查找
使用同样的方法创建一个查找字符串的项目
//myString.c
#include <stdio.h>
#include "myString.h"
void myScanf(char *p){
int i = 0;
while (1) {
char c = getchar();
if (c == '\n') {
p[i] = '\0';
break;
}
p[i] = c;
i++;
}
}
void input(char *p, char *des){
//提示用户操作
printf("%s:", des);
//输入语句
myScanf(p);
}
//计算字符串的长度
int length(char *p){
int i = 0;
//for (; p[i] != '\0'; i++);
while (1) {
if (p[i] == '\0') {
break;
}
i++;
}
return i;
}
int find(char *sentence, char *word){
//1.获取两个字符串的长度
int sLength = length(sentence);
int wLength = length(word);
//2.判断查询的字符串长度是否比句子短
if (sLength < wLength) {
return 0;
}
int start = 0;
int count = 0;
for (int i = 0; i < sLength; i++) {
//记录当前开始的位置
start = i;
//从当前位置开始去和查找的单词进行比较
int j = 0;
for(; j < wLength; j++){
//判断j对应的值和start+j比较
if (sentence[start+j] != word[j]) {
break;
}
}
//判断怎么出来的
if (j == wLength){
//都相同
//将i的值定位到start+j的位置
i = start + j-1;
count++;
}
}
return count;
}
//main.c
#include <stdio.h>
#include "myString.h"
int main(int argc, const char * argv[]) {
char sentence[100] = {};
char word[20] = {};
input(sentence, "请输入语句");
input(word, "请输入查找的单词");
int count = find(sentence, word);
printf("出现%d次\n", count);
return 0;
}
//myString.h
#include <stdio.h>
void myScanf(char *p);
void input(char *p, char *des);
int length(char *p);
int find(char *sentence, char *word);
实现结果如下:
image.png