ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

CSP-J 初赛(以满分为目标):第十四课《字符、ASCII与字符串——一个字母到底是什么?字符串又是怎样“藏”在数组里的?》

CSP-J 初赛(以满分为目标):第十四课《字符、ASCII与字符串——一个字母到底是什么?字符串又是怎样“藏”在数组里的?》 第十四课 字符、ASCII与字符串——一个字母到底是什么字符串又是怎样“藏”在数组里的一、本课学习目标这一课我们主要解决6个问题1. char到底是什么 2. 字符和整数有什么关系 3. ASCII是什么 4. char数组和字符串是什么关系 5. 字符串如何进行遍历和修改 6. CSP-J初赛怎样阅读字符串程序最后同学们还要掌握一个非常重要的能力看到字符串程序不要“凭感觉读”而是把每一个字符、每一个下标、每一次循环都模拟出来。二、先认识char我们以前学过int x 10; double y 3.14;那么字符呢使用char c;例如char c A;注意A是一个字符。而A是一个字符串。这是第一道非常重要的区别。三、字符和字符串不要混淆看char c A;这里A只有一个字符。而string s A;这里A是一个字符串。可以简单理解A ↓ 一个人 A ↓ 一支队伍只有一个人四、单引号和双引号这是CSP-J初赛非常容易出现的小陷阱。A表示字符A表示字符串例如char c A; // 正确 string s ABC; // 正确不要写成char c A;因为A不是一个字符。五、字符其实也可以进行计算这是孩子第一次接触时非常神奇的地方char c A; cout c 1;为什么可以计算因为计算机内部并不是直接保存“字母长什么样”而是给字符分配了一个数字编码。其中最经典的就是ASCII六、什么是ASCIIASCII可以理解成给常用字符安排一个数字编号。例如A → 65 B → 66 C → 67 ... Z → 90小写字母a → 97 b → 98 c → 99 ... z → 122数字字符0 → 48 1 → 49 2 → 50 ... 9 → 57所以一定要让孩子记住几个关键值0 48 A 65 a 97七、为什么A1是B因为A 65 B 66所以A 1就是65 1 66对应B因此char c A; cout c 1;这里需要特别注意表达式c 1的结果是整数类型的数值不是自动“打印成字符”。如果想输出字符cout char(c 1);得到B八、这就解释了很多字符串程序例如char c A; for(int i 0; i 5; i) { cout char(c i); }逐个计算i0 → A i1 → B i2 → C i3 → D i4 → E输出ABCDE九、ASCII非常适合处理字母例如char c D;我们想知道D是第几个大写字母可以c - A 1因为D - A 68 - 65 3再加14所以A → 1 B → 2 C → 3 D → 4十、为什么字符可以比较大小例如if(c A c Z)这是什么意思就是判断c是否是大写字母。因为A ≤ B ≤ ... ≤ Z对应ASCII65 ≤ 66 ≤ ... ≤ 90同样if(c 0 c 9)可以判断c是不是数字字符。十一、字符分类是初赛常见考点我们可以总结大写字母c A c Z小写字母c a c z数字字符c 0 c 9例如char c; cin c; if(c 0 c 9) cout 数字; else cout 不是数字;十二、大写字母和小写字母之间有什么关系ASCII中A 65 a 97相差97 - 65 32所以a A 32例如char c C; cout char(c 32);输出c反过来char c c; cout char(c - 32);输出C不过实际编程中更推荐使用标准字符函数来做大小写转换初赛阅读题则经常直接利用ASCII规律。十三、现在进入真正重要的内容字符串假设string s hello;字符串是什么可以把它想象成h e l l o实际上就是s[0] h s[1] e s[2] l s[3] l s[4] o十四、字符串下标从0开始这一点和数组完全一样。string s hello;画成表下标 0 1 2 3 4 ┌───┬───┬───┬───┬───┐ 字符 │ h │ e │ l │ l │ o │ └───┴───┴───┴───┴───┘所以s[0] h; s[1] e; s[4] o;而s[5]已经超出了这个字符串的有效字符位置。十五、字符串长度例如string s hello;长度5C中s.length()或者s.size()都可以得到长度。例如cout s.length();输出5十六、初赛最常见的字符串循环看到string s hello; for(int i 0; i s.size(); i) { cout s[i]; }不要复杂化。就是i0 → h i1 → e i2 → l i3 → l i4 → o输出hello十七、字符串可以修改例如string s hello; s[0] H;变成Hello再s[4] !;变成Hell!所以字符串可以看成一排可以访问、修改的字符。十八、字符串遍历统计例如统计字符串中有多少个a。string s banana; int cnt 0; for(int i 0; i s.size(); i) { if(s[i] a) cnt; } cout cnt;逐个看b → 不统计 a → 1 n → 不统计 a → 2 n → 不统计 a → 3答案3十九、这和数组统计完全一样前面学数组的时候for(int i0;in;i) { if(a[i] x) cnt; }现在字符串for(int i0;is.size();i) { if(s[i] x) cnt; }本质完全一样数组 ↓ 很多数字 字符串 ↓ 很多字符所以字符串就是“字符组成的一串数据”。二十、字符数组还有经常出现的一种写法char name[100];举例struct stu{ char name[100]; double score; };使用strcpy(s.name,ZhangSan);给name赋值。二十一、char name[100]是什么可以把它理解成100个char组成的数组例如char s[100];实际上是s[0] s[1] s[2] ... s[99]每一个位置都是一个char二十二、字符串为什么能放进字符数组例如char s[100] hello;可以想象成下标 0 1 2 3 4 5 ↓ ↓ ↓ ↓ ↓ ↓ h e l l o \0这里出现一个非常重要的东西\0二十三、什么是\0它叫字符串结束标志它的ASCII值是0所以hello在字符数组中实际上是h e l l o \0也就是说真正的字符串不仅有字母还要有一个结束标志。二十四、这是字符数组和普通数组的重要区别普通整数数组int a[5] {1,2,3,4,5};没有所谓结束符但C风格字符串char s[] hello;内部会有h e l l o \0因此需要至少5 1 6个字符空间。二十五、为什么char s[5] hello有问题因为hello需要h e l l o \0一共6个字符位置。所以char s[6] hello;才有足够空间容纳结束符。对于初赛程序阅读看到字符数组时一定要警惕数组空间是否足够有没有\0二十六、strcpy()是什么使用strcpy(s.name,ZhangSan);它的作用可以简单理解成把一个C风格字符串复制到另一个字符数组中。例如char a[100]; strcpy(a, hello);之后a ↓ hello二十七、为什么不能直接a hello;如果a是char a[100];那么它是一个字符数组。对于C风格字符数组字符串复制通常使用strcpy()而不是这一点和string s; s hello;不同。二十八、C的string更方便如果string s;那么s hello;直接可以。而且s world;可以拼接。所以可以简单理解char数组 ↓ 比较传统 ↓ 需要注意\0、数组空间、strcpy等 string ↓ C更方便的字符串类型二十九、字符串拼接例如string a hello; string b world; string c a b;得到helloworld如果string c a b;得到hello world这类程序在初赛阅读中要直接模拟。三十、字符串比较例如string a apple; string b banana; if(a b) cout a小;为什么字符串也能比较可以简单理解为按照字符的编码顺序进行字典序比较。比如apple banana第一个字符a b所以apple banana三十一、字符串比较最重要的思想逐字符比较例如abc abd前两个字符aa bb继续看第三个cd所以abc abd如果abc abcde前面完全相同较短的字符串更小。这个概念就是字典序三十二、字符串程序模拟案例一string s ABCDE; for(int i 0; i s.size(); i 2) { cout s[i]; }逐步i0 → A i2 → C i4 → E所以输出ACE这种题非常典型。三十三、字符串程序模拟案例二string s abcdef; for(int i 0; i s.size(); i) { if(s[i] a s[i] z) s[i] s[i] - a A; } cout s;逐字符a → A b → B c → C d → D e → E f → F输出ABCDEF这里实际上考了ASCII 字符比较 字符串下标 循环这就是初赛很喜欢考的“字符转换”。三十四、非常经典的周期问题真题讲解如果开始时处于小写输入状态小老鼠反复按照CapsLock、A、S、D、F的顺序按键那么屏幕上输出的第81个字符是什么题目给出的输出规律是ASDFasdfASDFasdf...三十五、为什么会出现周期看前8个A S D F a s d f然后又重新A S D F a s d f所以周期 8这类题的核心不是一个一个按81次。而是寻找周期。三十六、求第81个字符周期8所以81 ÷ 8余数1也就是81 % 8 1所以第81个字符等于一个周期中的第1个字符。即A答案是A。三十七、这里连接了第5课还记得我们之前讲过取模 %现在第N个 周期T经常可以使用N % T来确定位置。所以字符串 循环 取模是初赛非常常见的组合。三十八、周期题的通用方法看到ABCABCABCABC...立刻想到周期 3问第100个是什么计算100 % 3 1所以是A三十九、但是这里有一个小陷阱如果N % T 0例如ABCABCABC...问第6个是什么6 % 3 0不是第0个。而是第3个。所以余数 0 ↓ 对应周期的最后一个这个一定要注意修正。四十、字符串逆序例如string s hello;逆序olleh最简单的思路for(int i s.size()-1; i 0; i--) { cout s[i]; }程序阅读时i4 → o i3 → l i2 → l i1 → e i0 → h所以olleh四十一、统计元音字母例如string s hello; int cnt 0; for(int i0;is.size();i) { if(s[i]a || s[i]e || s[i]i || s[i]o || s[i]u) { cnt; } }hello中e o所以cnt 2这类题本质上依然是遍历 判断 统计所以不要把字符串题想得太复杂。四十二、字符串程序阅读“四步法”以后看到字符串程序建议同学按照这四步第一步写出字符串例如string s abcde;画0 1 2 3 4 a b c d e第二步确定循环范围例如for(int i0;is.size();i2)就写0 → 2 → 4第三步把下标对应字符s[0] a s[2] c s[4] e第四步写输出ace不要在脑子里硬算。四十三、字符串题最常见的5种题型题型1统计有多少个a 有多少个数字 有多少个大写字母题型2修改大写变小写 小写变大写 某个字符替换题型3逆序abcdef → fedcba题型4周期ABCABCABC...问第N个是什么。题型5字符串比较apple banana判断字典序关系。四十四、CSP-J容易出现的“字符陷阱”陷阱11不是整数1而是字符1的ASCII码 49陷阱20不是数值0。0 ≠ 0这是极其重要的。陷阱3A不是A前者是字符串后者是字符。陷阱4s[0]是第一个字符。不是整个字符串。陷阱5s.size()是字符串长度。不是最后一个下标。如果s.size() 5那么最后一个下标是4四十五、阅读题string s CSPJ; int ans 0; for(int i 0; i s.size(); i) { if(s[i] A s[i] Z) ans s[i] - A 1; } cout ans;我们一步一步算。字符串C S P J对应C → 3 S → 19 P → 16 J → 10所以ans 3 19 16 10 48输出48这个题一次考了字符串 ASCII 循环 条件 字符运算四十六、再来一道string s 123; int x 0; for(int i0;is.size();i) { x x * 10 s[i] - 0; } cout x;初看很疑惑s[i]明明是字符怎么变成数字了例如1 - 0ASCII49 - 48 1所以2 - 0 2 3 - 0 3于是x0 读1: x0*1011 读2: x1*10212 读3: x12*103123最后123这也是初赛经常考的知识点字符数字 → 真正的数字c - 0四十七、反过来怎么办如果int x 7;想得到字符7可以char c x 0;因为7 48 55ASCII 55就是7所以数字 ↓ 0 ↓ 数字字符而数字字符 ↓ - 0 ↓ 数字这一组关系非常值得大家记住。四十八、本课知识到这里本课可以和前面知识连起来字符串 │ ┌──────────┼──────────┐ ↓ ↓ ↓ char string char[] │ │ │ ↓ ↓ ↓ ASCII 下标 \0 │ │ ↓ ↓ 字符运算 遍历/修改 │ │ └────┬─────┘ ↓ 程序模拟 ↓ ┌───────┼────────┐ ↓ ↓ ↓ 统计 周期 字符转换四十九、本课CSP-J必背清单① 字符char c A;② 字符串string s ABC;③ 单引号 vs 双引号A → 字符 ABC → 字符串④ 三个关键ASCII值0 48 A 65 a 97⑤ 字符数字转换c - 0x 0⑥ 大小写转换思想a - A 32⑦ 字符串下标s[0] → 第一个字符⑧ 字符串长度s.size() s.length()⑨ C风格字符串char s[100];字符串末尾有\0⑩ 周期如果周期为T第N个位置 通常利用 N % T如果N % T 0对应周期中的最后一个位置。五十、给孩子的终极口诀单引号是字符双引号是字符串。字符背后有数字这就是ASCII。0不是01也不是1。字符减0字符数字变数字。数字加0数字变成数字字符。字符串下标从0开始。C风格字符串末尾有\0。字符串程序先写下标再逐个模拟。看到重复出现的字符串先找周期。求第N个想到取模。五十一、课堂练习第1部分字符 ASCIIchar ↓ 字符与整数 ↓ ASCII ↓ 大小写 ↓ 数字字符 ↓ c-0 ↓ 字符程序模拟重点训练“看到字符就想到ASCII。”第2部分字符串 程序阅读string ↓ 下标 ↓ size() ↓ 遍历 ↓ 修改 ↓ char数组 ↓ \0 ↓ 周期 ↓ 字符串综合程序重点训练“看到字符串程序画出下标表再模拟。”到这里大家已经从单纯的变量 ↓ 循环 ↓ 数组 ↓ 函数逐渐进入数据 ↓ 数据结构 ↓ 算法思想 ↓ 程序阅读下一课进入第15课结构体、排序与自定义比较——从“给数字排序”走向“给一群人、一堆物品排序”。
返回列表