学习c语言——进阶
指针的学习
1.使用指针交换数字
void swop(int *a, int *b) {
int t = *a;
printf("%p\n",&t);
printf("%p\n",&a);
printf("%p\n",a);
*a = *b;
*b = t;
}
/*
其中,前三行分别输出变量 t、指针变量 a 和指针变量 a 所指向的地址。
由于每次运行程序时内存的分配情况可能不同,所以这些地址可能与你的运行结果不完全相同。
(使用ai查找为什么不同)
*/
int main() {
int a = 5;
int b = 6;
swop(&a, &b);
printf("%d %d\n", a, b);
return 0;
}
2.使用指针的场景:返回值并改变值
#include<stdio.h>
/*
@return 如果除法成功,返回1;否则返回0
*/
int divide(int a,int b,int *result);
int main(void)
{
int a = 5;
int b = 2;
int c;
if(divide(a,b,&c)){
printf("%d/d=%d\n"a,b,c);
}
/*我认为这里好,直接判断函数的返回值*/
return 0;
}
int divide(int a,int b,int *result)
{
int ret = 1;
if(b==0) ret = 0;
else{
*result = a/b;
}
return ret;
}
3.使用指针返回多个值
#include <stdio.h>
void minmax(int a[],int len,int *max,int *min);
int main(void)
{
int a[] = {1,2,3,4,56,7,8,9,5,6};
int min,max;
minmax(a,sizeof(a)/sizeof(a[0]),&min,&max);//传入地址进去
printf("min=%d,max=%d\n",min,max);
return 0;
}
void minmax(int a[],int len, int *min,int *max)
{
int i;
*min = *max=a[0];
for(i=1;i<len;i++)
{
if(a[i]<*min){*min = a[i];}
if(a[i]>*max){*max = a[i];}
}
}
4.使用指针注意事项:
1.指针p的类型必须与变量的类型一致
2.如果使用指针,必须先给指针变量赋值(变量的地址),倘若直接使用指针用于赋值情况,会指向一片不知道是什么的区域,很可能导致错误
3.如何输出结果:
#include <stdio.h>
int main ()
{
int var_runoob = 10;
int *p; // 定义指针变量
p = &var_runoob;
printf("var_runoob 变量的地址: %p\n", p);
return 0;
}
4.0地址通常是个不能随便碰的地址
●所以你的指针不应该具有0值
●因此可以用0地址来表示特殊的事情:
返回的指针是无效的
●指针没有被真正初始化(先初始化为0)
●NULL是一个预定定义的符号,表示0地址(建议使用NULL,有的编译器0和NULL表达的意思不同)
●有的编译器不愿意你用0来表示0地址
5.指针的类型转换
●void表示不知道指向什么东西的指针
●计算时与char相同(但不相通,加一的时候大小变化的值是1)
●指针也可以转换类型
●int、*p = &i; void、q = (void)p;
●这并没有改变p所指的变量的类型,而是让后人用不同的眼光通过p看它所指的变量
●我不再当你是int啦,我认为你就是个void!
5.数组变量是常量指针
int b[] --> int * const
6.数组变量本身表达地址
- int a[10] ; int *p=a; //无需用&取地址
- 但是数组的单元表达的是变量,需要用&取地址
- a ==&a[0]
7.[]运算符可以对数组做,也可以对指针做:
*a = 25;
const在*号的前面,表示它所指的东西不能被修改;
eg:const int* p1 = &i;int const* p2 = &i;
const在*号的后面,表示指针不能不能被修改
eg:int *const p3 = &i;
8.指针的运算
1.*p+1;看p是什么类型,如果是char,那么加一,如果是int,那么加二;其实就是加类型的大小
2.(星)p++表示:取出p所指的那个数据来,完事之后顺便把p移到下一个位置去.
3.p的优先级虽然高但是没有++高
4.常用于数组类的连续空间操作
5.在某些CPU上,这可以直接被翻译成一条汇编指令
#include <stdio.h>
int main(void)
{
char ac[] = {0,1,2,3,4,5,6,7,8,-1};
char *p = &ac[0];//取第几个如:*p = &ac[5]
int i;
for(i=0;i<sizeof(ac)/sizeof(ac[0]);i++){
printf("%d\n",ac[i]);
}/*两种不同的循环方法*/
while(*p != -1){
printf("%d\n",*p++);
}
}
9.内存的动态分配
#include <stdio.h>
#include <stdlib.h>//使用malloc函数的标准库
int main(void){
int number,i;
int *a;
printf("输入数量:");
scanf("%d",&number);
a = (int *)malloc(number*sizeof(int));//类型强制转换
for(i=0;i<number;i++){
scanf("%d",&a[i]);
}
for(i=number-1;i>=0;i--){
printf("%d ",a[i]);
}
free(a);//释放内存
return 0;
}
1.malloc类型是void:void*malloc(size_t size);
2.向malloc申请的空间的大小是以字节为单位的1Mb=1 * 1024* 1024
3.返回的结果是void*,需要类型转换为自己需要的类型
4.(int *)malloc(n * sizeof(int))
5.使用不同的类型数据就使用不同的int,double,short,char
没有空间了?
1.如果申请失败则返回0,或则就做NIULL
2.换地址free(),只能还申请来的空间的首地址
3.使用指针的良好习惯是void *p=0;
字符串操作
1.单字符输入输出
#include <stdio.h>
int main(){
int ch;
while((ch = getchar()) != EOF){
putchar(ch);//循环读入
}
printf("EOF\n");
return 0;
}
实现的功能:不断读取用户输入,输入ctrl+z可以使程序跳出循环,输入ctrl+c会使程序终止
2.字符串数组
数组传参的时候的,传的只是数组首字母的大小
//二维数组的输出
#include <stdio.h>
int main(void) {
const int *a[] = {
(const int[]){1, 2, 3, 4, -1}, // 在数组末尾添加-1作为结束标记
(const int[]){5, 6, -1},
(const int[]){7, 8, -1}
};
//每一个定义都要加上const,不太明白,但是不加就会报类型错误
int size = sizeof(a) / sizeof(a[0]);
for (int i = 0; i < size; i++) {
int j = 0;
while (a[i][j] != -1) { // 根据结束标记判断数组的结束位置
printf("%d ", a[i][j]);
j++;
}
printf("\n");//换行
}
return 0;
}
如果已知数量就可以:改变的只有前面的部分,这个时候遍历的话,就不需要在每一个后面加上-1,可以直接用嵌套循环输出了
#include <stdio.h>
int main(void) {
const int a[3][5] = {
{1, 2, 3, 4, -1}, // 在数组末尾添加-1作为结束标记
{5, 6, -1},
{7, 8, -1}
};
int size = sizeof(a) / sizeof(a[0]);
for (int i = 0; i < size; i++) {
int j = 0;
while (a[i][j] != -1) { // 根据结束标记判断数组的结束位置
printf("%d ", a[i][j]);
j++;
}
printf("\n");
}
return 0;
}
3.字符串函数
==注意引用string.h函数
#include <stdio.h>
#define N 6
int binarySearch(int arr[], int n, int target);
int main() {
int arr[] = {8, 12, 23, 45, 54, 67};
int target = 67; // 要查找的目标元素
int index = binarySearch(arr, N, target);
if (index != -1) {
printf("目标元素 %d 在数组中的索引为 %d\n", target, index);
} else {
printf("目标元素 %d 未在数组中找到\n", target);
}
return 0;
}
// 二分查找函数,返回目标元素的索引,若未找到则返回 -1
int binarySearch(int arr[], int n, int target) {
int low = 0, high = n-1;
while (low <= high) {
int mid = low + (high - low) / 2; // 计算中间元素的索引
// 如果目标元素与中间元素相等,则返回中间元素的索引
if (arr[mid] == target) {
return mid;
} else if (arr[mid] < target) {
// 如果中间元素小于目标元素,则在右半部分继续搜索
low = mid + 1;
} else {
// 如果中间元素大于目标元素,则在左半部分继续搜索
high = mid - 1;
}
}
return -1; // 未找到目标元素,返回 -1
}