
C 字符串知识点总结一、字符数组基础1.1 字符数组保存字符串在 C 中字符串可以使用字符数组来保存。使用字符数组保存字符串时必须使用字符\0结尾\0是字符串结尾的标记。charc[6]{h,e,l,l,o,\0};存储示意图下标012345元素hello\0如果定义时不写\0则只是普通数组不是字符串charc[5]{h,e,l,l,o};// 普通数组不是字符串1.2 字符数组初始化方式初始化方式代码示例说明完整初始化指定长度char c2[6] hello;不用写\0系统自动添加省略长度char c3[] {h,e,l,l,o};数组长度自动推断省略长度字符串形式char c4[] hello;最简洁的写法全 0 初始化char s[20] {0};所有元素初始化为 0注意\0的编码是整数 0所以0和\0等价。二、字符串概念字符串0个或1个或多个字符组成的一串字符可以是字母、数字、中文或其他符号。C 中字符串需要使用双引号包含。三、字符串输入3.1 cin.getline()C风格字符数组chars[100];cin.getline(s,100);// 最多读99个字符最后自动补\0cin.getline(s,100,,);// 第三个参数可选以,结束属于iostream的成员函数只能读进 C 风格字符数组可以接收空格3.2 getline(cin, str)配合 std::string#includestringstring str;getline(cin,str);// 读取一整行遇到\n结束getline(cin,str,,);// 以,作为分隔符属于string里的全局函数C 中优先使用这种方式3.3 cin s注意局限string s;cins;// 无法接收空格输入good morning只能读到good四、字符数组操作函数#include 函数操作说明strlen(s1)计算字符串 s1 长度不含\0strcpy(s1, s2)将 s2 的内容复制给 s1strcat(s1, s2)s2 的内容拼接在 s1 尾部strcmp(s1, s2)比较 s1 和 s2。结果 0 表示 s1 s2结果 0 表示 s1 s2等于0表示相等4.1 大小写转换函数函数操作示例strupr(s)将字符数组中的小写字符转换成大写“hello” → “HELLO”strlwr(s)将字符数组中的大写字符转换成小写“HELLO” → “hello”4.2 遍历字符串chars[]hello;for(inti0;istrlen(s);i)couts[i]endl;注意最后一个有效字符的下标为strlen(s) - 1。五、string 字符串5.1 string 定义与初始化string s1hello;couts1endl;5.2 string 输入string s;cins;// 无法接收空格getline(cin,s);// 可接收空格能读取一整行5.3 string 常用操作函数函数/操作操作说明s1.length()计算字符串 s1 长度不含\0s1.size()计算字符串 s1 长度同 length()s1.find(s2)查找 s2 在 s1 中第一次出现的位置(下标)没找到返回string::nposs1 s2给 s1 重新赋值 s2s1 s2s1 和 s2 拼接成新字符串s1 s2在 s1 尾部追加 s2、、、、、!字符串之间比较5.4 string 高级操作substr() - 截取子串string s1hello;string s2s1.substr(1,3);// 从下标1开始截取3个字符 - ellstring s3s1.substr(3);// 从下标3开始截取到结束 - loinsert() - 插入子串string s1hello;s1.insert(2,...);// 在下标2位置插入... - he...lloreplace() - 替换string s1hello;s1.replace(2,2,LL);// 从下标2开始用LL替换2个字符 - heLLos1.replace(5,2,3,A);// 从下标5开始用3个A替换 - helloAAAerase() - 删除string s1hello world;s1.erase(2,2);// 从下标2开始删除2个字符 - heoworlds1.erase(2);// 从下标2开始删除到末尾 - he六、课件例题与真题解析6.1 真题密码合规检测2023年6月【问题描述】网站注册需要有用户名和密码编写程序以检查用户输入密码的有效性。合规的密码应满足以下要求只能由 a-z、A-Z、0-9 以及 !#$ 四个特殊字符构成密码最短长度6个字符最大长度12个字符大写字母、小写字母和数字必须至少有其中两种以及至少有四个特殊字符中的一个【输入描述】输入一行不含空格的字符串。约定长度不超过100。该字符串被英文逗号分隔为多段作为多组被检测密码。【输出描述】输出若干行每行输出一组合规的密码。输出顺序以输入先后为序。【样例输入】seHJ12!,sjdkkfH$123,sdf!12HDHa!,123^YUhg!【样例输出】seHJ12! sjdkkfH$123【样例解释】输入被英文逗号分为了四组被检测密码“seHJ12!”、“sjdkkfH$123”、“sdf!12HDHa!”、“123YUhg!”。其中“sdf!12HDHa!”长度超过12个字符不合规“123YUhg!”包含四个特殊字符之外的字符“^”不合规。解法一字符数组实现【解题思路】读取整行字符串长串遍历长串以逗号,为分隔符截取子串对每个子串调用 check 函数判断是否合规合规则输出#includeiostreamusingnamespacestd;charline[101];charpwd[101];boolcheck(charstr[],intl){if(l6||l12)returnfalse;boolhasCfalse,hasLfalse,hasDfalse,hasSfalse;for(inti0;str[i]!\0;i){if(Astr[i]str[i]Z){hasCtrue;}elseif(astr[i]str[i]z){hasLtrue;}elseif(0str[i]str[i]9){hasDtrue;}elseif(str[i]!||str[i]||str[i]#){hasStrue;}else{returnfalse;// 含有其他字符不合法}}if(!hasS)returnfalse;// 没有特殊字符if(hasChasLhasD2)returnfalse;// 字母和数字组合小于2种returntrue;}intmain(){cinline;intlen0;for(inti0;line[i]!\0;i){if(line[i]!,){pwd[len]line[i];len;}else{pwd[len]\0;if(check(pwd,len))coutpwdendl;len0;}}// 循环结束后单独输出最后一个子串if(len0){pwd[len]\0;if(check(pwd,len))coutpwdendl;}return0;}解法二string 字符串实现【解题思路】使用 string 类型存储密码串使用 find(‘,’) 查找逗号位置来分割子串使用 string 的 length() 方法获取长度check 函数只需一个 string 类型参数#includeiostreamusingnamespacestd;boolcheck(string str){if(str.length()12||str.length()6)returnfalse;boolhasCfalse,hasLfalse,hasDfalse,hasSfalse;for(inti0;istr.length();i){if(Astr[i]str[i]Z){hasCtrue;}elseif(astr[i]str[i]z){hasLtrue;}elseif(0str[i]str[i]9){hasDtrue;}elseif(str[i]!||str[i]||str[i]#||str[i]$){hasStrue;}else{returnfalse;// 含有其他字符不合法}}if(hasChasLhasD2)returnfalse;if(!hasS)returnfalse;returntrue;}intmain(){string pwd;cinpwd;intpospwd.find(,);intbegin0;string line;while(pos!-1){for(intibegin;ipos;i){linepwd[i];}if(check(line))coutlineendl;beginpos1;pospwd.find(,,begin);line;}// 处理最后一个子串for(intibegin;ipwd.length();i){linepwd[i];}if(check(line))coutline;return0;}两种解法对比对比项字符数组实现string 实现字符串类型charstring长度获取strlen()length()/size()子串截取手动逐个字符拷贝find() 循环拼接代码简洁度较繁琐更简洁直观推荐程度理解底层原理C首选6.2 课堂练习文本替换【问题描述】现在有一行英文单词组成的文本区分大小写以“.”结尾请你设计一个程序输入要替换的单词和替换后的目标单词将整篇文本所有需要替换的单词全部更改成目标单词最后将全部文本输出。【输入描述】共三行第一行一串单词文本 s长度为 L0 L 200单词之间用空格隔开第二行要替换的单词 s1长度为 L10 L1 10第三行目标单词 s2长度为 L20 L2 10【样例输入】To ba or not to ba, that is a question. ba be【样例输出】To be or not to be, that is a question.【解题思路】输入三个字符串 s、s1、s2使用s.find(s1, i)从当前位置开始查找 s1找到后用s.replace()进行替换替换后步进 s2 的长度避免重复替换【完整代码】#includebits/stdc.husingnamespacestd;intmain(){string s,s1,s2;getline(cin,s);getline(cin,s1);getline(cin,s2);// 对 s 中的所有 s1 进行查找替换for(inti0;(is.find(s1,i))0;is2.size()){s.replace(i,s1.size(),s2);}couts;return0;}【关键点说明】s.find(s1, i)从下标 i 位置开始查找 s1返回首次出现的位置下标没找到返回string::npos即 -1s.replace(pos, n, str)从下标 pos 位置开始用 str 替换 n 个字符步进为s2.size()替换词长度防止替换后的内容被再次匹配导致死循环6.3 选择题解析题目1在下列代码的横线处填写什么可以保证输出是“1357”不会有多余字符#includeiostream#includestringusingnamespacestd;intmain(){charstr[]1234567;for(________________________)// 在此处填入代码coutstr[i];return0;}选项A.int i 0; i strlen(str); iB.int i 0; str[i] ! \0; iC.int i 1; i 7; iD.int i 0; i 6; i 2答案D—— 从下标 0 开始每次步进 2输出下标 0,2,4,6 对应的字符“1357”。题目2下面代码的结果是什么#includestdio.h#includestring.hintmain(){chararr[]{b,i,t};printf(%d\n,strlen(arr));return0;}选项A. 3 B. 4 C. 随机值 D. 5答案C随机值—— 字符数组 arr 没有以\0结尾strlen 会一直向后查找\0结果是随机的。七、配套 GESP 三级洛谷题目推荐7.1 基础题适合入门练习题号题目名称主要考点B3956字母求和字符判断、ASCIIB4003移位字符循环、取模B4449密码强度字符分类、条件判断字符串7.2 核心题系统训练题号题目名称主要考点B3843密码合规字符串分割、规则判断与课件真题同类型B4039回文拼接枚举切点、回文判断字符串B4262词频统计大小写转换、计数字符串7.3 提高题冲刺高分题号题目名称主要考点B4499二进制回文串二进制转换、回文判断字符串B4500凯撒密码偏移量推断、字符串解密7.4 拓展练习题题号题目名称知识点P1308统计单词数字符串搜索与转换P1598垂直柱状图字符串统计与格式化输出P1012拼数字符串排序与拼接P1553数字反转升级版字符串分割与反转B2116加密的病历单字符串处理GESP三级练习八、学习建议熟练掌握字符数组和 string 两种字符串处理方式理解它们的区别和各自适用的场景重点掌握 string 类的常用操作函数find()、substr()、replace()、insert()、erase()这些在 GESP 三级考试中频率很高密码合规检测类题目是 GESP 三级高频题型建议同时掌握字符数组和 string 两种解法注意边界条件字符串末尾的\0、数组下标越界、strlen 对非\0结尾数组的危险性等多练习洛谷 GESP 三级真题特别是字符串分割、字符分类判断、文本替换等核心题型