首页 > 其他分享 >C语言day11(string函数族、递归函数、结构体、共用体、枚举)

C语言day11(string函数族、递归函数、结构体、共用体、枚举)

时间:2024-08-06 08:55:03浏览次数:9  
标签:struct int 32 定义 C语言 char day11 student string

【1】string函数族

1. strlen

头文件:#include <string.h>

格式:size_t strlen(const char *s);

功能:计算字符串实际长度,不包括\0

参数:s:目标字符串首地址

返回值:字符串实际长度

2. strcpy

       头文件 : #include <string.h>
       格式:char *strcpy(char *dest, const char *src);
       功能:实现字符串的复制
       参数:dest:目标字符串的地址
       src:源字符串的地址
       返回值:目标字符串的地址

  

       注意:字符串的结束字符'\0',也会一起拷贝。

 3.strncpy

       头文件: #include <string.h>

       格式:char *strncpy(char *dest, const char *src, size_t n);
       功能:实现前 n 个字符串的复制
       参数:dest:目标字符串的地址
       src:源字符串的地址
       n:个数
       返回值:目标字符串的地址
       
       注意:字符串的结束字符'\0',也会一起拷贝。

 

 4.strcat

       头文件:#include <string.h>
       格式:char *strcat(char *dest, const char *src);
       功能:实现字符串的拼接
       参数:dest:目标字符串的地址
       src:源字符串的地址
       返回值:目标字符串的地址

       注意:目标字符串'\0'被删除,然后连接源串

 5.strncat

       头文件:#include <string.h>       

       格式:char *strncat(char *dest, const char *src, size_t n);
       功能:实现字符串的拼接
       参数:dest:目标字符串的地址
       src:源字符串的地址
       n:指定要拼接字符的个数
       返回值:目标字符串的地址
       
       注意:目标字符串'\0'被删除,然后连接源串

 6.strcmp

       头文件:#include <string.h>
       格式:int strcmp(const char *s1, const char *s2);
       功能:用于字符串大小的比较
       参数:s1,s2:用来比较的字符串的地址
       返回值:ascii码值比较 两者相等 继续向后比较 如果不相等 返回s1-s2

       比较字符的ASCII值(从第一个字符开始比较)
        >0      s1>s2
        0        s1=s2
       <0       s1<s2

7.strncmp

格式:int strncmp(const char *s1, const char *s2, size_t n);

功能:比较前n个字符的大小 

练习:

void fun(char *p)   //p=NULL
	{
		p = (char *)malloc(32);
		strcpy(p, "hello");	
	}
int	main()
	{
		char *m = NULL;
		fun(m);
		printf("%s\n", m); //NULL
         return 0;
	}

输出结果:段错误

子函数里面的 p 指针所指向的地址开辟的32 个字节的堆区空间,但是未释放,函数就结束了,内存泄漏导致段错误;主函数中的输出语句输出空指针的值,调用空指针,也会导致段错误;

解决方法:

(1)通过返回值

char *fun(char *p)   //p=NULL
	{
		p = (char *)malloc(32);
		strcpy(p, "hello");	
        return p;
	}
int	main()
	{
		char *m = NULL;
		m = fun(m);
		printf("%s\n", m); //hello
        free(m);
        m = NULL;
         return 0;
	}

(2)传参数的地址过去,通过二级指针

char *fun(char **p)   //p=NULL
	{
		*p = (char *)malloc(32);
		strcpy(*p, "hello");	
	}
int	main()
	{
		char *m = NULL;
		m = fun(&m);
		printf("%s\n", m); //hello
        free(m);
        m = NULL;
         return 0;
	}

【2】递归函数

定义:自己调用自己的函数

执行过程:

(1)递推阶段:从原问题出发,按照递归公式递推,从未知推到已知,最终达到递归终止条件

(2)回归阶段:按照递归终止条件求出结果,逐步带入递归公式,回到原问题

 例子:实现阶乘

