C语言总结七:表示字符串的两种方式—字符数组与字符串指针详细总结

本文详细介绍了C语言中表示字符串的两种方式:字符数组和字符串指针,包括它们的定义、初始化、访问方式、区别以及字符串处理函数。字符数组和字符串指针在内存中的存储区域不同,字符数组可以修改,字符串指针不可。字符串处理函数如strlen、strcpy等在实际开发中非常重要,需要理解其工作原理和注意事项。
摘要由CSDN通过智能技术生成

       C语言并没有专用的字符串数据类型来存储一个字符串,字符串是C语言中重要的一块基本理论,知道如何使用字符串和掌握好字符串可减少实际开发经常出现的错误,本篇博客详细全面总结字符数组与字符串的定义及基本的使用方法,以及常用的库函数和针对内存操作的内存函数。

目录

一、字符数组与字符串

1、字符数组的定义与初始化

 2、字符串的定义

3、二者的区别(面试)

二、字符串的访问方式/使用

1、下标引用操作符访问(同整型数组)/或者%s直接输出整个字符串(字符串特有方式)

2、通过指针自增或者指针+偏移量访问

三、字符串的输入

四、字符串转换函数(atoi和itoa函数)编码实现

五、常用的字符处理函数(库函数)

1. int tolower(int c);

2. int toupper(int c);

六、常用字符串处理函数(库函数)理解编码实现

七、内存操作函数,编码实现


一、字符数组与字符串

       C语言存储字符,其实是存储字符所对应的ASCII码,因此字符可以以%c或者%d输出均可以,需要作为常识记住的是:字符'0'对应的ASCII码为48,字符'A'对应的ASCII码为65,字符'Z'对应的ASCII码为90,字符'a'对应的ASCII码为97,字符'z'对应的ASCII码为122; 字符类型char占用1个字节。

      用来存放字符的数组称为字符数组,字符数组实际上是一系列字符的集合,也就是字符串,C语言通常有两种表示字符串的方法:

第一种:定义一个字符数组;char  str[]="helloworld";     

第二种:字符串指针;    const  char * str="helloworld"; 这种方式不可通过对字符指针解引用进行修改字符串,因为字符串常量不可修改!

      这二者都是使用字符串常量对其进行初始化,从指针角度理解,本质一样,不论是字符数组,还是字符指针,str都代表字符串首字符的起始地址。区别在于:字符数组名为常量,常量不可以作左值!字符指针是变量,但是字符指针不可以进行解引用再修改值。

1、字符数组的定义与初始化

字符数组的定义:    

       C语言字符数组定义如下:char 数组名 [数组长度];与普通整型数组相同。只是在初始化方面有所区别。

字符数组的初始化:

      方式1:与普通整型数组初始化方式相同,花括号括起来,单个字符用单引号;

第1种:全部元素初始化,可以省略字符数组的长度(编译器自动确定)。

       char  str[5]={'a','b','c','d','e'};   或者  char  str[]={'a','b','c','d','e'};

第2种:未进行初始化,局部数组声明存储在栈区,此时字符数组的元素为随机值。

       char  str[5];

第3种:部分元素进行初始化,那么未初始化的元素默认为默认值'\0'

      char  str[5]={'a','b','c'}              str[3]='\0'           str[4]='\0'

    

     方式2:字符数组特有的初始化形式,即C语言规定,可以将字符串(双引号括起来)直接赋值给字符数组;

第1种:char str [6]={"abcde"};     或者为了简便省略花括号:char str [6]="abcde"; 需要注意的是:这里的字符数组的长度为6,这是为了存储'\0',因为用双引号" "包围的字符串会在字符串末尾自动添加'\0',因此,当用字符数组存储字符串时,要注意'\0',要为'\0'留个位置,这意味着,字符数组的长度至少要比字符串的长度加1。因此为了开发方便,这种方式常常不指定数组的长度。

第2种:char str []="abcde";(实际开发常用的方式)

这里有个坑需要注意:字符数组只有在定义的时候,才能将整个字符串一次性地赋值给它。

      char  str[6];

      str ="abcde" ;         //错误     字符数组,他也是数组,数组名是字符串的首字符的起始地址,是一个常量,无法作为左值!因为左值必须是变量。

字符串结束标志(重点!!!)

        字符串是一系列连续的字符的组合,要想在内存中定位一个字符串,除了要知道它的开头,还要知道它的结尾,找到字符串的开头很容易,知道它的名字(字符数组名或者字符串名)就可以,因为字符数组名或者字符串名都代表首字符的起始地址。那么应该如何找到字符串的结尾?

      在C语言中,字符串总是以'\0',作为结尾,所以'\0'也被称为字符串结束标志,或者字符串结束符。'\0'是ASCII码表中的第0个字符,英文称为NUL,中文称为空字符,该字符即不能显示,也没有控制功能,输出该字符不会有任何效果,它在C语言中的唯一作用就是作为字符串结束标志。0、'\0'、NULL、false 都是 0 的表现形式。

       C语言在处理字符串时,会从前往后逐个扫描字符,一旦遇到'\0'就认为到达了字符串的结尾,就会结束处理,'\0'至关重要,没有'\0'就意味着永远也到达不了字符串的结尾。

      用双引号" "包围的字符串,编译器会隐式的在字符串末尾自动添加'\0',然而通过逐个单引号为字符数组赋值并不会自动添加'\0'。

      如:char str[]={'a','b','c'};数组长度为3。   char str[]="abc";数组长度为4。

