C语言入门_数组与函数传参(重点在于练习实战)

举报
DS小龙哥 发表于 2024/01/31 14:19:07 2024/01/31
【摘要】 今天这篇博客,咱要一起聊聊C语言中那些“接地气”的实用技巧,特别是关于字符串标准处理函数、指针和数组作为函数参数的那些事儿。谁说编程就得咬文嚼字、故作高深?其实这些看似复杂的概念,只要理解透彻并灵活运用,就能在日常编码中如鱼得水。

今天这篇博客,咱要一起聊聊C语言中那些“接地气”的实用技巧,特别是关于字符串标准处理函数、指针和数组作为函数参数的那些事儿。谁说编程就得咬文嚼字、故作高深?其实这些看似复杂的概念,只要理解透彻并灵活运用,就能在日常编码中如鱼得水。

首先来盘一盘string.h头文件中的那些字符串处理好帮手,它们就像是你编程工具箱里的瑞士军刀,帮你轻松搞定字符串拼接、查找替换等各种操作,让你对字符串管理游刃有余。

再来说说指针和数组作为函数形参的话题,这两者堪称是C语言的灵魂所在,不仅能够高效传递大量数据,还能实现复杂的数据结构操作。从指针的基本定义开始,一步步教你如何通过函数返回指针、使用void类型定义指针以及进行类型强制转换等核心技巧,助你修炼成指针大神!

另外,也不能忽视常量声明和extern关键字的作用。常量声明就像给程序中的特定数值起了个永不改变的名字,而extern关键字则帮助我们在不同源文件之间共享变量,让代码逻辑更加清晰,项目协作更为便捷。


字符串标准处理函数介绍(string.h)、指针和数组当做函数形参,指针定义、函数返回指针、void类型定义指针、类型强制转换、常量声明、extern外边引用声明关键字。

1. 总结字符串相关的处理函数

string.h里常用的字符串处理相关函数。

字符串: string.h
void *memcpy(void *restrict, const void *restrict, size_t);
int  memcmp(const void *, const void *, size_t);
void *memset(void *, int, size_t);
char *strcat(char *restrict, const char *restrict);
int  strcmp(const char *, const char *);
char *strcpy(char *restrict, const char *restrict);
size_t strlen(const char *);
char *strncat(char *restrict, const char *restrict, size_t);
int  strncmp(const char *, const char *, size_t);
char *strncpy(char *restrict, const char *restrict, size_t);
char *strstr(const char *, const char *);
​
格式化打印(转换)函数:
int sprintf(char *str, const char *format, ...);
int snprintf(char *str, size_t size, const char *format, ...);
int sscanf(const char *str, const char *format, ...);

说明: char p; // a=aa; //乘法 char *p; //定义指针 指针用于代表一个地址。 指针可以当做数组使用,数组无法当做指针使用。

数组的名称: 就是首地址 在C语言里任何类型的指针(地址)是4个字节

2. 函数参数: 指针与数组类型

函数的形参: 指针类型与数组类型 示例代码: ()

#include <stdio.h>  //标准输入输出
#include <string.h> //字符串处理头文件
int my_strlen1(char buff[]);
int my_strlen2(char *buff);
​
int main(int argc,char **argv)
{
    char str[]="1234567890";
    int len1=my_strlen1(str);
    int len2=my_strlen2(str);
    printf("%d\n",len1);
    printf("%d\n",len2);
    return 0;
}
​
/*
函数功能:计算字符串的长度
char buff[] :传入是数组类型,也就是传入的是地址
*/
int my_strlen1(char buff[])
{
    int cnt=0;
    while(buff[cnt]!='\0')
    {
        cnt++;
    }
    return cnt;
}
​
/*
函数功能:计算字符串的长度
char *str :传入是字符指针类型,也就是传入的是地址
*/
int my_strlen2(char *buff)
{
    int cnt=0;
    while(buff[cnt]!='\0')
    {
        cnt++;
    }
    return cnt;
}

3. 数组当做函数形参的问题

示例:
#include <stdio.h>  //标准输入输出
#include <string.h> //字符串处理头文件
​
void my_func1(char buff[100]);
void my_func2(char *buff);
void sum(int a);
​
int main(int argc,char **argv)
{
    int a=100;
    char str[100]="12345";
    my_func1(str);
    my_func2(str);
    sum(a);
    return 0;
}
​
//char buff[100] 函数形参里是地址不会申请空间
void my_func1(char buff[100])
{
    char buff1[100];
    printf("sizeof=%d\n",sizeof(buff));
    printf("sizeof1=%d\n",sizeof(buff1));
}
​
void my_func2(char *buff)
{
    printf("sizeof=%d\n",sizeof(buff));
}

