从零开始探索C语言(十)----字符串和结构体

1. 字符串相关

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

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

其实,我们不需要把 null 字符放在字符串常量的末尾。C 编译器会在初始化数组时,自动把 \0 放在字符串的末尾。
实例:

#include <stdio.h>

int main ()
{
//   char site[6] = {'H', 'E', 'L', 'L', 'O', '\0'};
   char site[6] = {'H', 'E', 'L', 'L', 'O'};

   printf("C语言字符串: %s\n", site );

   return 0;
}

编译输出结果:

C语言字符串: HELLO

C 中有大量操作字符串的函数:

  1. strcpy(s1, s2);
    复制字符串 s2 到字符串 s1。
  2. strcat(s1, s2);
    连接字符串 s2 到字符串 s1 的末尾。
  3. strlen(s1);
    返回字符串 s1 的长度。
  4. strcmp(s1, s2);
    如果 s1 和 s2 是相同的,则返回 0;如果 s1<s2 则返回小于 0;如果 s1>s2 则返回大于 0。
  5. strchr(s1, ch);
    返回一个指针,指向字符串 s1 中字符 ch 的第一次出现的位置。
  6. strstr(s1, s2);
    返回一个指针,指向字符串 s1 中字符串 s2 的第一次出现的位置。

示例:

#include <stdio.h>
#include <string.h>
 
int main ()
{
   char str1[14] = "hello";
   char str2[14] = "world";
   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;
}

程序编译执行结果;

strcpy( str3, str1) :  hello
strcat( str1, str2):   helloworld
strlen(str1) :  10

2. 结构体相关

C语言中的结构体(Structures)是一种用户自定义的数据类型,允许你组合不同类型的变量,以创建一个包含多个成员的复合数据类型。结构体的每个成员可以是不同的数据类型,例如整数、字符、浮点数等。结构体用于组织和表示具有相关性的数据。

实例:

#include <stdio.h>
#include <string.h>

int main(){

    // 定义结构体
    struct Student {
        char name[50];
        int roll_number;
        float marks;
    };

    // 声明结构体变量
    struct Student student1;
    struct Student student2;

    // 初始化结构体成员
    strcpy(student1.name, "John");
    student1.roll_number = 101;
    student1.marks = 95.5;

    // 访问结构体成员
    printf("Student 1:\n");
    printf("Name: %s\n", student1.name);
    printf("Roll Number: %d\n", student1.roll_number);
    printf("Marks: %.2f\n", student1.marks);

    // 可以将结构体变量作为函数参数传递,也可以从函数中返回结构体

    return 0;


}

编译运行结果:

Student 1:
Name: John
Roll Number: 101
Marks: 95.50

2.1 定义结构体

在C语言中,可以使用struct关键字来定义一个结构体。
结构体定义的基本语法如下:

struct 结构体名称 {
    // 结构体成员声明
    数据类型 成员名称1;
    数据类型 成员名称2;
    // ...
    数据类型 成员名称N;
}结构变量;

一般情况下 结构体名称(标签)结构体成员结构变量部分至少要出现 2 个。

以下是一个示例,定义一个名为Person的结构体,其中包含姓名(字符串类型)和年龄(整数类型)两个成员:

struct Person {
    char name[50];
    int age;
};

这样,你就创建了一个名为Person的结构体,其中有两个成员:nameage

接下来,你可以声明结构体变量并初始化它们。这是如何声明和初始化Person结构体变量的示例:

struct Person person1; // 声明一个名为person1的Person结构体变量
struct Person person2; // 声明一个名为person2的Person结构体变量

// 初始化结构体成员
strcpy(person1.name, "Alice"); // 使用strcpy函数将字符串赋值给name成员
person1.age = 25;

// 初始化另一个结构体变量
strcpy(person2.name, "Bob");
person2.age = 30;

你可以使用.运算符来访问和修改结构体的成员。例如:

printf("Name: %s\n", person1.name); // 访问name成员
printf("Age: %d\n", person1.age);   // 访问age成员

person2.age = 31; // 修改age成员的值

这些是定义和使用C语言结构体的基本步骤。

结构体允许你组织和存储不同类型的数据作为一个单独的实体,这在处理复杂的数据结构时非常有用。

上面说过 一般情况下 结构体名称(标签)结构体成员结构变量部分至少要出现 2 个。

请看以下实例了解:

//此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c
//同时又声明了结构体变量s1
//这个结构体并没有标明其标签
struct
{
    int a;
    char b;
    double c;
} s1;

//此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c
//结构体的标签被命名为SIMPLE,没有声明变量
struct SIMPLE
{
    int a;
    char b;
    double c;
};
//用SIMPLE标签的结构体,另外声明了变量t1、t2、t3
struct SIMPLE t1, t2[20], *t3;

//也可以用typedef创建新类型
typedef struct
{
    int a;
    char b;
    double c;
} Simple2;
//现在可以用Simple2作为类型声明新的结构体变量
Simple2 u1, u2[20], *u3;

在上面的声明中,第一个和第二声明被编译器当作两个完全不同的类型,即使他们的成员列表是一样的,如果令 t3=&s1,则是非法的。

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

//此结构体的声明包含了其他的结构体
struct COMPLEX
{
    char string[100];
    struct SIMPLE a;
};

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




如果两个结构体互相包含,则需要对其中一个结构体进行不完整声明,如下所示:

struct B;    //对结构体B进行不完整声明

//结构体A中包含指向结构体B的指针
struct A
{
    struct B *partner;
    //other members;
};