因此,实际开发会有以下出错点:

程序的逻辑要求必须逐个字符的为字符数组赋值(通常for循环),经常会出现以下问题:

//通过for循环将26个大写英文字母存入字符数组,并以字符串的形式输出
#include <stdio.h>
int main()
{
   char str [30];
   char c;
   int  i;
   for(c=65,i=0; c<=90; c++,i++)
      {
          str[i]=c;
      }
   printf("%s",str);
   return  0;
}

         在函数内部定义的变量、数组、结构体、共用体等都成为局部数据,在很多编译器,局部数据的初始值都是随机值,并不是我们通常认为的”零“值,因此本例字符数组定义后,里面存放的是随机值,通过循环赋值后,前26个元素已经被赋值为26个英文字母,但是后4个为随机值,不一定是'\0',因此,printf打印完前26个字符后,接下来后面的不一定是'\0',只有遇到'\0',打印才会结束,有可能到了第50个元素才是'\0',这已经超出数组的范围了!!但是也会打印出来!因此,如果不注意'\0'的后果很严重,不但不能正确处理字符,甚至还会毁坏其他数据!

解决办法:

      方式1:在字符串的最后手动添加'\0'即可;

      方式2:字符数组定义时便进行初始化,将字符数组的所有元素都初始化为”零“值;从根本解决问题。(实际开发常用方法:因为一般定义的局部变量都需要进行初始化再使用)

//通过for循环将26个大写英文字母存入字符数组,并以字符串的形式输出
#include <stdio.h>
int main()
{
   char str [30];
   char c;
   int  i;
   for(c=65,i=0; c<=90; c++,i++)
      {
          str[i]=c;
      }
   str[i]=0;        //方式1 在字符串末尾手动添加0,即'\0'
   printf("%s",str);
   return  0;
}
//通过for循环将26个大写英文字母存入字符数组,并以字符串的形式输出
#include <stdio.h>
int main()
{
   char str [30]={0};   //方式2:字符数组定义时便将字符数组的所有元素都初始化为0,或者说'\0'
   char c;
   int  i;
   for(c=65,i=0; c<=90; c++,i++)
      {
          str[i]=c;
      }
   printf("%s",str);
   return  0;
}

 2、字符串的定义

        用"  "包括的字符序列,其末尾包含一个隐含的结尾标识字符'\0'。 字符串只需要满足以下两个条件其中一点即可。

1)   用"   "表示。

2)   字符数组中包含'\0'。 温馨提示: 0、'\0'、NULL、false 都是 0 的表现形式。

3、二者的区别(面试)

        以char str[]={'h','e','l','l','o'};   和char str[]="hello";为例

区别1:sizeof(arr)/sizeof(arr[0])求解字符数组的长度时,---数组空间大小

        (1)由双引号" "包围的字符串会自动的在末尾添加'\0',因此,在用sizeof求字符数组长度时,结果会比实际字符数组的长度多1个。   6个(求解的是字符数组所占的内存空间大小)

        (2)逐个为字符数组赋值初始化并不会自动添加'\0',因此在用sizeof求字符数组长度时,结果就是实际的字符数组的长度。            5个

区别2:利用字符串处理函数strlen求字符串长度时,-----字符串的实际长度

      strlen()字符串处理函数在头文件string.h中,返回的值是字符串的实际长度,不包括'\0',只要遇到'\0',那么之前的字符个数就被认作是该字符串的大小,是一个整数。

    (1)由双引号" "包围的字符串会自动的在末尾添加'\0',因此,在用strlen求字符数组长度时,strlen返回的就是实际字符串长度。           5个

    (2)逐个为字符数组赋值初始化并不会自动添加'\0',若字符数组定义处也未进行初始化,则利用strlen()求字符数组的长度时,结果为一个随机值,因为不知道什么时候遇到'\0'。

面试题:

      char  str[]="abc\123\a\0124hello";

(1) 利用sizeof()求数组长度: 12+1=13个

(2) 利用strlen()求数组长度: 12个

二、字符串的访问方式/使用

       由于字符串在内存中也是连续存放的,是由一个个的字符组成,对字符数组元素进行大量移动或者拷贝时,同样可以考虑使用内存函数memcpy()、memmove(),更加简单高效,提高开发效率,后续总结内存函数。

       上一节已经详细说明,C语言共有两种表示字符串的方法,第一种:字符数组存储字符串;第二种:字符指针指向字符串常量(区别在于是否可以修改元素)。

第一种:字符数组存储字符串

1、下标引用操作符访问(同整型数组)/或者%s直接输出整个字符串(字符串特有方式)

        字符数组(字符串)的访问同整型数组,因为他们在内存都是连续存放的,是通过下标引用操作符操作的,使用方式同变量的使用,str[i]代表字符串中第i个元素,并且字符数组元素的下标也是从0开始的,字符串长度减1结束。对于字符数组(字符串)的遍历通常是通过循环结构,如for循环,i既可以作为循环变量,又可以作为字符数组元素访问的下标定位。

        字符数组(字符串)的元素个数(长度)可以通过头文件string.h中的strlen()函数求得,作为循环变量的终止条件,方便程序的实现。

#include <stdio.h>
#include <string.h>
i
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

未来可期,静待花开~

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

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

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

打赏作者

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

抵扣说明:

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

余额充值