int fun(int n){
    if(n == 1){
        return 1;
    }
    return n * fun(n - 1);
}
int main()
{
printf("%d\n",fun(5));
return 0;
}

【3】结构体

定义:用户自定义的数据类型,在结构体中可以包含若干不同数据类型的成员变量(也可以相同),是这些数据项目组合起来反应某一信息。

格式:

struct 结构体名
{
数据类型  成员变量名1;
数据类型  成员变量名2;
数据类型  成员变量名3;
.....
};

注意:要在结构体定义的大括号后加分号  ‘   ; ’

1》结构体变量

概念:使用结构体类型定义的变量

格式:

struct 结构体名 变量名;
 定义方式:

(1)定义结构体同时定义结构体变量

struct 结构体名
{
    成员列表;
} 变量名;

(2)先定义结构体,后再定义结构体变量

struct 结构体名
{
    成员列表;
};
struct 结构体名 结构体变量名;

(3)定义结构体时没有名称(缺省结构体类型名)

 struct
{
    成员列表;
} 变量名;
赋值:

(1) 在定义变量时,直接用大括号进行赋值

struct student
{
    int age;
    float score;
    char name[32];
};
struct student stu1 = {23, 99, "zhangsan"};
struct student stu2 = {60, 61, "lisi"};

(2)定义变量时未初始化,然后通过结构体成员变量单独赋值

#include <stdio.h>
#include <string.h>
struct student
{
    int age;
    float score;
    char name[32];
};
struct student stu1;
int main(int argc, char const *argv[])
{
    stu1.age = 18;
    stu1.score = 63;
    strcpy(stu1.name, "zhangsan");       //数组类型不能直接赋值,需要通过strcpy函数进行赋值
    return 0;
}

(3)点等法赋值

struct student
{
    int age;
    float score;
    char name[32];
};
struct student stu1 =
    {
        .age = 18;
        .score = 36.2;
};
访问:

输出:通过点的方式:结构体变量名 . 成员变量名

输入:结构体变量名 . 成员变量名

struct student
{
    int age;
    float score;
    char name[32];
};

int main(){
struct student stu1;
scanf("%s",stu1.name);
printf("%s\n",stu1.name);
return 0;
}

2》重定义typedef

格式:typedef 旧名称  新名称

例:Typedef  int *  intp           则int * p就等同于intp  p

定义格式:

(1)定义结构体同时重定义

typedef struct student
{
    int age;
    float score;
    char name[32];
}stu;     //这就将student结构体重定义为了stu,之后创建结构体变量就可以使用stu创建,更加简便

(2)先定义结构体,之后再重定义

struct student
{
    int age;
    float score;
    char name[32];
}; 

type struct student stu;
stu stu1;

3》结构体数组

概念:结构体类型相同的变量组成的数组

定义格式:

(1)定义结构体同时定义结构体数组

struct student
{
    int age;
    float score;
    char name[32];
}stu[32];           //同时定义

(2)先定义结构体,再定义结构体数组

struct student
{
    int age;
    float score;
    char name[32];
}; 

struct student stu[32];

 初始化:

(1)定义的同时赋值

struct student
{
    int age;
    float score;
    char name[32];
}stu[32] = {
      {20,99.9,liuhuan},
      {23,34.4,lkjh},
      {22,23.3,ksldfm},
      ......
};     

(2)先定义后再对每一个元素赋值

struct student
{
    int age;
    float score;
    char name[32];
}stu[32];

strcpy(stu[0].name,"kkk");
stu[0].age = 20;
stu[0].score = 34.4;

结构体数组的大小:

(1)结构体大小 * 元素个数

(2)sizeof(结构体数组名称)

结构体大小:

字节对齐原则         (64位系统)对齐 8 字节,比8字节小的就按照8字节开辟空间

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct demo
{
    short a;// 2     开辟8字节
    int b; //4     
    double c;//8    开辟8字节
};

int main()
{
    struct demo Darr[3];
    printf("%d\n", sizeof(struct demo)); // 16
    return 0;
}

 4》结构体指针

