C语言初阶【字符串和数组】6700字解析

         随着学习的进行我们的“野心”越来越大,常量和变量只能存放一个数据,这已经不能满足我们的需求,今天我们将引入字符串的数组,相对于前两位来说它们可都是重量级的存在,是多个变量的集合,既然是集合,那么它们之中的每个元素必然有相同的属性,即它之中的元素都是同一类型的;拿字符串举例,它里面全是字符型的元素,而数组中的元素也是同一类型。接下来我们将正式开始今天的内容。

一、字符串

(一)字符串的定义

在C语言中,字符串是以字符数组的形式表示的,以空字符('\0')结尾。以下是C语言中字符串的定义和操作示例:

1.使用双引号定义字符串:

char my_string[] = "Hello, World!";
//******************************************************************
//char         代表字符类型
//my_string    是该字符数组的名称
//一对方括号是代表my_string是一个数组,在括号中输入数字可以控制数组的大小
//等号用于改变字符数组的内容
//双引号(必须是英文双引号)内的内容就是字符串中存放的数据
//最后不要忘记用分号(英文分号)结尾
//******************************************************************

 如果有同学对数组的概念不太理解可以先保留问题,继续往下看,后续会有涉及的。

2.使用单引号定义单个字符:

char my_char = 'H';

在C语言中,字符串可以通过字符数组来表示,每个字符占用一个字节的内存空间。字符串的结尾必须是空字符('\0'),以便标记字符串的结束。

(二)字符串的初始化

字符串同我们之前讲解的变量一样也是容器的一种,变量常量存放单个数据,而字符串就是存放多个数据,这些数据的类型是字符型(char类型)。在C语言中,如果字符数组没有显式初始化,则其大小和内容取决于数组所在的上下文。

1、完全初始化:

一个完整的字符串需要大小和对应的内容,经过上部分的介绍,相信大家可以很快理解完全初始化的格式:

char FullyInitialized_String[6] = "Hello!";

2、不完全初始化:

不完全初始化就是字符串的两个元素任意丢失其中一个:

char FullyInitialized_String1[] = "Hello!";
char FullyInitialized_String3[6];

 在接下来讲解之前大家可以先在思考一下两个字符串内容分别是什么呢?大小又是多少呢?

一下内容是我从VS2020中调试监视窗口中得来的结果:

 可以看到String1的大小为7,除去我们给它的Hello!之外还多出了一个斜杠零,这是为什么呢?等会儿我们会在数组部分进行解答。String3则是大小为6,和我们给它的值一样,但是其内容全是随机值,显示出来的内容是“烫烫烫,”可以说是意料之中,因为我们创建后并没有对其进行任何操作。

3、不初始化

如果字符数组在全局作用域中或者局部作用域中声明,但没有显式初始化,则数组的大小会根据初始化时提供的初始值来确定,如果没有提供初始值,则大小为0。数组的内容将根据编译器和操作系统的实现而定,通常会被初始化为0或者随机值。

此部分内容为扩展,不作为讲解内容:

如果使用malloc()calloc()等动态内存分配函数来分配字符数组,而没有对其进行初始化,则数组的内容也是未定义的,可能包含随机值或者垃圾值,这一切根据环境的不同会有差别。

(三)字符串的输出

        当我们在程序中使用字符串时,我们可以通过输出函数将字符串显示在屏幕上。在C语言中,我们通常使用printf()函数来输出字符串。下面是一个简单的例子:

#include <stdio.h>

int main() {
    char my_string[] = "Hello, World!";

    printf("The string is: %s\n", my_string);

    return 0;
}

        在这个例子中,我们首先定义了一个名为my_string的字符数组,并将字符串"Hello, World!"赋值给它。然后,我们使用printf()函数来输出这个字符串。在printf()函数中,和之前输出整形不同,这里我们使用%s格式化符号来表示要输出的是一个字符串,然后将my_string作为参数传递给printf()函数。

当我们运行这个程序时,屏幕上将会显示:

The string is: Hello, World!

 这样,我们就可以通过printf()函数将字符串输出到屏幕上,方便我们查看程序中的字符串内容。

(四)测量字符串的长度和大小

说到测量字符串的大小和长度就不得不提及C语言中的函数和一个运算符:

sizeof();
strlen();

strlen也就是 string length的缩写, 它的作用可想而知,就是测量字符串长度用的,它是C语言库文件中的字符串库<string.h>中的函数,使用时要包含下列这个头文件:

#include <string.h>

1、测量字符串的长度

Get string length

Returns the length of the C string str.

The length of a C string is determined by the terminating null-character: A C string is as long as the number of characters between the beginning of the string and the terminating null character (without including the terminating null character itself).

This should not be confused with the size of the array that holds the string. For example:

