结构体、结构体变量、结构体指针、字符串

结构体

数组是用于保存一组相同类型数据的, 而结构体是用于保存一组不同类型数组的
在使用结构体之前必须先定义结构体类型, 因为C语言不知道你的结构体中需要存储哪些类型数据, 我们必须通过定义结构体类型来告诉C语言, 我们的结构体中需要存储哪些类型的数据

struct 结构体名{
     类型名1 成员名1;
     类型名2 成员名2;
     ……
     类型名n 成员名n;
 };

结构体变量占用存储空间大小

结构体的总大小为结构体最宽基本类型元素大小的整数倍

  struct Person{
        int age; // 4  第一次开辟8byte 剩4
        char ch; // 1  不开辟使用第一次开辟剩余的4byte,剩3 
        double score; // 8 3byte不够分配,第二次开辟8byte
    };
   struct Person p;
   printf("sizeof = %i\n", sizeof(p)); // 16
占用内存最大属性是score, 占8个字节, 所以第一次会分配8个字节
将第一次分配的8个字节分配给age4个,分配给ch1个, 还剩下3个字节
当需要分配给score时, 发现只剩下3个字节, 所以会再次开辟8个字节存储空间
一共开辟了两次8个字节空间, 所以最终p占用16个字节
    struct Person{
        int age; // 4  第一次开辟88byte  剩4
        double score; // 8  不够,第二次开辟8byte 
        char ch; // 1   无剩,第三次开辟8 byte
    };
    struct Person p;
    printf("sizeof = %i\n", sizeof(p)); // 24
占用内存最大属性是score, 占8个字节, 所以第一次会分配8个字节
将第一次分配的8个字节分配给age4个,还剩下4个字节
当需要分配给score时, 发现只剩下4个字节, 所以会再次开辟8个字节存储空间
将新分配的8个字节分配给score, 还剩下0个字节
当需要分配给ch时, 发现上一次分配的已经没有了, 所以会再次开辟8个字节存储空间
一共开辟了3次8个字节空间, 所以最终p占用24个字节

结构体变量的定义

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

先定义结构体类型,再定义变量:
struct Student {
     char *name;
     int age;
 };
struct Student stu;
定义结构体类型的同时定义变量
struct Student {
    char *name;
    int age;
} stu;
匿名结构体定义结构体变量
struct {
    char *name;
    int age;
} stu;

第三种方法与第二种方法的区别在于,第三种方法中省去了结构体类型名称,而直接给出结构变量,
这种结构体最大的问题是结构体类型不能复用。

结构体变量的初始化

定义的同时按顺序初始化
struct Student {
     char *name;
     int age;
 };