//结构体B中包含指向结构体A的指针,在A声明完后,B也随之进行声明
struct B
{
    struct A *partner;
    //other members;
};

2.2 结构体变量的初始化

和其它类型变量一样,对结构体变量可以在定义时指定初始值。

实例

#include <stdio.h>

struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
} book = {"C 语言", "SRTUCT", "编程语言", 123456};

int main()
{
    printf("title : %s\nauthor: %s\nsubject: %s\nbook_id: %d\n", book.title, book.author, book.subject, book.book_id);
}

执行输出结果为:

title : C 语言   
author: SRTUCT   
subject: 编程语言
book_id: 123456  

2.3 访问结构成员

为了访问结构体的成员,我们使用成员访问运算符.
成员访问运算符是结构变量名称和我们要访问的结构成员之间的一个句号。
可以使用 struct 关键字来定义结构类型的变量。

下面的实例演示了结构的用法:

#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, "笑傲江湖");
   strcpy( Book1.author, "金庸");
   strcpy( Book1.subject, "武侠");
   Book1.book_id = 1;

   /* Book2 详述 */
   strcpy( Book2.title, "我欲封天");
   strcpy( Book2.author, "耳根");
   strcpy( Book2.subject, "玄幻");
   Book2.book_id = 2;
 
   /* 输出 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;
}

当上面的代码被编译和执行时,它会产生下列结果:

Book 1 title : 笑傲江湖
Book 1 author : 金庸   
Book 1 subject : 武侠  
Book 1 book_id : 1     
Book 2 title : 我欲封天
Book 2 author : 耳根   
Book 2 subject : 玄幻  
Book 2 book_id : 2  

2.4 结构作为函数参数

可以把结构作为函数参数,传参方式与其他类型的变量或指针类似。
使用上面实例中的方式来访问结构变量实例:

#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, "笑傲江湖");
   strcpy( Book1.author, "金庸");
   strcpy( Book1.subject, "武侠");
   Book1.book_id = 1;

   /* Book2 详述 */
   strcpy( Book2.title, "我欲封天");
   strcpy( Book2.author, "耳根");
   strcpy( Book2.subject, "玄幻");
   Book2.book_id = 2;
 
   /* 输出 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);
}

当上面的代码被编译和执行时,它会产生下列结果:

Book title : 笑傲江湖
Book author : 金庸   
Book subject : 武侠  
Book book_id : 1     
Book title : 我欲封天
Book author : 耳根   
Book subject : 玄幻
Book book_id : 2

2.5 指向结构的指针

也可以定义指向结构的指针,方式与定义指向其他类型变量的指针相似,如下所示:

struct Books *struct_pointer;

现在,你可以在上述定义的指针变量中存储结构变量的地址。

为了查找结构变量的地址,请把 & 运算符放在结构名称的前面,如下所示:

struct_pointer = &Book1;

为了使用指向该结构的指针访问结构的成员,必须使用 -> 运算符,如下所示:

struct_pointer->title;

让我们使用结构指针来重写上面的实例,这将有助于您理解结构指针的概念:

实例

#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, "笑傲江湖");
   strcpy( Book1.author, "金庸");
   strcpy( Book1.subject, "武侠");
   Book1.book_id = 1;

   /* Book2 详述 */
   strcpy( Book2.title, "我欲封天");
   strcpy( Book2.author, "耳根");
   strcpy( Book2.subject, "玄幻");
   Book2.book_id = 2;
 
   /* 通过传 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);
}

当上面的代码被编译和执行时,它会产生下列结果:

Book title : 笑傲江湖
Book author : 金庸   
Book subject : 武侠  
Book book_id : 1     
Book title : 我欲封天
Book author : 耳根   
Book subject : 玄幻  
Book book_id : 2

2.6 结构体大小的计算

C 语言中,我们可以使用 sizeof 运算符来计算结构体的大小,sizeof 返回的是给定类型或变量的字节大小。

对于结构体,sizeof 将返回结构体的总字节数,包括所有成员变量的大小以及可能的填充字节。

以下实例演示了如何计算结构体的大小:

实例

#include <stdio.h>

struct Person {
    char name[20];
    int age;
    float height;
};

int main() {
    struct Person person;
    printf("结构体 Person 大小为: %zu 字节\n", sizeof(person));
    return 0;
}

以上实例中,我们定义了一个名为 Person 的结构体,它包含了一个字符数组 name、一个整数 age 和一个浮点数 height。

在 main 函数中,我们声明了一个 Person 类型的变量 person,然后使用 sizeof 运算符来获取 person 结构体的大小。

最后,我们使用 printf 函数打印出结构体的大小,输出结果如下:

结构体 Person 大小为: 28 字节

struct Person 包含三个成员:

name 是一个字符数组,占据20个字节。
age 是一个整数,通常占据4个字节(在大多数系统上)。
height 是一个浮点数,通常占据4个字节(在大多数系统上)。
因此,根据这些成员的大小和对齐规则,struct Person 的总大小为20字节(name) + 4字节(age) + 4字节(height) = 28字节。

注意,在C语言中,结构体的大小由其成员的大小和对齐方式决定。每个成员都需要在内存中占据一定的字节,并且为了数据的高效存取,编译器通常会根据硬件架构和对齐规则来决定如何排列结构体的成员

因此,结构体的实际大小可能会大于成员变量大小的总和,如果你需要确切地了解结构体的内存布局和对齐方式,可以使用 offsetof 宏和 attribute((packed)) 属性等进一步控制和查询结构体的大小和对齐方式。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

冰履踏青云

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

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

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

打赏作者

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

抵扣说明:

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

余额充值