首页 > 其他分享 >C语言:指针(2)

C语言:指针(2)

时间:2024-12-12 13:02:12浏览次数:5  
标签:字符 int C语言 char str 字符串 指针

字符数组和字符指针

字符串的实现

在C语言中,表示一个字符串有以下两种形式:

  1. 用字符数组存放一个字符串,
  2. 用字符指针指向一个字符串
    案例:
/**
*字符串的两种实现方式
*/
	//方式1:使用字符数组实现字符串
	char str[]="I LOVR YOU";
	printf("%s\n",str);

	//使用字符指针实现字符串
	char *str="I LOVE YOU";
	printf("%s\n",str);

注意:字符数组和字符指针变量都能实现字符串的存储与运算

字符数组和字符指针的联系

  • 字符数组由元素组成,每个元素存放一个字符,而字符指针变量存放的是地址,也能作为函数参数
  • 只能对字符数组中的各个元素赋值,而不能用赋值语句对整个字符数组赋值。
char arr[3];
arr[2] = 'A';
arr = {'A','B','C'}; // 错误,(可以理解为数组名就是一个常量,也就是一旦创建,就不能再改变)

  • 字符数组名虽然代表地址,但数组名不能改变,因为数组名是常量。
  • 对于字符串中字符的存取,可以用下标法,可以用指针。
 //使用两种方式定义字符串
 char str1[]="奥丁当当";
 char *str2[]="奥丁当当";//我们将数据类型为char的指针变量称之为字符指针

 //测试赋值
 //str1 = "程序";//不能对字符数组整体赋值,如果要赋值,请使用string库下的strcpy();
 str2="奥丁当当"

 //打印输出
 printf("%s,%s\n",str1,str2);

 char a[]="奥丁当当";
 char *b[]="奥丁当当";

// 使用下标法和指针法来访问字符串
printf("%c,%c,%c,%c\n",a[2],*(a+2),b[2],*(b+2));

 

字符串作为形式参数

  • 实参与形参都可以是字符数组