4. 指针定义: 存放地址

#include <stdio.h>  //标准输入输出
#include <string.h> //字符串处理头文件
​
int main(int argc,char **argv)
{
    int a=100;
    char str[100]="123456";
    char *p; //定义的是一个指针(地址)
    p=str;   //可以赋值
    //p=&a;    //可以赋值
​
    printf("%p\n",&a);
    printf("%p\n",str);
    printf("%p\n",p);
    
    printf("%s\n",str);
    printf("%s\n",p);
    return 0;
}

5. 函数形参和返回值: 都是地址

(1)数组类型可以当做函数形参。void func(char buff[]){}

(2)数组类型不能当做函数返回值类型。char buff[] func(void){} 错误的 函数如果要返回地址类型: 必须使用指针类型。 函数形参如果要传入地址类型: 可以使用指针类型或者数组类型。

示例代码:

#include <stdio.h>  //标准输入输出
#include <string.h> //字符串处理头文件
char *func(char buff[]);
int main(int argc,char **argv)
{
    char str[]="12345";
    char *str1=func(str);
    
    printf("%p\n",str);
    printf("%p\n",str1);
    
    printf("%s\n",str1);
    return 0;
}
​
//形参是一个数组类型(char的地址)
//返回值是一个char类型的地址
char *func(char buff[])
{
    return buff;
}
​
示例代码(局部地址是不能返回的)
#include <stdio.h>  //标准输入输出
#include <string.h> //字符串处理头文件
char *func(void);
int func1(void);
int main(int argc,char **argv)
{
    char *str=func();
    printf("str=%s\n",str);
    printf("str2=%p\n",str);
    
    int a=func1();
    printf("a=%d\n",a);
    return 0;
}
​
char *func(void)
{
    char str[]="5thgtrgbtfbfgbgf";
    //static char str[]="5thgtrgbtfbfgbgf"; 
    //加了静态关键字之后,数据空间永久保留(与main函数生命周期一样)
    printf("str1=%p\n",str);
    return str; //将数据空间的地址返回,将地址赋值给接收返回值的指针变量
}
​
int func1(void)
{
    int a=88;
    return a; //a变量里的数据取出来返回去,赋值给接收返回值的变量。
}

6. void*类型指针

#include <stdio.h>  //标准输入输出
#include <string.h> //字符串处理头文件
void func(void *p);
​
int main(int argc,char **argv)
{
    int buff[100];
    char str[100];
    func(buff);
    func(str);
    return 0;
}
​
/*
void *p:传入的形参自适应
*/
void func(void *p)
{
    
}
//void a; //语法是错误的
//int a;  //定义一个int类型变量,空间是4个字节
//void *p //指针本身是存放地址,任何类型的指针都是4个字节

7. 强制转换

强制转换只是欺骗编译器,消除警告,不会改变本身的数据类型。 示例代码: 指针之间的强制转换

#include <stdio.h>  //标准输入输出
#include <string.h> //字符串处理头文件
void func(int *p);
​
int main(int argc,char **argv)
{
    char str[]="123456789";
    func((int*)str); //强制转换语法
    return 0;
}
​
/*
void *p:传入的形参自适应
*/
void func(int *p)
{
    char *str=(char*)p;
    printf("str=%s\n",str);
}

8. 常量声明关键字: const

#include <stdio.h>  //标准输入输出
#include <string.h> //字符串处理头文件
​
int main(int argc,char **argv)
{
    char buff[100]="123";
    const char *p=buff; //表示p指向的buff的空间数据是不能修改的
    //*p='A'; //不能修改  赋值是错误的
    p[0]='A'; //不能修改  赋值是错误的
    
    //const int a=99;//定义a是只读变量。
    //a=88; //赋值是错误的
    return 0;
}

9. extern外部声明关键字

主要是用在头文件里,多文件编程中。
#include <stdio.h>  //标准输入输出
#include <string.h> //字符串处理头文件
extern void func(void);//外部引用声明
extern int data; //外部引用声明

int main(int argc,char **argv)
{
	func();
	printf("%d\n",data);
	return 0;
}

int data=888; //定义变量
void func(void)
{
	printf("123\n");
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。