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

文章目录

  • 1. 字符串相关
  • 2. 结构体相关
    • 2.1 定义结构体
    • 2.2 结构体变量的初始化
    • 2.3 访问结构成员
    • 2.4 结构作为函数参数
    • 2.5 指向结构的指针
    • 2.6 结构体大小的计算

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)) 属性等进一步控制和查询结构体的大小和对齐方式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/89672.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

1.centos7 安装显卡驱动、cuda、cudnn

安装conda 参考 python包 2.安装conda python库-CSDN博客3.Cenots Swin-Transformer-Object-Detection环境配置-CSDN博客 1.安装显卡驱动 步骤1&#xff1a;安装依赖 yum -y install kernel-devel yum -y install epel-release yum -y install gcc 步骤2&#xff1a;查询显…

[滴水逆向]03-12 pe头字段说明课后作业,输出pe结构

#include <iostream> #include <windows.h> using namespace std; #pragma warning(disable:4996) //DOC结构 typedef struct _DOC_HEADER {WORD e_magic;WORD e_cblp;WORD e_cp;WORD e_crlc;WORD e_cparhar;WORD e_minalloc;WORD e_maxalloc;WORD e_ss;WO…

CentOS 7下载安装MySQL 5.7以及连接虚拟机CentOS 7数据库教程

## CentOS 7下载安装MySQL 5.7以及连接虚拟机CentOS 7数据库教程 文章目录 ## [CentOS 7下载安装MySQL 5.7以及连接虚拟机CentOS 7数据库教程](https://my.oschina.net/u/3986411/blog/4714780) 通过如下命令查看mariadb的安装包 rpm -qa | grep mariadb通过如下命令卸载mariad…

Java基础简单整理

文章目录 Java语言具有以下特点&#xff1a;Java SE vs Java EEJVM vs JDK vs JRE为什么说 Java 语言编译与解释并存&#xff1f;Java 和 C 的区别?Java注释用法&#xff1a;Java标识符Java基本数据类型链接Java字符串类型链接基本类型和包装类型的区别&#xff1f;静态方法为…

flutter 递归