概念:指向结构体变量的指针

定义格式:

struct  结构体名  *   指针名

struct demo
{
    short a;  
    int b;    
    double c; 
} d1, d2;
struct work
{
    int a;
} w1;

int main()
{
    struct demo *p = &d1;   
    struct demo *p1 = &w1;//错,不同类型的结构体不能混合指向
    return 0;
}

赋值:

(1)指针变量名 ->成员变量名  =  新值

struct student *p = &stu1;
p->age = 20;
p->score = 23.4;
printf("%d\n",p->age);

(2)(*p).成员变量

struct student *p = &stu1;
(*p).age = 20;
printf("%d\n",(*p).age);

 指针大小:8字节  仍然是取决于计算机操作系统的大小

重定义指针:

struct student
{
    int age;
    float score;
    char name[32];
}stu,*stup;    //重定义了结构体和结构体指针

int main(){
stu stu1;       //定义结构体变量
stup p = &stu1; //定义结构体指针
return 0;
}


总结:

1. 不能把结构体类型变量作为整体引用,只能对结构体类型变量中的各个成员变量分别引用

即:stu.id可以输出 直接输出stu不行 stu整体不行必须具体到每一个成员变量

2.如果成员变量本身属于另一种结构体类型,用若干个成员运算符一级级找到最低级的成员变量

3. 可以把成员变量当成普通变量运算(++ --都可以)

4. 在数组中,数组之间是不能彼此赋值的,结构体变量可以相互赋值

 【4】共用体

概念

不同类型的成员变量共用同一块地址空间 使用union

 格式

union 共用体名

{

成员变量1;

成员变量2;

};

#include <stdio.h>
union 共用体名 变量名;
union val               //定义一个共用体
{
    int num;
    char ch;
};
union val v;            //定义共用体变量
int main(int argc, char const *argv[])
{
    v.num = 10;
    v.ch = 'a';
    printf("%d",v.num);     //97   
    return 0;
}

特性:

(1)共用体所有成员共用同一块地址空间

(2)赋值顺序一最后一次赋值为内存中的实际数据

(3)共用体的大小为数据类型的数据大小

但当存在数组类型时,也需要进行共用体对齐,以最大的数据类型所占字节数为比较标准

 可以用来判断大小端

union hello
 {
   int a;
   char b;
 };
 
int main()
{
    union hello h1;
    h1.a=0x12345678; 
    printf("a=%#x\n",h1.b);//   ox78   小端模式
    return 0;
}

【5】枚举

定义

用户自定义的数据类型,可以用于声明一组常数

 格式

enum  枚举名

{

value1 = 值;

value2 = 值;

value3 = 值;

value4 = 值;

.....

}

#include <stdio.h>
enum week
{
    MON = 1,
    TUE,
    WED,
};
int main()
{
    int n;
    scanf("%d", &n);
    switch (n)
    {
    case MON:
        printf("%d\n", MON);
        break;
    case TUE:
        printf("%d\n", TUE);
        break;
        ...
    }
}
未赋初值,第一个常数会默认为0,依次加一。

未赋值的部分在前一个的基础上加1

 【6】存储类型

static    extern   register(寄存器)

(1)static:修饰变量和函数

修饰变量:
1.变量存放的位置在全局区(静态区)

a. 有初值存在.data区域
b. 没有初值存在.bss区域

2.生命周期为整个程序

3.限制作用域:
修饰的是局部变量,和普通局部变量作用域没有区别,但是可以延长它的生命周期。
修饰全局变量,限制仅在本文件中使用

4.只初始化一次,在未赋初值时为0
修饰函数:
static 修饰的函数只能在本文件中使用

  (2)extern 外部引用

通过extern引用其他文件中的全局变量或函数

 main.c

#include <stdio.h>
extern int n;
extern void fun();     //通过extern引用了test.c中的fun.c函数
int main()
{
    printf("%d\n", n);
    fun();
    return 0;
}