void fun(char str[],int len){...};
void main
{
	char str[] = "hello";
	fun(str,sizeof(str)/sizeof(str[0]);
}
  • 实参用字符数组,形参用字符指针(在函数内部不能对字符串中的字符做修改,gcc编译环境可通过)
void fun(char *str,int len){
str[2] = 'A'; // GCC编译环境可通过
}
void main()
{
char str[] = "hello";// 常量池,此时的赋值,将常量池中的数据读取出来,存入到栈中数组对应的位
置
fun(str,sizeof(str) / sizeof(str[0]);
}
  • 实参和形参都是指针变量(在函数内部不能对字符串中的字符做修改)
void fun(char *str,int len){
str[2] = 'A'; // 错误,字符串常量一旦创建,就不能被改变
}
void main()
{
char *str = "hello";
fun(str,sizeof(str) / sizeof(str[0]);
}
  • 实参是指针类型,形参是字符数组(在函数内部不能对字符串中的字符做修改)
void fun(char str[],int len){
str[2] = 'A'; // 错误,字符串常量一旦创建,就不能被改变
}
void main()
{
char *str = "hello";
fun(str,sizeof(str) / sizeof(str[0]);
}

注意:

  1. 字符数组在创建的时候,会在内存中开辟内存空间,内存空间可以存放字符数据;字符指针在创建的时候,需要依赖于字符数组,字符指针在内存开辟的内存空间中,存放的是数组元素的地址。字符指针的创建依赖于字符数组,字符数组可以独立存在,而字符指针不能独立存在。
  2. 字符数组可以初始化,但是不能赋值;字符指针可以初始化,也可以赋值。
    案例
#include <stdio.h>
/**
* 定义一个函数,实现字符串的拷贝,返回字符串长度
* @param source 拷贝的源字符串
* @param target 需要保存拷贝数据的目标字符串
* @return 字符串的大小
*/
int str_copy(char *source,char *target)
{
// 定义一个循环变量
int i = 0;
while(source[i]!='\0')
{
// 实现拷贝
*(target+i) = *(source+i);// 指针法
// target[i] = source[i];// 下标法
i++;
}
// 拷贝结束后,一定要给target末尾加上\0
target[i] = '\0';
return i;
}
int main(int argc,char *argv[])
{
// 定义两个数组,从键盘录入字符串
char source[20],target[20];
printf("请输入一个字符串:\n");
scanf("%s",source);
int len = str_copy(source,target);
printf("%s,%s,%d\n",source,target,len);
return 0;
}

案例:

#include <stdio.h>
/**
* 定义一个函数,实现字符串的截取
* @param source 源字符串
* @param start 开始截取的位置
* @param end 截取结束的位置
* @param target 截取后的字符串
* @return 新字符串长度
*/
int str_split(char *source,int start,int end,char *target)
{
// 定义循环变量
int i = 0, k = 0;
// 遍历源字符串(数组)
while(source[i] != '\0')
{
// 根据位置截取
if(i >= start && i < end)
{
// 将截取的字符串存入target "helloworld"
target[k] = source[i];
k++;
}
i++;
}
// 新字符串需要末尾添加\0
target[k] = '\0';
return k;
}
int main(int argc,char *argv[])
{
char *str = "abcdefg";
char target[100];
int len = str_split(str,2,5,target);
printf("%s,%s,%d\n",str,target,len);
return 0;
}

函数指针与指针函数

函数指针

定义:函数指针本质上是指针,它是函数的指针(定义了一个指针变量,变量中存储了函数的地址)。函数都有一个入口地址,所谓指向函数的指针,就是指向函数的入口函数。这里函数名就代表入口地址
函数指针存在的意义:

  1. 让函数多了一种调用方式
  2. 函数指针作为形参,可以形式调用(回调函数)
    定义格式:
返回值类型 (*变量名)(形式参数列表);

举例:

int (*p)(int a,int b);

函数指针的初始化:

  1. 定义的同时赋值
// 函数指针需要依赖于函数,先有函数,再有指针
// 定义一个普通的函数
int add(int a,int b){ return a + b;}
// 定义一个函数指针,并给他赋值
// 通过以下代码我们发现:函数指针的返回类型和依赖函数的返回类型一致,函数指针的参数个数类型和依赖函
数一致
int (*p)(int a,int b) = add;// 赋值一定要注意:函数不能带有()
  1. 先定义后赋值
// 定义一个普通的函数
int add(int a,int b){ return a + b;}
// 定义一个函数指针
// int (*p)(int a,int b);
int (*p)(int,int); // 一般写作这种
// 给函数指针赋值
p = add;

注意:

  1. 函数指针指向的函数要和函数指针定义的返回值类型,形参列表对应,否则编译报错
  2. 函数指针时指针,但不能指针运算,如p++等,没有实际意义
  3. 函数指针作为形参,可以形成回调
  4. 函数指针作为形参,函数调用时的实参只能是与之对应的函数名,不能带()
  5. 函数指针的形参列表中的变量名可以省略

案例:

#include <stdio.h>
/**
* 定义一个函数指针
*/
int max(int a,int b)
{
if(a > b)
return a;
return b;
}
int main(int argc,char *argv[])
{
// 定义测试数据
int a = 3,b = 2,c;
// 直接函数调用
c = max(a,b);
printf("%d,%d两个数中的最大值是%d\n",a,b,c);
// 定义一个函数指针
int (*p)(int,int) = max;
// 间接函数调用
c = p(a,b);
printf("%d,%d两个数中的最大值是%d\n",a,b,c);
c = (*p)(a,b);
printf("%d,%d两个数中的最大值是%d\n",a,b,c);
return 0;
}

指针函数

定义:本质上是函数,这个函数的返回值类型是指针,这个函数称为指针函数。
语法:

指针类型 函数名(形参列表)
{
	函数体;
	return 指针变量;
}
// int *get(int a)
int* get(int a)
{
int *b = &a;
return b;
}
int main()
{
int *a = get(5);
printf("%d\n",*a);
}

注意:
在函数中不要直接返回一个局部变量的地址。因为函数调用完毕后,局部变量会被回收,使得返回的地址就不明确,此时返回的指针就是野指针
解决方案:
如果非要访问,可以给这个局部变量添加一个关键字static,可延长它的生命周期,避免野指针(尽量少用,因为存在内存泄漏)
案例:

#include <stdio.h>
/**
* 定义一个函数,传入学生的序号,返回这个学生的所有课程成绩
* @param p 二维数组
* @param n 学生索引(二维数组中行号)
* @return 学生成绩(行号对应的列数组)
*/
float* search(float (*p)[4],int n)
{
// 定义一个指针,用来接收查询到的某个学生的所有课程
float *pt;
pt = *(p+n);// *(p+n),*p[n],p[n]
return pt;
}
int main(int argc,char *argv[])
{
// 准备一个二维数组
float score[][4] = {{60,70,80,89},{55,66,77,88},{90,89,90,91}};
int m;
float *p;
printf("请输入学生序号(0~2):\n");
scanf("%d",&m);
printf("第%d个学生的成绩:\n",m);
// 用来接收某个学生的所有成绩
p = search(score,m);
// 遍历成绩
for(int i = 0;i < 4;i++)
printf("%5.2f\t",*(p+i));
printf("\n");
return 0;
}

标签:字符,int,C语言,char,str,字符串,指针
From: https://blog.csdn.net/2403_88805387/article/details/144390466

相关文章

  • C语言基础:数组(一维数组)
    引例如果我们要在程序中表示一个学生的成绩,我们会使用一个int来表示,如:intscore。假如我们要在程序中表示一组成绩,此时我们所学的常规的数据类型就无法再表示,这个时候我们就需要使用到一种新的表现形式,这种表现形式就是我们的数组。什么是数组数组是相同类型,有序数据的集合......
  • C语言基础:数组(二维数组)
    数组二维数组定义:二维数组本质上是一个行列式的组合,也就是说二维数组是由行和列两部分组成。二维数组数据是通过行列解读。二维数组可被视为一个特殊的一维数组,相当于二维数组又是一个一维数组,只不过它的元素是一维数组。(也就是说数组的元素可以是数组类型)。语法 类型......
  • 一些可能不太常见的C语言开发使用技巧
    1.复合字面量(CompoundLiterals)[C99]复合字面量是在C99中引入的,允许你在代码中直接定义结构体、数组或其他复杂数据类型的字面量。这种技巧可以简化代码,尤其是在需要临时生成复杂数据结构时。#include<stdio.h>structPoint{intx,y;};intmain(){//......
  • 十九、初识指针(2)
    指针不知道初始化为何值时,可先初始化为空指针。int*p=NULL;    //NULL,用来初始化指针,给指针赋值。一、指针运算1.指针+/-整数2.指针-指针|指针-指针|=中间的元素个数+1(同一数组)(同一块空间内存)(高地址-低地址)#define_CRT_SECURE_NO_WARNING......
  • ### 使用C语言优化解决八皇后问题
    八皇后问题是一道经典的算法问题,它要求在8×8的棋盘上放置8个皇后,使得任何两个皇后都不能互相攻击。本文通过改进传统回溯算法的实现,采用占用标记数组优化冲突检测,从而提升算法效率。####八皇后问题的规则在八皇后问题中,每个皇后必须满足以下规则:1.不能位于同一行。2.不......
  • ### 最大化相邻字符ASCII码之差的最小值:C语言实现与详解
    在字符串处理问题中,如何调整字符的排列以最大化相邻字符ASCII码之差的最小值是一个有趣的挑战。本文将通过一个具体的C语言实现,带你了解这一问题的解决思路和代码细节。####问题描述给定一个字符串,通过调整其字符顺序,使得字符串中任意相邻字符ASCII码之差的最小值最大。###......
  • C语言编程1.24螺旋方阵
    题目描述本题要求从右下角开始按螺旋型递减打印数字方阵。输入格式输入为一个正整数n(1=<n<=20)。输出格式螺旋型递减顺序输出n行n列的数字方阵,每个数字占4个宽度,左对齐。输入样例复制在这里给出一组输入。例如:4输出样例复制在这里给出相应的输出。例如:1098......
  • c语言编程1.23报数
    题目描述输入两个正整数n和m((1<m<n<=50)),有n个人围成一圈,按顺序从1到n编号。从第一个人开始报数,报数m的人退出圈子,下一个人从1开始重新报数,报数m的人退出圈子。如此循环,直到留下最后一个人。请按退出顺序输出退出圈子的人的编号,以及最后一个人的编号。提示:将......
  • C语言之初识数组存在的问题
        首先我们先了解数组的概念,所谓数组,简单来说数组就是一组相同元素的集合。是用来存放一组相同类型元素的存储形式。    但是我们在开始学数组的时候会存在一些问题或者说是疑问。    1.数组的下表是从‘0’开始,所以我们在访问数组的某个元素时,我......
  • 5.C语言-代码中的进制表示与转换
    八进制=三个二进制为一组十六进制=四个二进制为一组//进制转换intmain(){ //二进制:由0和1组成,在代码中以0b开头 inta=0b10; printf("%d",a); //十进制:由0~9组成,无需加前缀 intb=10; printf("%d",b); //八进制:由0~7组成,代码中以0开头 int......