if (!Global.wsImMessageQueueState) {Global.wsImMessageQueueState true;startProcessingMessageQueue(true);//开始执行}startProcessingMessageQueue(bool isExistMessage) {if (isExistMessage) {if (Global.wsImMessageQueue.isNotEmpty) {PrintUtil.prints(WsIm消息队列…

可以动态改变刻度背景色的车速仪表盘

最近做的项目的主页面需要用到一个仪表盘来动态显示车速&#xff0c;同时改变对应的背景色 仪表盘 开始是想着使用echarts&#xff0c;修修改改拿来用&#xff0c;但是人家客户有规定&#xff0c;必须搞个差不多的&#xff0c;那没办法&#xff0c;自 己动手搞个吧 截图如下&am…

9-4 查找星期 (15分)

本题要求实现函数&#xff0c;可以根据下表查找到星期&#xff0c;返回对应的序号。 序号 星期 0 Sunday 1 Monday 2 Tuesday 3 Wednesday 4 Thursday 5 Friday 6 Saturday函数接口定义&#xff1a; int getindex( char *s );函数getindex应返回字符串s序号。如果传入的参数…

SDI-12协议与STM32 进行uart通信

场景是用stm32与一款温湿度传感器通信&#xff0c;不过是基于SDI-12协议&#xff0c;SDI-12时序和UART类似&#xff0c;故采用UART传输&#xff0c;原理图如下 其中DIR_OUT_SDI是一个IO引脚&#xff0c;控制UART_TX_SDI是否使能&#xff0c;U10是三态门IC&#xff0c;即拉低DIR…

AI文章,AI文章生成工具

在互联网时代&#xff0c;随着信息爆炸式增长&#xff0c;文章的需求愈发旺盛。从博客、新闻、社交媒体到企业宣传&#xff0c;文字作为传达信息、吸引受众的工具变得愈发重要。但问题是&#xff0c;对于很多人来说&#xff0c;创作一篇高质量的文章并不容易。时间、创意、写作…

Qt获取屏幕(桌面)的大小或分辨率

Qt提供QDesktopWidget和QScreen两个类获取屏幕大小。Qt5开始&#xff0c;QDesktopWidget官方不建议使用&#xff0c;改为QScreen。Qt 6.0 及之后版本&#xff0c;QDesktopWidget 已从QtWidgets 模块中被彻底移除。 QDesktopWidget QDesktopWidget 提供了详细的位置信息&#…

【c语言的函数指针介绍】

C语言中的函数指针是一种特殊的指针&#xff0c;它指向函数而不是数据。函数指针允许你在运行时动态地选择要调用的函数&#xff0c;这使得你可以根据需要在不同的函数之间切换&#xff0c;或者将函数作为参数传递给其他函数。函数指针的声明和使用如下&#xff1a; 声明函数指…

Tomcat多实例、负载均衡、动静分离

Tomcat多实例部署 安装jdk [rootlocalhost ~]#systemctl stop firewalld.service [rootlocalhost ~]#setenforce 0 [rootlocalhost ~]#cd /opt [rootlocalhost opt]#ls apache-tomcat-8.5.16.tar.gz jdk-8u91-linux-x64.tar.gz rh [rootlocalhost opt]#tar xf jdk-8u91-linu…

荣耀时刻!2023抖音电商作者峰会为优质直播间和卓越生态伙伴颁奖

9月27日&#xff0c;抖音电商在上海举行了以“向新成长”为主题的2023抖音电商作者峰会&#xff0c;并现场颁发了荣誉奖项。抖音电商优质直播间以及践行抖音电商作者精神四个维度的年度荣誉一一揭晓。 过去一年&#xff0c;数百万作者与众多品牌商家、MCN机构和精选联盟服务商…

RockyLinux9.2 网卡配置和nmcli、nmtui命令的使用

NetworkManager NetworkManager 是一个标准的Linux网络配置工具套件&#xff0c;支持服务器&#xff0c;也支持桌面环境&#xff0c; 发展到如今&#xff0c;绝大多数流行的发行版都支持它。 这套网络配置工具适用于 Rocky Linux 8 及更高版本。 nmcli是nm的命令行工具、nmt…

面试题库(十):NIO和Netty面试题

NIO 阐述 NIO原理&#xff1f;BIO/NIO/AIO有什么区别&#xff1f;有那些实现&#xff1f;讲讲NIO的原理与实现&#xff1f;NIO用到了哪个经典技术思想&#xff1f;JDK1.8中NIO有做什么优化了解多路复用机制 常见问题 同步阻塞、同步非阻塞、异步的区别&#xff1f;select、pol…

FireDAC 同一个查询语句中有join, 同时更新多个数据表设置

dfdquery.sql.text : select a.*, b.* from a left join b on a.id b.id fdqery.cacheupdate : true; //这样可更方便回退多表错误 fdquery.updateoptions.updatenobasefields : true; //副表字段可以编辑 fdquery.updateobject : TFdUpdateSqL; 或者fdquery.onupdaterec…

Java研发规范

文章目录 一、code规范二、需求跟进实践总结**需求分析****设计****开发** 三、幂等&一致性四、代码规范五、项目流程5.1 详设汇总5.2 排期5.3 数据组影响5.4 全流程SOP预案5.5 每日测试进度汇总5.6 灰度方案5.7 上线计划5.8 风险评估 一、code规范 【强制】POJO类中布尔类…

打造卓越摄影作品,尽享专业级编辑体验——DxO PhotoLab 7 for Mac

DxO PhotoLab 7 for Mac 是一款功能强大的专业照片编辑软件&#xff0c;为摄影爱好者和专业摄影师提供了优秀的工具和功能&#xff0c;让您能够轻松打造卓越的摄影作品并实现专业级的编辑效果。 DxO PhotoLab 7 提供了一套先进的图像处理算法&#xff0c;能够准确地还原照片的…

ORACLE 在内存管理机制上的演变和进化

截止目前&#xff0c;计算机内存仍然被认为是我们可以获得的最快速度的物理存储设备。 将频繁访问的数据尽可能地置于内存中&#xff0c;已成为当前各种软件和应用程序提高数据访问性能&#xff0c;减少访问延迟的最为有效的途径。 然而&#xff0c;内存作为关键的计算资源&am…

K8S-存储卷,pv,pvc

pv&#xff0c;pvc 一、emptyDir存储卷1.概述2.示例 二、hostPath存储卷1.概述 三、nfs共享存储卷1.在stor01节点上安装nfs&#xff0c;并配置nfs服务2.master节点操作3.在nfs服务器上创建index.html4.master节点操作 四、PVC 和 PV1.概述2.PV和PVC之间的相互作用遵循的生命周期…