这是网站(strlen - C++ Reference (cplusplus.com))的解释,意思是strlen这个函数在遇到终止字符时就会停止计算,终止字符指的就是“\0”,而且计算的数值不会包括"\0",且当一个初始化大小为100的字符数组指初始化了前11个数据时,其读取的字符数组长度就是11,总而言之,它测量的是字符串的有效长度,所以我们要在这里使用到它。

//以下为网站示例代码
/* strlen example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char szInput[256];
  printf ("Enter a sentence: ");
  gets (szInput);
  printf ("The sentence entered is %u characters long.\n",(unsigned)strlen(szInput));
  return 0;
}

2、测量字符串的大小

        在C语言中,`sizeof`是一个运算符,用于获取数据类型或变量的大小(以字节为单位)。`sizeof`运算符不是一个函数,而是由编译器直接处理的。因此,`sizeof`并不是由特定的函数库提供,而是由编译器实现。

在C语言标准中,并没有要求将`sizeof`运算符实现为一个函数,因此它通常是作为编译器的一部分来处理的。总而言之,编译器会根据数据类型或变量来计算其大小,并在编译时将`sizeof`表达式替换为相应的大小值。        

        在C/C++中,sizeof操作符用于获取数据类型或变量的字节大小。sizeof操作符是在编译时计算的,而不是在运行时计算的,因此不会增加程序的运行时间开销。

sizeof操作符的底层逻辑可以简单描述为:
1. 对于基本数据类型(如int、char、float等),sizeof操作符返回该数据类型的字节大小。
2. 对于数组,sizeof操作符返回整个数组占用的字节大小。
3. 对于指针,sizeof操作符返回指针本身的字节大小,而不是指向的对象的大小。
4. 对于结构体和类,sizeof操作符返回整个结构体或类占用的字节大小,包括所有成员变量的大小以及可能的填充字节。

在实际编程中,sizeof操作符通常用于动态内存分配(如malloc函数)、数组操作、结构体内存布局等场景,以确保程序在处理内存时能够正确地计算数据的大小。

        对于sizeof我们后续还有更深度的辨析,我们在这里浅尝辄止。

3、最终结果(strlen和sizeof在测量字符串时的差距)

示例代码:

#include <string.h>
#include <stdio.h>
int main(void)
{
	char my_string1[] = "HelloWorld!";
	printf("my_string1 The value of Strlen:%d\n", strlen(my_string1));
	printf("my_string1 The value of Sizeof:%d\n", sizeof(my_string1));

	char my_string2[] = {'H','e','l','l','o','W','o','r','l','d','!'};
	printf("my_string2 The value of Strlen:%d\n", strlen(my_string2));
	printf("my_string2 The value of Sizeof:%d\n", sizeof(my_string2));

	char my_string3[] = { 'H','e','l','l','o','\0','W','o','r','l','d','!' };
	printf("my_string3 The value of Strlen:%d\n", strlen(my_string3));
	printf("my_string3 The value of Sizeof:%d\n", sizeof(my_string3));

	char my_string4[] = { 'H','e','l','l','o','W','o','r','l','d','!','\0'};
	printf("my_string4 The value of Strlen:%d\n", strlen(my_string4));
	printf("my_string4 The value of Sizeof:%d\n", sizeof(my_string4));
}

 运行结果如下:

现在来逐一解释一下为什么会出现这种结果:

首先,针对my_string1出现Strlen结果为11Sizeof结果为12很正常,第一个字符串属于正常生成,内有11个字符并附带一个结束标志“反斜杠零”,“反斜杠零”并不计算入字符串本身长度,所以返回结果为11,但是“反斜杠零”仍然属于字符串包含的内容,所以根据sizeof的算法,它是占用空间的,所以sizeof返回的是12。

再来看第二个,strlen返回值竟然相差如此之远,有点出乎我们预料,明明我们是一个值一个值自己输进去的啊?为什么还是会出错呢?经过仔细检查可以发现sizeof的返回值比上一个字符串少一,原来是我们丢失了“斜杠零”,如果我们一个字符一个字符的自己输入最后的斜杠零是不会自动补全的,但是我们用双引号直接生成字符串最后的终止字符斜杠零会自动补全,疑问解决了,但是141这个长度是怎么来的呢?其实这个是随机值,因为strlen遇到终止字符斜杠零才会停止,所以说这个值的大小就取决于内存下一个零的位置了,可能你的实验结果就和我的完全不同。

第三个数组,sizeof返回值和第一个完全一样,但是由于我将反斜杠零放在了中间部分,strlen在碰到后就不再向下计算返回的就是斜杠零之前的数据个数,也就是5.

第四个可以说是正确初始化的另一种写法,取得的值和第一组完全相同,到此为止你就完全理解它们之间的差距了。



注(小知识点)

局部变量和全局变量名称相同的话

采用局部优先原则

 二、数组

        在数学中,数组通常指的是一个有序的集合,其中的元素按照一定的顺序排列。数组可以是一维的、二维的甚至更高维的。在编程中,数组是一种数据结构,用来存储一组相同类型的数据。数组的具体定义方法取决于编程语言,我们今天主要分享再C语言前提下的数组。

(一)数组的定义

在C语言中数组定义方法如下:

int arr1[5]; // 定义一个长度为5的整型数组
char arr2[6];
long arr3[7];
long long arr4[8];
float arr5[9];

 具体格式就是:数组存放的元素类型+数组名+方括号内写数组数据个数;最后以分号结尾

(二)数组的的初始化

数组的初始化在字符串部分已经演示过了,总结就是定义字符串后加等号,等号后面接大括号(花括号),花括号内放置初始化内容,元素和元素之间用逗号隔开,如果初始化的内容是字符,不要忘记每个字符都要用单引号括起来,这样它才是字符型的数据,最后用分号结尾。注意,如果使用了固定的数组大小,那么创建的数据不能超过给定的大小。

这里有一点需要注意:

初始化大小必须为常量和变长数组:

如果你在初始化数组的过程中使用了n或者j这种没有定值的变量,那么编译器可能会报错,但是还有另外一种情况,那就是变长数组;

在C语言中,变长数组(Variable Length Arrays,简称VLA)是指数组的长度在运行时确定,而不是在编译时确定。这意味着可以在程序运行时根据需要动态地分配数组的长度。变长数组是C99标准中引入的特性,因此只有支持C99标准的编译器才能够使用变长数组。

变长数组的定义方式与普通数组类似,但是可以使用变量来指定数组的长度。以下是一个简单的示例:

void Function(int n) {
    int arr[n]; // 定义一个长度为n的变长数组
    // 可以在这里使用arr数组进行操作
}

在上面的示例中,n是一个在运行时确定的长度,根据调用 exampleFunction时传入的参数值来决定数组 arr的长度。

需要注意的是,变长数组的长度必须是一个正整数,不能是负数或者零。另外,变长数组通常是在栈上分配内存的,因此可能会受到栈大小的限制。

使用变长数组可以更灵活地处理需要在运行时确定长度的数组情况,但也需要注意内存管理和性能方面的考虑。在使用变长数组时,建议谨慎考虑其适用性和可能的限制。
 

(三)数组的访问

我们既然能创建数组并且在其中存放数据,那么我们怎样将其中的数据读取出来呢?

在C语言中,数组是通过下标(索引)来访问对应的数据元素的。数组就相当于一个酒店,每个数据占用一个房间,那个创建数组的方括号其实另有用途,它可以是一个房管,你只需要告诉它对应的房间号,它就可以带你去对应的房间取对应的数据,数组的下标从0开始,即第一个元素的下标为0,第二个元素的下标为1,依此类推。通过指定数组名和下标的方式,可以访问数组中特定位置的数据。具体为什么从0开始,祖师爷规定的,咱也不知道,咱也不敢问,就这么记住就行了,好回归正题;

创建数组的那个方括号其实另有其名:

        在C语言中,数组的方括号 [] 实际上被称为下标运算符。下标运算符用于指定数组中的特定元素,通过在数组名后面加上方括号并填入下标值来访问数组中的元素。

        和下标运算符 [] 对应的是指针运算符 *。指针运算符用于声明指针变量和进行指针操作,可以通过指针来访问内存中的数据。指针和数组在C语言中有着密切的关系,通过指针可以实现对数组元素的访问和操作。

下面是一个简单的示例,展示了如何定义数组并访问数组中的数据:

#include <stdio.h>

int main() {
    int arr[5] = {10, 20, 30, 40, 50}; // 定义一个包含5个元素的整型数组

    // 访问数组中的数据
    printf("第一个元素:%d\n", arr[0]);  // 访问第一个元素,下标为0
    printf("第三个元素:%d\n", arr[2]);  // 访问第三个元素,下标为2

    // 修改数组中的数据
    arr[1] = 200; // 修改第二个元素的值为200

    // 打印修改后的数组
    for (int i = 0; i < 5; i++) {
        printf("arr[%d] = %d\n", i, arr[i]);
    }

    return 0;
}

在上面的示例中,我们定义了一个包含5个整型元素的数组 arr,然后通过下标访问数组中的数据。可以使用 arr[i] 的方式来访问数组中下标为 i 的元素,并且可以通过下标赋值的方式修改数组中的数据。

通过数组下标访问数据是数组的一种基本操作,也是C语言中处理数组的重要方式。在实际编程中,我们经常会利用数组下标来遍历数组、访问特定位置的数据或者修改数组中的元素。

        这次内容有些多,用了两天时间才写完,感谢大家观看,如果内容能解决你一些疑惑,或者是能给你带来深入思考还请帮忙点赞推荐,如果觉得可以用于学习复习可以把文章放入收藏夹,最后再次感谢各位支持,我们下一个博文再见。

  • 11
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

寒雒

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

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

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

打赏作者

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

抵扣说明:

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

余额充值