test.c

#include <stdio.h>
int n = 10;
void fun()
{
    printf("helloworld\n");
}

标签:struct,int,32,定义,C语言,char,day11,student,string
From: https://blog.csdn.net/dghbs/article/details/140920891

相关文章

  • ARC181 - B - Annoying String Problem
    B-令人讨厌的字符串问题编辑:evima在大多数情况下,\(f(S,T,X)\)和\(f(S,T,Y)\)的长度相等,这揭示了\(T\)的长度。让我们来看看当已知\(S\)和\(T\)的长度时,在什么条件下\(S\)和\(T\)满足\(f(S,T,X)=f(S,T,Y)\)。例题例如,当\(|S|=6\)和\(|T|=4\)时,让我们考虑当\(S+......
  • C语言编译和链接
    前言我们已经写了这么多的代码,那我们是不是应该了解一下代码是运行的呢?1.翻译环境和运行环境翻译环境将源代码转换为二进制指令。运行环境用于执行实际代码2.翻译环境翻译环境主要由编译和链接两个大过程组成,而编译又可以分解成:预处理/预编译,编译,汇编三个过程。2.1......
  • Vs code写C语言代码配置(超级详细基础,小白也能看得懂)
    前言本文旨在为那些希望在VSCode中配置C语言开发环境的开发者提供一份详尽的指南。无论你是C语言的新手,还是希望提升开发效率的老手,本文都将引导你通过一系列简单的步骤,完成VSCode的C语言开发配置。我们将涵盖从安装VSCode开始,到配置编译器、调试器,以及安装必要的扩展,确保......
  • 模拟实现 memcpy --浅谈C语言
    内存拷贝-memcpy描述C库函数void*memcpy(void*str1,constvoid*str2,size_tn)从存储区str2复制n个字节到存储区str1。memcpy是最快的内存到内存复制子程序。它通常比必须扫描其所复制数据的strcpy,或必须预防以处理重叠输入的memmove更高效。memcpy,memcpy......
  • 嵌入式开发C语言学习day28-华清作业8.5
    思维导图作业1:pipe.c//使用有名管道实现一个进程用于给另一个进程发消息//另一个进程收到消息后展示到终端上并且将消息保存到文件上一份#include<myhead.h>intmain(intargc,charconst*argv[]){//创建一个有名管道if(mkfifo("./linux",0664)......
  • C语言入门 --- sizeof 与 strlen 的区别
    ......
  • C语言 随机函数
    随机函数随机函数是一个使用内部链接的静态变量的函数;ANSIC库提供了rand()函数生成随机数。在C语言中rand()生成的随机数,并不是真正意义上的随机数,而是一个伪随机数;实际上,rand()是“伪随机数生成器”,意思是可预测生成数字的实际序列,且数字在其取值范围内均匀分布......
  • 【Python】Python中的输入与输出——内附Leetcode【151.反转字符串中的单词】的C语言
    输入与输出导读一、Python中的输出1.1基本用法1.2格式化输出1.3通过`:`格式化值的输出1.4其它格式化输出二、Python中的输入2.1基本用法2.2`split()`方法2.3split()习题演练结语导读大家好,很高兴又和大家见面啦!!!在上一篇内容中我们介绍了Python中的数据类......
  • String类常用方法
    常用方法字符串比较:equals(Objectanother):比较两个字符串的内容是否相等。equalsIgnoreCase(Stringanother):比较两个字符串的内容,忽略大小写。字符串长度:length():返回字符串的长度。字符串转换:toString():返回其自身的字符串表示形式。valueOf(类型x......
  • StringBuffer 和 StringBuilder
    StringBuffer和StringBuilder目录StringBuffer和StringBuilderStringBuffer:StringBuilder常用方法StringBuffer:StringBuffer是线程安全的。这意味着它的方法是同步的,可以在多线程环境中使用而不会出现问题。由于同步,StringBuffer的性能比StringBuilder稍低,特别是......