前言 字符串的存储方式有字符数组和字符指针。 因为字符串是由多个字符组成的序列,所以要想存储一个字符串,可以先把它拆成一个个字符,然后分别对这些字符进行存储,即通过字符数组存储。字符数组是一个数组,且是存储字符的数组,该数组中一个元素存放字符串的一个字符。一、字符数组的定义 1、因为字符数组首先是一个数组,所以前面讲的数组内容通通都适用。其次它是存放字符的数组,即数组的类型是char型。比如:charname〔10〕;表示定义了10字节的连续内存空间。如果字符串的长度大于10,那么就存在语法错误。这里需要注意的是,这里指的字符串的长度包括最后的。也就是说,虽然系统会自动在字符串的结尾加,但它不会自动为开辟内存空间。所以在定义数组长度的时候一定要考虑。如果字符串的长度小于数组的长度,则只将字符串中的字符赋给数组中前面的元素,剩下的内存空间系统会自动用填充。 2、我们在用C语言编写程序时,经常会遇到使用字符串数组的情况,这种数组的特点是,数组中的每个元素都是一个字符串,但每个字符串的长度却不相同。如果你使用C语言进行编程的话,实现起来相对比较简单,只需直接选择标准模板库的字符串string类,在代码中定义该类的一个数组即可实现。现在的问题是,在纯C语言中如何定义这样的一个字符串数组呢? 如对于下面的一个字符串数组:str{IloveC。,IloveC。,IloveJAVA。,IlovePython。,IloveLabVIEW。} 下面给出C语言中的两种定义方法。 方法1:定义一个char类型的二维数组这种方法是通过定义一个char类型的二维数组实现,通过二维数组的行索引可得到数组中的每个字符串,列的大小限定了每个字符串所能包含的最大字符个数,所以采用这种定义方式时,列的大小必须不能小于数组所有字符串的最大长度。如对于上面的数组,C语言的定义代码如下:charstr〔5〕〔20〕{IloveC。,IloveC。,IloveJAVA。,IlovePython。,IloveLabVIEW。}在取该数组的每个字符串时,直接对行索引即可。 方法2:定义一个指向char类型的指针数组这种方法是通过定义一个指向char类型的指针数组实现,数组中的每个元素都是一个指针,通过该指针可得到数组中的每个字符串。如对于上面的数组,C语言的定义代码如下:charstr〔5〕{IloveC。,IloveC。,IloveJAVA。,IlovePython。,IloveLabVIEW。} 两种方法对比上面的两种方法都可以实现我们的目的,但在内存的占用上两种方法不同。第1种方法定义了一个5行20列的二维数组,即每个字符串所占的字节长度都为20个,所以共需要占用100个字节。第2种方法是定义的指针数组,每个指针指向的字符串占用的字节长度是其实际长度,所以其总的长度肯定小于100个字节。综合来讲,第1种方法相对于第2种方法,造成了存储空间的浪费情况。二、字符数组的初始化 字符数组的初始化与数组的初始化一样,要么定义时初始化,要么定义后初始化。下面写一个程序来说明这个问题: 代码如下(示例):includestdio。hintmain(){chara〔10〕;a〔0〕i;a〔1〕;a〔2〕l;a〔3〕o;a〔4〕v;空格字符的单引号内一定要敲空格a〔5〕e;a〔6〕;a〔7〕y;a〔8〕o;a〔9〕u;a〔10〕;charb〔10〕;b〔0〕i;b〔1〕;b〔2〕m;b〔3〕i;b〔4〕s;b〔5〕s;b〔6〕;b〔7〕y;b〔8〕o;b〔9〕u;charc〔〕ibelieveyou;chard〔〕{i,,l,i,k,e,,y,o,u,};chare〔〕{H,e,l,l,o,,W,o,r,l,d};charf〔〕不是我抄你的,就是你抄我的!;charg〔10〕;printf(as,a);输出字符串用s,输出参数必须写数组名printf(bs,b);printf(cs,c);printf(ds,d);printf(es,e);printf(fs,f);printf(gs,g);return0;输出结果是:ailoveyoubimissyou琉iloveyoucibelieveyoudilikeyoueHelloWorld繇likeyouf不是我抄你的,就是你抄我的!g} 1。先定义后初始化chara〔10〕;a〔0〕i;a〔1〕;a〔2〕l;a〔3〕o;a〔4〕v;空格字符的单引号内一定要敲空格a〔5〕e;a〔6〕;a〔7〕y;a〔8〕o;a〔9〕u;a〔10〕; 数组a是先定义后初始化。一方面与以前讲的数值型数组一样,先定义后初始化必须一个一个地进行赋值,不能整体赋值;另一方面与以前讲的数值型数组又不一样,对于字符串,先定义后初始化也可以整体赋值,但是要调用strcpy函数,这点稍后再讲。 总之上面这个程序中给数组a一个一个进行初始化的方式很麻烦。而且这样写需要注意:前面讲过系统会在字符串的最后自动添加结束标志符,但是当一个一个赋值时,系统不会自动添加,必须手动添加。如果忘记添加,虽然语法上没有错误,但是程序将无法达到我们想要的功能。数组b就是这样的例子。 此外,空格字符必须要在单引号内敲一个空格,不能什么都不敲,什么都不敲就是语法错误。也不能多敲,因为一个单引号内只能放一个字符,敲多个空格就是多个字符了。charb〔10〕;b〔0〕i;b〔1〕;b〔2〕m;b〔3〕i;b〔4〕s;b〔5〕s;b〔6〕;b〔7〕y;b〔8〕o;b〔9〕u; 数组b就是最后没有手动添加的例子。程序是希望数组b输出imissyou,但输出结果是imissyou錌iloveyou。原因就是系统没有在最后添加。 虽然程序中对数组b的长度进行了限制,即长度为10,但是由于内存单元是连续的,对于字符串,系统只要没有遇到,就会认为该字符串还没有结束,就会一直往后找,直到遇到为止。被找过的内存单元都会输出,从而超出定义的10字节。 2。定义时初始化charc〔〕ibelieveyou; 数组c是定义时初始化。定义时初始化可以整体赋值。整体赋值有一个明显的优点方便。定义时初始化可以不用指定数组的长度,而先定义后初始化则必须要指定数组的长度,如数组a和数组b。不用指定数组长度有一个好处:不用人为确定需要多少字节的内存空间,系统会根据初始化的内容自动分配数量正好的内存空间。而且对于数组c的写法系统会自动在最后添加结束标志符,不需要人为添加。chard〔〕{i,,l,i,k,e,,y,o,u,}; 数组d也是定义时初始化,但它既属于整体赋值,也属于一个一个赋值。说它是整体赋值是因为不用写d〔0〕、d〔1〕而说它是一个一个赋值是因为它把整个句子分成了一个一个的字符。还是数组c的写法比较方便,而且对于数组d的写法系统也不会自动在最后添加结束标志符,必须人为添加。如果忘记添加就会出现与数组b同样的错误。从数组e的输出结果可以看出这一点。charf〔〕不是我抄你的,就是你抄我的!; 数组f是存储汉字,汉字不能像数组a或数组d那样分开一个一个赋值。因为一个汉字占2字节,若分开赋值,由于一个单引号内只能放一个字符,即一字节,所以将占2字节的汉字放进去当然就出错了。因此如果用字符数组存储汉字的话必须整体赋值,即要么定义时初始化,要么调用strcpy函数。charg〔10〕; 数组g初始化为一对双引号,表示该字符数组中10个元素的内容都为。下面写一个程序验证一下:includestdio。hintmain(){charstr〔3〕;str〔2〕a;printf(strs,str);return0;}输出结果是: str 程序中定义了一个长度为3的字符数组,然后给第三个元素赋值为a,然后将整个字符数组输出。但是输出结果什么都没有,原因就是其直接初始化为一对双引号,此时字符数组中所有元素都是。所以虽然第三个元素为a,但因为第一个元素为,而是字符串的结束标志符,所以无法输出。 需要注意的是,使用此种初始化方式时一定要指定数组的长度,否则默认数组长度为1。 总结,字符数组与前面讲的数值数组有一个很大的区别,即字符数组可以通过s一次性全部输出,而数值数组只能逐个输出每个元素。三、怎样引用字符数组中的元素 1。输出一个已知的字符串includestdio。hintmain(){charc〔〕{I,,C,o,m,e,,F,r,o,m,,N,Y,I,S,T,};法一for(inti0;i17;i){printf(c,c〔i〕);}printf();法二printf(s,c);return0;} 2。输出一个菱形includestdio。hintmain(){chardiamond〔〕〔5〕{{,,},{,,,},{,,,,},{,,,},{,,}};inti,j;for(inti0;i5;i){for(intj0;j5;j){printf(c,diamond〔i〕〔j〕);}printf();}return0;} 3。连续字符力扣题目给你一个字符串s,字符串的能量定义为:只包含一种字符的最长非空子字符串的长度。 请你返回字符串的能量。 示例1: 输入:sleetcode 输出:2 解释:子字符串ee长度为2,只包含字符e。 示例2: 输入:sabbcccddddeeeeedcba 输出:5 解释:子字符串eeeee长度为5,只包含字符e。 示例3: 输入:striplepillooooow 输出:5 示例4: 输入:shooraaaaaaaaaaay 输出:11 示例5: 输入:stourist 输出:1includestdio。hincludestring。hintmaxPower(chars){inti;intstart;intmaxlen1;inttemplen1;start0;for(i1;istrlen(s);i){if(s〔i〕s〔start〕){templen;}else{starti;if(templenmaxlen){maxlentemplen;}templen1;}}最后一句很关键,把最后start直到末尾算出的templen和maxlen比较一下例如eettt,计算出的maxlen为2,但最后start直到末尾算出的templen为3returnmaxlentemplen?maxlen:templen;}intmain(){charstr〔〕aaaabbbeeeeeee;intlenmaxPower(str);printf(d,len);return0;} 4。截断句子力扣题目在字符串s中找出第一个只出现一次的字符。如果没有,返回一个单空格。s只包含小写字母。 句子是一个单词列表,列表中的单词之间用单个空格隔开,且不存在前导或尾随空格。每个单词仅由大小写英文字母组成(不含标点符号)。 例如,HelloWorld、HELLO和helloworldhelloworld都是句子。 给你一个句子s和一个整数k,请你将s截断,使截断后的句子仅含前k个单词。返回截断s后得到的句子。 示例1: 输入:sHellohowareyouContestant,k4 输出:Hellohowareyou 解释: s中的单词为〔Hello,howare,you,Contestant〕 前4个单词为〔Hello,how,are,you〕 因此,应当返回Hellohowareyou 示例2: 输入:sWhatisthesolutiontothisproblem,k4 输出:Whatisthesolution 解释: s中的单词为〔What,isthe,solution,to,this,problem〕 前4个单词为〔What,is,the,solution〕 因此,应当返回Whatisthesolution 示例3: 输入:schopperisnotatanuki,k5 输出:chopperisnotatanukiincludestdio。hincludestring。hchartruncateSentence(chars,intk){intlenstrlen(s);intcnt0;inti;for(i0;ilen;i){if(s〔i〕(cntk)){空格够了,就添加结束符s〔i〕;break;}}returns;}intmain(){charstr〔〕aaaabbbeeeeeee;charlentruncateSentence(str,3);printf(s,len);return0;}完结撒花