C语言的学习(四)字符串 结构体 共同体 typedef

192 阅读7分钟

C语言 字符串 结构体 共同体 typedef

C语言 字符串

在 C 语言中,字符串实际上是使用空字符 \0 结尾的一维字符数组。因此,\0 是用于标记字符串的结束

空字符(Null character)又称结束符,缩写 NUL,是一个数值为 0 的控制字符,\0 是转义字符,意思是告诉编译器,这不是字符 0,而是空字符

定义字符串

// 数组的表面化的定义字符串的基本形式
char site[7] = {'R', 'U', 'N', 'O', 'O', 'B', '\0'};
​
// 等价于
char site[] = "RUNOOB";

字符串实质上来说的话就是我们的数组,只是我们数组的不同的表现形式,由于我们的字符串实际上就是我们的数组

所以说我们也是可以实现对字符串的遍历操作的



字符串常用方法

序号函数目的
1strcpy(str1, str2)将 str2 复制到 str1
2strcat(str1, str2)将 str2 连接到 str1 尾部
3strlen(str)返回 str1 长度
4strcmp(str1, str2)判断 str1 和 str2 是否相同,相同则返回0,否则返回 !0
5strchar(str1, ch)返回一个指针,指向 str1 中首次首次出现 ch 第一次出现的位置
6strstr(str1, str2)返回一个指针,指向字符串 str1 中字符串 str2 的第一次出现的位置
#include <stdio.h>
#include <string.h>
 
int main ()
{
   char str1[14] = "runoob";
   char str2[14] = "google";
   char str3[14];
   int  len ;
 
   /* 复制 str1 到 str3 */
   strcpy(str3, str1);
   printf("strcpy( str3, str1) :  %s\n", str3 );
 
   /* 连接 str1 和 str2 */
   strcat( str1, str2);
   printf("strcat( str1, str2):   %s\n", str1 );
 
   /* 连接后,str1 的总长度 */
   len = strlen(str1);
   printf("strlen(str1) :  %d\n", len );
 
   return 0;
}


C语言 结构体

C 数组允许定义可存储相同类型数据项的变量, 结构* 是 C 编程中另一种用户自定义的可用的数据类型,它允许您存储不同类型的数据项*

定义结构体

结构体的定义就是使用了我们的 struct 关键字,结构体内部是可以实现存放任意的数据类型的,以及自定义类型

实现定义的基本语法:

struct struct_name {
    // 需要包含的数据类型
};

定义结构体变量

struct struct_name s_name;

两者结合

struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
} book;

结构体的成员可以包含其他结构体,也可以包含指向自己结构体类型的指针,而通常这种指针的应用是为了实现一些更高级的数据结构如链表和树等

//此结构体的声明包含了其他的结构体
struct COMPLEX
{
    char string[100];
    struct SIMPLE a;
};
​
//此结构体的声明包含了指向自己类型的指针
struct NODE
{
    char string[100];
    struct NODE *next_node;
};


结构体变量的初始化

#include <stdio.h>struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
} book = {"C 语言", "RUNOOB", "编程语言", 123456};
​
int main()
{
    printf("title : %s\nauthor: %s\nsubject: %s\nbook_id: %d\n", book.title, book.author, book.subject, book.book_id);
}

访问结构体成员

实现访问结构体成员的,就是使用的是我们的 成员访问运算符(.)

#include <stdio.h>
#include <string.h>
 
struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
};
 
int main( )
{
   struct Books Book1;        /* 声明 Book1,类型为 Books */
   struct Books Book2;        /* 声明 Book2,类型为 Books */
 
   // 先实现结构变量的初始化赋值操作 
   /* Book1 详述 */
   strcpy( Book1.title, "C Programming");
   strcpy( Book1.author, "Nuha Ali"); 
   strcpy( Book1.subject, "C Programming Tutorial");
   Book1.book_id = 6495407;
​
   /* Book2 详述 */
   strcpy( Book2.title, "Telecom Billing");
   strcpy( Book2.author, "Zara Ali");
   strcpy( Book2.subject, "Telecom Billing Tutorial");
   Book2.book_id = 6495700;
 
 
    
   // 开始实现我们的访问结构体中的成员信息 
   /* 输出 Book1 信息 */
   printf( "Book 1 title : %s\n", Book1.title);
   printf( "Book 1 author : %s\n", Book1.author);
   printf( "Book 1 subject : %s\n", Book1.subject);
   printf( "Book 1 book_id : %d\n", Book1.book_id);
​
   /* 输出 Book2 信息 */
   printf( "Book 2 title : %s\n", Book2.title);
   printf( "Book 2 author : %s\n", Book2.author);
   printf( "Book 2 subject : %s\n", Book2.subject);
   printf( "Book 2 book_id : %d\n", Book2.book_id);
​
   return 0;
}

结构体和函数

结构体是可以作为我们的函数参数进行实现的

#include <stdio.h>
#include <string.h>
 
struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
};
​
/* 函数声明 */
void printBook( struct Books book );
int main( )
{
   struct Books Book1;        /* 声明 Book1,类型为 Books */
   struct Books Book2;        /* 声明 Book2,类型为 Books */
 
   /* Book1 详述 */
   strcpy( Book1.title, "C Programming");
   strcpy( Book1.author, "Nuha Ali"); 
   strcpy( Book1.subject, "C Programming Tutorial");
   Book1.book_id = 6495407;
​
   /* Book2 详述 */
   strcpy( Book2.title, "Telecom Billing");
   strcpy( Book2.author, "Zara Ali");
   strcpy( Book2.subject, "Telecom Billing Tutorial");
   Book2.book_id = 6495700;
 
   /* 输出 Book1 信息 */
   printBook( Book1 );
​
   /* 输出 Book2 信息 */
   printBook( Book2 );
​
   return 0;
}
​
// 该函数作用: 就是实现简化我们的访问结构体中成员的函数,提高了代码的复用性,后续些项目也是可以把这些
// 需要复用的代码实现抽离出来的,这样便于我们的代码的维护以及管理
void printBook( struct Books book )
{
   printf( "Book title : %s\n", book.title);
   printf( "Book author : %s\n", book.author);
   printf( "Book subject : %s\n", book.subject);
   printf( "Book book_id : %d\n", book.book_id);
}

结构体和指针之间的使用

首先需要说明的一点就是:我们的结构体就是我们的一种 type,只是结构体只是一种自定义数据类型而已

如果使用了结构体指针,那么这个时候实现访问成员变量的方法就是使用 **-> **操作符实现访问成员变量

#include <stdio.h>
#include <string.h>
 
struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
};
​
/* 函数声明 */
void printBook( struct Books *book );
int main( )
{
   struct Books Book1;        /* 声明 Book1,类型为 Books */
   struct Books Book2;        /* 声明 Book2,类型为 Books */
 
   /* Book1 详述 */
   strcpy( Book1.title, "C Programming");
   strcpy( Book1.author, "Nuha Ali"); 
   strcpy( Book1.subject, "C Programming Tutorial");
   Book1.book_id = 6495407;
​
   /* Book2 详述 */
   strcpy( Book2.title, "Telecom Billing");
   strcpy( Book2.author, "Zara Ali");
   strcpy( Book2.subject, "Telecom Billing Tutorial");
   Book2.book_id = 6495700;
 
   /* 通过传 Book1 的地址来输出 Book1 信息 */
   printBook( &Book1 );
​
   /* 通过传 Book2 的地址来输出 Book2 信息 */
   printBook( &Book2 );
​
   return 0;
}
void printBook( struct Books *book )
{
   printf( "Book title : %s\n", book->title);
   printf( "Book author : %s\n", book->author);
   printf( "Book subject : %s\n", book->subject);
   printf( "Book book_id : %d\n", book->book_id);
}

结构体大小的运算

计算结构体的大小就是使用的是我们的 sizeof 操作符实现的,最终的大小就是里面的数据类型大小之和

注意,结构体的大小可能会受到编译器的优化和对齐规则的影响,编译器可能会在结构体中插入一些额外的填充字节以对齐结构体的成员变量,以提高内存访问效率。因此,结构体的实际大小可能会大于成员变量大小的总和,如果你需要确切地了解结构体的内存布局和对齐方式,可以使用 offsetof 宏和 attribute((packed)) 属性等进一步控制和查询结构体的大小和对齐方式。



C语言 共同体

共用体是一种特殊的数据类型,允许您在相同的内存位置存储不同的数据类型

在共用体定义的末尾,最后一个分号之前,您可以指定一个或多个共用体变量,这是可选的

共用体占用的内存应足够存储共用体中最大的成员

您可以定义一个带有多成员的共用体,但是任何时候只能有一个成员带有值

#include <stdio.h>
#include <string.h>
 
union Data
{
   int i;
   float f;
   char  str[20];
};
 
int main( )
{
   union Data data;        
 
   printf( "Memory size occupied by data : %d\n", sizeof(data));
 
   return 0;
}
​
// 所以说这个共同体的内存空间大小的话就是我们的: 20

访问共同体的成员

访问的方法就是实现的是我们的 . 操作符来实现访问成员变量

#include <stdio.h>
#include <string.h>
 
union Data
{
   int i;
   float f;
   char  str[20];
};
 
int main( )
{
   union Data data;        
 
   data.i = 10;
   printf( "data.i : %d\n", data.i);
   
   data.f = 220.5;
   printf( "data.f : %f\n", data.f);
   
   strcpy( data.str, "C Programming");
   printf( "data.str : %s\n", data.str);
 
   return 0;
}

但是需要注意的是。共同体最终拥有值的是我们的最大的存储单位,其他的成员的值会被损坏,导致无法正常显示



C语言 typedef 的使用

C 语言提供了 typedef 关键字,您可以使用它来为类型取一个新的名字。下面的实例为单字节数字定义了一个术语 BYTE

可以使用 typedef 来为用户自定义的数据类型取一个新的名字

typedef struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
} Book;

typedef 仅限于为类型定义符号名称, #define 不仅可以为类型定义别名,也能为数值定义别名,比如您可以定义 1 为 ONE

typedef 是由编译器执行解释的, #define 语句是由预编译器进行处理的。