struct Student stu = {“cxx", 22};
定义的同时不按顺序初始化
struct Student{
	char *name;
	int age;
};
struct Student stu = {.age = 22, .name = "cxx" };
先定义后逐个初始化
struct Student{
	char *name;
	int age;
};
struct Student stu;
stu.age = 22;
stu.name = "cxx" ;
先定义后一次性初始化
struct Student {
     char *name;
     int age;
 };
struct Student stu;
stu2 = (struct Student){"cxx", 22};

结构体指针

一个指针变量当用来指向一个结构体变量时,称之为结构体指针变量
格式:== struct 结构名 *结构指针变量名==

int main(void)
{
    // 定义一个结构体类型
      struct Student {
          char *name;
          int age;
      };

     // 定义一个结构体变量
     struct Student stu = {“lnj", 18};
     // 定义一个指向结构体的指针变量
     struct Student *p;

    // 指向结构体变量stu
    p = &stu;
    
     //这时候可以用3种方式访问结构体的成员
     // 方式1:结构体变量名.成员名
     printf("name=%s, age = %d \n", stu.name, stu.age);

     // 方式2:(*指针变量名).成员名
     printf("name=%s, age = %d \n", (*p).name, (*p).age);

     // 方式3:指针变量名->成员名
     printf("name=%s, age = %d \n", p->name, p->age);

     return 0;
 }

结构体指针成员访问

通过结构体指针访问结构体成员, 可以通过以下两种方式:
(*结构指针变量).成员名
== 结构指针变量->成员名==

字符串定义、初始化:

	char string[]="cxx";
	printf("%s\n",string); //输出结果:cxx
	//数组名保存的是数组第0个元素的地址, 指针也可以保存第0个元素的地址
	char *str = "abc"
	for(int i = 0; i < strlen(str);i++){
  		printf("%c-", *(str+i)); //输出结果:a-b-c
	}
    char name[9] = "cxx"; //在内存中以“\0”结束, \0ASCII码值是0
    char name1[9] = {'c,'x','x','\0'};
    char name2[9] = {'c','x','x',0};
    // 当数组元素个数大于存储字符内容时, 未被初始化的部分默认值是0, 所以下面也可以看做是一个字符串
    char name3[9] = {'c','x','x'};

字符串输出:

如果字符数组中存储的是一个字符串, 那么字符数组的输入输出将变得简单方便。
不必使用循环语句逐个地输入输出每个字符
可以使用printf函数和scanf函数一次性输出输入一个字符数组中的字符串
使用的格式字符串为“%s”,表示输入、输出的是一个字符串

输出%s的本质就是根据传入的name的地址逐个去取数组中的元素然后输出,直到遇到 ‘\0’ 位置结束

	char name[]="chenc\0hen";
	printf("%s\n",name); //输出结果:chenc
 	//对一个字符串数组, 如果不做初始化赋值, 必须指定数组长度
	char name[10];
	scanf("%s",name); //输入一串字符
	
//name最多存放由9个字符构成的字符串,其中最后一个字符的位置要留给字符串的结尾标示‘\0’
//当用scanf函数输入字符串时,字符串中不能含有空格,否则将以空格作为串的结束符;

字符串长度计算:

sizeof关键字:

因为字符串在内存中是逐个字符存储的,一个字符占用一个字节,所以字符串的结束符长度也是占用的内存单元的字节数。

    char name[] = "it666";
    int size = sizeof(name);// 包含\0结束符
    printf("size = %d\n", size); //输出结果:6
strlen函数:

测字符串的实际长度(不含字符串结束标志‘\0’)并作为函数返回值。

  char name[] = "it666";
  size_t len = strlen(name2);
  printf("len = %lu\n", len); //输出结果:5

以“\0”为字符串结束条件进行统计

/**
 *  自定义方法计算字符串的长度
 *  @param name 需要计算的字符串
 *  @return 不包含\0的长度
 */
int myStrlen2(char str[])
{
    //    1.定义变量保存字符串的长度
    int length = 0;
    while (str[length] != '\0')
    {
        length++;//1 2 3 4
    }
    return length;
}
/**
 *  自定义方法计算字符串的长度
 *  @param name  需要计算的字符串
 *  @param count 字符串的总长度
 *  @return 不包含\0的长度
 */
int myStrlen(char str[], int count)
{
//    1.定义变量保存字符串的长度
    int length = 0;
//    2.通过遍历取出字符串中的所有字符逐个比较
    for (int i = 0; i < count; i++) {
//        3.判断是否是字符串结尾
        if (str[i] == '\0') {
            return length;
        }
        length++;
    }
    return length;
}

字符串连接函数:strcat

格式: strcat(字符数组名1,字符数组名2)
功能:把字符数组2中的字符串连接到字符数组1 中字符串的后面,并删去字符串1后的串标志 “\0”。本函数返回值是字符数组1的首地址。

char oldStr[100] = "welcome to";
char newStr[20] = " cxx";
strcat(oldStr, newStr);
puts(oldStr); //输出: welcome to lnj"

本程序把初始化赋值的字符数组与动态赋值的字符串连接起来。
要注意的是,字符数组1应定义足 够的长度,否则不能全部装入被连接的字符串。

字符串拷贝函数:strcpy

格式: strcpy(字符数组名1,字符数组名2)
功能:把字符数组2中的字符串拷贝到字符数组1中。串结束标志“\0”也一同拷贝。字符数名2, 也可以是一个字符串常量。这时相当于把一个字符串赋予一个字符数组。

char oldStr[100] = "welcome to";
char newStr[50] = " cxx";
strcpy(oldStr, newStr);
puts(oldStr); // 输出结果:  lnj // 原有数据会被覆盖

本函数要求字符数组1应有足够的长度,否则不能全部装入所拷贝的字符串。

字符串比较函数:strcmp

格式: strcmp(字符数组名1,字符数组名2)
功能:按照ASCII码顺序比较两个数组中的字符串,并由函数返回值返回比较结果。
字符串1=字符串2,返回值=0;
字符串1>字符串2,返回值>0;
字符串1<字符串2,返回值<0。

char oldStr[100] = "0";
char newStr[50] = "1";
printf("%d", strcmp(oldStr, newStr)); //输出结果:-1
char oldStr[100] = "1";
char newStr[50] = "1";
printf("%d", strcmp(oldStr, newStr));  //输出结果:0
char oldStr[100] = "1";
char newStr[50] = "0";
printf("%d", strcmp(oldStr, newStr)); //输出结果:1
  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程一时爽Cxx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值