假设英文句子由若干词构成。下面 C++ 代码统计输出的词数是( )。
int main()
{
string str = "gEsP is Interesting !";
int x = str.length();
int nwords = 0;
for (int i = 0; i < x; i++)
if (str[i] == ' ') {
nwords++;
while (str[++i] == ' ');
}
cout << nwords << endl;
cout << endl;
return 0;
}这题别急着数空格,先盯着while里那个++i。它不是简单的跳过,而是先自增再判断,意味着遇到连续空格时,循环会多吞掉一个字符,导致计数逻辑出错。抓住这个细节,模拟一遍i的变化轨迹,答案自然浮现。
最容易栽跟头的地方是忽略while循环里++i的副作用。很多学生会以为只要遇到空格就nwords++,然后while把空格跳过去就行,完全没注意到++i会让i额外加1。如果字符串里有连续空格(比如两个空格),第一个空格触发nwords++,while里++i让i多走一步,结果会漏判或者多判,导致最终计数偏差。还有人选B是以为只统计了中间的空格,或者选D是误以为非空格也算词,这些都是没读懂while里++i在连续空格场景下的行为造成的。
这道题考查的是字符串遍历中的循环控制细节,特别是while循环里前置自增++i对下标的影响。命题人故意在while里用++i而不是++i的普通写法,就是为了测试考生是否真正理解循环变量的变化顺序,以及连续空格场景下的边界处理。这是GESP三级里典型的“代码追踪”类陷阱题,属于循环结构与控制流的结合点,考频虽不高,但一旦出错就是硬伤。
我们先看代码主干:字符串str是"gEsP is Interesting !",长度x=21。nwords初始为0。外层for循环从i=0走到x-1(即0到20)。核心逻辑是:如果str[i]是空格,nwords++,然后进入while循环,只要str[++i]还是空格,就继续++i。注意,这里while的条件判断是先执行++i再取str[++i],也就是说,i在判断前已经自增了。
现在一步步模拟i的变化,这是解题的关键心法:拿到题先想“i现在在哪?str[i]是什么?触发条件了吗?if里做了什么?while里i怎么变?”。
初始i=0。str[0]='g',不是空格,跳过if,i++到1。 i=1,str[1]='E',跳过,i++到2。 i=2,str[2]='s',跳过,i++到3。 i=3,str[3]='P',跳过,i++到4。 i=4,str[4]=' ',是空格!执行nwords++,此时nwords=1。然后进入while:先++i,i变成5,str[5]='i',不是空格,while结束。i++到6。 i=6,str[6]='s',跳过,i++到7。 i=7,str[7]=' ',是空格!nwords++,现在nwords=2。while:++i,i变成8,str[8]='I',不是空格,while结束。i++到9。 i=9,str[9]='n',跳过,i++到10。 i=10,str[10]='t',跳过,i++到11。 i=11,str[11]='e',跳过,i++到12。 i=12,str[12]='r',跳过,i++到13。 i=13,str[13]='i',跳过,i++到14。 i=14,str[14]='n',跳过,i++到15。 i=15,str[15]='g',跳过,i++到16。 i=16,str[16]=' ',是空格!nwords++,现在nwords=3。while:++i,i变成17,str[17]='!',不是空格,while结束。i++到18。 i=18,str[18]=' ',是空格!nwords++,现在nwords=4。while:++i,i变成19,str[19]=' ',还是空格!继续循环:++i,i变成20,str[20]=' '(注意,str长度是21,下标0到20,str[20]是最后一个字符,是空格吗?等等,原字符串是"gEsP is Interesting !",长度21,最后一个字符是空格,所以str[20]=' '。那while条件str[++i] == ' ',++i让i变成21,str[21]越界了?不对,题目里str是"gEsP is Interesting !",我们数一下:g(0)E(1)s(2)P(3) (4)i(5)s(6) (7)I(8)n(9)t(10)e(11)r(12)e(13)s(14)t(15)i(16)n(17)g(18) (19)!(20)。哦,我刚才数错了,str[19]是空格,str[20]是'!',str[21]不存在。那回到i=18,str[18]=' ',nwords++变成4。while:++i,i=19,str[19]='!',不是空格,while结束。i++到20。 i=20,str[20]='!',不是空格,跳过,i++到21,循环结束。
等等,刚才模拟i=18时,str[18]是空格,nwords++变成4。然后while里++i到19,str[19]是'!',不是空格,while结束。i++到20。i=20,str[20]是'!',不是空格,跳过,i++到21,循环结束。所以最终nwords=4?不对,题目答案是3。哪里错了?哦,我重新看字符串:"gEsP is Interesting !",长度21。字符:g(0)E(1)s(2)P(3) (4)i(5)s(6) (7)I(8)n(9)t(10)e(11)r(12)e(13)s(14)t(15)i(16)n(17)g(18) (19)!(20)。str[18]是'g',不是空格!我刚才把str[18]看成空格了,错误。重新模拟:i=16,str[16]='i',跳过,i++到17。i=17,str[17]='n',跳过,i++到18。i=18,str[18]='g',跳过,i++到19。i=19,str[19]='!',跳过,i++到20。i=20,str[20]不存在?不对,长度21,下标0到20,str[20]是'!',i=20时str[20]='!',不是空格,跳过,i++到21,循环结束。所以nwords=3。对了,答案是3。
刚才的错误在于把str[18]误判为空格,导致多算了一次。这说明代码追踪必须极其小心,不能凭感觉,要逐字符核对。命题人挖坑的地方就是这种细节:字符串里空格的位置不是均匀分布的,而且while里的++i会让i在判断前就变了,如果连续空格,i会多走一步,但本题里没有连续空格,所以while只执行一次,但i的自增顺序容易让人混淆。还有,字符串末尾的'!'不是空格,所以不会触发if,但很多人会以为末尾有空格,从而多算。
避坑方面,最易错的是选B(2)或D(4)。选B的人可能只数了中间的两个空格,忽略了末尾的'!'前面的空格?不对,末尾是'!',前面是空格,str[19]='!',str[18]='g',所以末尾没有空格。那选B的人可能是漏了第一个空格?或者把'!'当成空格?选D的人可能是把'!'当成空格,或者多算了一次。总之,一定要逐字符模拟,不能靠直觉。
考频趋势看,字符串遍历和控制结构在GESP三级里是高频考点,2024年考了413题,2025年401题,2026年109题,逐年下降但总量巨大。循环控制类题目虽然整体考频不高(题库共5题),但在GESP三级里占了1题,说明这是命题人喜欢的“小而精”的陷阱题。未来可能还会以类似形式出现,比如改if条件、改while里++i的位置,或者用连续空格测试边界。暂无足够依据预测具体年份,但可以肯定的是,这类题在GESP三级里会持续存在,因为它是基础语法与逻辑判断的结合点,非常适合考察学生的代码阅读能力。
所以,拿到题先想:字符串长度是多少?每个字符是什么?i怎么变?if条件触发几次?while里i怎么变?最终nwords是多少?一步步推,别跳步骤。这样就能避开所有坑,稳稳选C。