NOIP 普及组初赛 · NOIP 2007 普及组初赛试题 第 26 题

选择题 · 答案 input s1:wer2345defgh45456782qqq · 考点:字符数组与字符串处理

← 整套速查表 NOIP 普及组初赛 全部真题

题目

看程序写结果:

#include "ctype.h"
#include "stdio.h"
void expand( char s1[], char s2[] )
{
	int i, j, a, b, c;
	j = 0;
	for ( i = 0; (c = s1[i]) != '\0'; i++ )
		if ( c == '-' )
		{
			a = s1[i - 1]; b = s1[i + 1];
			if ( isalpha( a ) && isalpha( b ) || isdigit( a ) && isdigit( b ) )
/*函数 isalpha(a) 用于判断字符 a 是否为字母,isdigit(b) 用于判断字符 b 是否为数字,如果是,返回 1,否则返回 0 */
			{
				j--;
				do
					s2[j++] = a++;
				while ( tolower( a ) < tolower( s1[i + 1] ) );
			}
/*函数 tolower(a) 的功能是当字符 a 是大写字母,改为小写,其余情况不变*/
			else s2[j++] = c;
		}else s2[j++] = c;
	s2[j] = '\0';
}


int main()
{
	char s1[100], s2[300];
	printf( "input s1:" );
	gets( s1 );
	expand( s1, s2 );
	printf( "%s\n", s2 );
}

输入:wer2345d-h454-82qqq

答案:input s1:wer2345defgh45456782qqq

考点

字符数组与字符串处理 讲解 →字符数组与字符串处理 真题汇总 →

解题思维

拿到题先盯着那个'-'看,这题核心就是识别'x-y'这种模式,且x、y类型必须相同(都是字母或都是数字),然后按ASCII码从小到大补全中间字符。输入里有两个'-',要逐个判断两侧字符是否满足条件,满足就展开,不满足就原样保留。

常见错误

最容易踩的坑就是数错了展开范围。比如把'd-h'当成'd-h'中间只差一个字母,结果写成'deh'漏了'f'和'g';或者把'4-8'当成'45678'后面还多塞个'9'。另外,题目里有两个'-',很多考生只处理了第一个'd-h',把第二个'4-8'漏了,导致结果里少了一段展开。还要注意'-'两侧字符类型必须一致,像'd-4'这种混合的不展开,但本题没出现这种干扰项,主要陷阱还是区间长度和是否漏掉第二个'-'。

详细解析(节选)

这道题考查的是字符串处理中的模式替换与ASCII码大小关系判断,属于程序设计基础里很经典的'展开'题型。命题人为什么考这个?因为这类题目披着'看程序写结果'的外衣,实则考察对字符类型判断、循环展开逻辑以及ASCII码顺序的理解,是NOIP普及组初赛的高频考点。从2007年到2026年,字符数组与字符串处理在题库中一共考了107题,覆盖所有考试级别。特别是近几年的趋势非常明显:2025年单年就考了32题,2024年10题,2023年9题,呈现逐年上升趋势,说明这是命题人非常青睐的考点。

我们先来拆解程序的逻辑,这是解题的关键。函数expand里有一个for循环扫描s1,遇到'-'时,它会取前一个字符a和后一个字符b,用isalpha和isdigit判断类型。如果a、b类型相同,就执行展开:先j--(因为'-'占一个位置,展开后要覆盖它),然后用do-while循环从a开始递增,直到tolower(a) >= tolower(b)为止,把中间所有字符填进s2。否则,'-'直接保留。这个逻辑非常清晰:只要'-'两边是同类型的字符,且左边ASCII值小于右边,就把整个区间[x, y]展开成连续序列。

接下来我们代入输入字符串'wer2345d-h454-82qqq'进行模拟。这个字符串里有两个'-',我们需要逐个处理。 第一个'-'在'd'和'h'之间。'd'是字母,'h'也是字母,类型相同,且'd'(ASCII 100) < 'h'(ASCII 104),满足展开条件。从'd'到'h'的字母序列是'd','e','f','g','h',共5个字符。程序会把'-'替换成这5个字母,所以'd-h'变成'defgh'。这里有个细节,do-while循环是从a开始递增,直到a >= b,所以一定会包含b本身,这是一个闭区间。 第二个'-'在'4'和'8'之间。'4'是数字,'8'也是数字,类型相同,且'4'(ASCII 52) < '8'(ASCII 56),同样满足展开条件。从'4'到'8'的数字序列是'4','5','6','7','8',共5个字符。所以'4-8'变成'45678'。

注意程序里有个细节:展开时j--是为了抵消'-'占用的位置,然后do-while循环把a从原值开始递增,直到a >= b(用tolower比较是为了统一大小写,但本题都是小写字母和数字,不影响结果)。这样展开后的字符串长度会变长,但s2数组开的是300,足够容纳。

现在把整个字符串按顺序拼起来:

连起来就是:wer2345defgh45456782qqq。

程序最后输出时,前面还有提示'input s1:',所以完整输出是:input s1:wer2345defgh45456782qqq。

易错点再强调一遍: 1. 区间长度算错:比如'd-h'只展开'deh'(漏了f、g)或'defghi'(多了i),这都是没正确理解'x-y'是闭区间[x, y]。 2. 漏掉第二个'-':输入里有两个'-',很多考生只处理了第一个,导致结果里少了一段展开。 3. 类型判断错误:虽然本题没出现混合类型,但理论上'd-4'这种不展开,如果误展开就会错。 4. 大小写统一:程序用tolower比较,如果两边大小写不一致(比如'D-h'),按题意应该也展开,但本题都是小写,不用纠结。

基于近年趋势,未来这类题目可能会继续出现,而且可能会把展开规则稍微复杂化,比如加入'x-y'中间有非同类字符时不展开,或者展开后还要进行二次处理(如大小写转换)。但就本题而言,核心就是识别两个'-'并正确展开区间。

同考点真题

在 OI伴学 里做这道题
登录后可计时作答、查看完整六段式解析,并按你的错题自动生成同类练习。
去刷题先做一次 AI 学情诊断