mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4mobile wallpaper 5mobile wallpaper 6mobile wallpaper 7
5200 字
14 分钟
端午大礼包-C语言练习题
2026-06-01

端午大礼包 - C 语言练习题完整解析#

本篇文章整理了 C 语言”端午大礼包”练习题共 12 道,分为三个部分:

  • 填空题(3 道):在 SPACE 标记处填入正确代码
  • 改错题(5 道):找出 FOUND 标记处的错误并修正
  • 编程题(4 道):在 Program 标记处编写函数实现

每道题均包含题目描述、解题思路、完整代码(带详细注释)、错误分析(改错题)、关键知识点。涉及的考点覆盖字符串处理、指针运算、数组操作、ASCII 码、循环结构等 C 语言核心知识。


一、填空题#

填空题要求在 /***********SPACE***********/ 标记的位置填入正确的代码,使程序能正常运行并得到预期结果。

填空题1 - 字符串中数字累加和#

题目描述#

给定程序中,函数 fun 的功能是:将形参 s 所指字符串中的数字字符转换成对应的数值,计算出这些数值的累加和作为函数值返回。

例如,形参 s 所指的字符串为 abs5def126jkm8,程序执行后的输出结果为 22

计算过程:5 + 1 + 2 + 6 + 8 = 22

解题思路#

  1. 遍历字符串中的每一个字符
  2. 使用 isdigit() 函数判断当前字符是否为数字字符('0' ~ '9'
  3. 若是数字字符,则通过 *s - 48(或 *s - '0')将字符转换为对应的数值
  4. 将转换后的数值累加到 sum
  5. 移动指针到下一个字符,直到字符串结束
  6. 最后返回累加和

完整代码#

#include <stdio.h>
#include <string.h>
#include <ctype.h>
int fun(char* s)
{
int sum = 0;
while (*s) // 遍历字符串,直到遇到 '\0'
{
if (isdigit(*s)) // isdigit() 判断是否为数字字符 '0'~'9'
/***********SPACE***********/
sum += *s - 48; // 【填空1】数字字符转数值并累加
// '0' 的 ASCII 码是 48,所以 *s - 48 等价于 *s - '0'
// 例如 '5' 的 ASCII 码是 53,53 - 48 = 5
/***********SPACE***********/
s++; // 【填空2】指针后移,处理下一个字符
}
/***********SPACE***********/
return sum; // 【填空3】返回累加和
}
main()
{
char s[81];
int n;
printf("\nEnter a string:\n\n");
gets(s);
n = fun(s);
printf("\nThe result is: %d\n\n", n);
}

填空答案#

填空答案说明
填空1sum += *s - 48;字符转数值并累加,48 是 '0' 的 ASCII 码
填空2s++;指针后移到下一个字符
填空3return sum;返回累加结果

关键知识点#

  • isdigit() 函数:声明在 <ctype.h>,用于判断字符是否为十进制数字字符
  • 字符转数值:数字字符 '0''9' 的 ASCII 码为 4857,因此 ch - '0'ch - 48 可得到对应数值
  • 指针遍历字符串:通过 while (*s) 配合 s++ 逐个访问字符,直到遇到字符串结束符 '\0'

填空题2 - 插入字符#

题目描述#

下列给定程序中,函数 fun 的功能是:在形参 s 所指字符串中寻找与参数 c 相同的字符,并在其后插入一个与之相同的字符,若找不到相同的字符则不做任何处理。

例如:若 s 所指字符串为 "baacda"c 中的字符为 a,执行后 s 所指字符串为 "baaaacdaa"

插入过程:每个 a 后面都插入一个 a,所以 3 个 a 变成对应位置后各插一个

解题思路#

  1. for 循环遍历字符串 s 中的每个字符
  2. s[i] == c 时,需要在该位置后插入一个字符 c
  3. 插入前需要计算从当前位置到字符串末尾的长度 n(用于确定后移范围)
  4. 将插入位置后的所有字符整体后移一位,腾出插入空间
  5. 在腾出的位置写入字符 c
  6. 插入后 i = i + 1 跳过刚插入的字符,避免被当作”原字符”再次处理导致死循环

完整代码#

#include <stdio.h>
void fun(char* s, char c)
{
int i, j, n;
/***********SPACE***********/
for (i = 0; s[i] != '\0'; i++) // 【填空1】遍历整个字符串
if (s[i] == c) // 找到与 c 相同的字符
{
/***********SPACE***********/
n = i; // 【填空2】从当前位置开始计算字符串剩余长度
while (s[i + 1 + n] != '\0') // 注意:此循环计算的是 i+1+n 位置
n++; // n 最终表示从 i 开始到结尾的字符数(不含'\0')
for (j = i + n + 1; j > i; j--) // 从后往前把字符后移一位
s[j + 1] = s[j]; // s[j+1] = s[j],腾出 i+1 的位置
/***********SPACE***********/
s[j + 1] = c; // 【填空3】在原字符后插入相同的字符 c
i = i + 1; // 跳过刚插入的字符,避免重复处理
}
}
main()
{
char s[80] = "baacda", c;
printf("\nThe string: %s\n", s);
printf("\nInput a character: ");
scanf("%c", &c);
fun(s, c);
printf("\nThe result is: %s\n", s);
}

填空答案#

填空答案说明
填空1for (i = 0; s[i] != '\0'; i++)遍历字符串直到结束符
填空2n = i;初始化 n 为当前位置,配合后续 while 计算剩余长度
填空3s[j + 1] = c;在腾出的位置插入字符 c

关键知识点#

  • 字符插入操作:插入前必须先将后续字符后移,从后往前移动避免覆盖
  • 避免重复处理:插入字符后要将循环变量 i 加 1,跳过新插入的字符
  • 字符串后移技巧for (j = end; j > pos; j--) s[j+1] = s[j]; 是经典的字符后移模板

填空题3 - 最长字符串#

题目描述#

给定程序中,函数 fun 的功能是:求出形参 ss 所指字符串数组中最长字符串的长度,其余字符串左边用字符 * 补齐,使其与最长的字符串等长。字符串数组中共有 M 个字符串,且串长小于 N

例如字符串数组 {"shanghai","guangzhou","beijing","tianjing","cchongqing"},最长的是 "cchongqing"(10 个字符),其余字符串左边补 * 到 10 个字符。

解题思路#

  1. 第一遍遍历:找出最长字符串的长度 n 及其索引 k
  2. 第二遍遍历:对每个非最长字符串 ss[i]i != k):
    • 先将该字符串的内容(含 '\0')整体右移到与最长串对齐的位置
    • 再在左侧空出的位置填充字符 '*'

完整代码#

#include <stdio.h>
#include <string.h>
#define M 5
#define N 20
void fun(char (*ss)[N])
{
int i, j, k = 0, n, m, len;
// 第一遍:找出最长字符串及其长度
for (i = 0; i < M; i++)
{
len = strlen(ss[i]);
if (i == 0) n = len; // 第一个字符串的长度作为初始值
if (len > n)
{
/***********SPACE***********/
n = len; k = i; // 【填空1】更新最大长度 n 和最长串索引 k
}
}
// 第二遍:对其余字符串左补 '*'
for (i = 0; i < M; i++)
if (i != k) // 跳过最长字符串本身
{
m = n; // m 用于从右端开始放置字符
len = strlen(ss[i]); // 当前字符串长度
/***********SPACE***********/
for (j = len; j >= 0; j--) // 【填空2】将原字符串(含'\0')右移到对齐位置
ss[i][m--] = ss[i][j]; // 从 ss[i][len] 开始(含'\0'),整体右移
for (j = 0; j < n - len; j++) // 左侧空出的 n-len 个位置
/***********SPACE***********/
ss[i][j] = '*'; // 【填空3】填充 '*'
}
}
main()
{
char ss[M][N] = { "shanghai","guangzhou","beijing","tianjing","cchongqing" };
int i;
printf("\nThe original strings are :\n");
for (i = 0; i < M; i++) printf("%s\n", ss[i]);
printf("\n");
fun(ss);
printf("\nThe result:\n");
for (i = 0; i < M; i++)
printf("%s\n", ss[i]);
}

运行结果示例#

The original strings are :
shanghai
guangzhou
beijing
tianjing
cchongqing
The result:
**shanghai
guangzhou
***beijing
*tianjing
cchongqing

填空答案#

填空答案说明
填空1n = len; k = i;记录最长串的长度和索引
填空2for (j = len; j >= 0; j--)从字符串末尾(含 '\0')开始右移
填空3ss[i][j] = '*';左侧空位填充 '*'

关键知识点#

  • 二维字符数组作函数参数char (*ss)[N] 是指向含 N 个元素的字符数组的指针,等价于 char ss[][N]
  • 字符串右对齐填充:先右移原内容(含结束符 '\0'),再在左侧补字符
  • strlen() 函数:声明在 <string.h>,返回字符串长度(不含 '\0'

二、改错题#

改错题在 /***********FOUND***********/ 标记处存在错误,需要找出并修正。下面每道题先分析可能的错误形式,再给出正确代码

改错题1 - 统计0的个数#

题目描述#

下列给定程序中,函数 fun 实现的功能是:统计一个无符号整数中各位数字值为 0 的个数,通过形参传回主函数,并把该整数中各位上最大的数字值作为函数值返回。

例如:若输入无符号整数 30800,则数字值为 0 的位的个数为 3,各位上数字值最大的是 8

30800 的各位:3、0、8、0、0,其中 0 出现 3 次,最大数字是 8

错误分析#

错误位置可能的错误形式错误原因正确写法
FOUND 1if (t = 0)把比较运算符 == 误写成赋值运算符 =,导致条件恒为假(且破坏 t 的值)if (t == 0)
FOUND 2zero = count;zero 是指针,应通过解引用 *zero 修改主调函数的变量;直接赋值给指针是错误的*zero = count;

解题思路#

  1. 使用 do-while 循环依次取出整数的每一位(至少执行一次,处理 n=0 的情况)
  2. n % 10 取最低位数字,n / 10 去掉最低位
  3. 统计值为 0 的位数到 count
  4. 同时记录出现过的最大数字到 max
  5. 通过指针参数 *zero 返回 0 的个数,函数返回最大数字

完整代码#

#include <stdio.h>
int fun(unsigned n, int* zero)
{
int count = 0, max = 0, t;
do
{
t = n % 10; // 取出最低位数字
/***********FOUND***********/
if (t == 0) // 【修正】比较运算符用 ==,不能用 =
count++; // 若该位为 0,计数器加 1
if (max < t) // 若该位比 max 大,更新 max
max = t;
n = n / 10; // 去掉最低位
} while (n); // 直到 n 为 0 时结束循环
/***********FOUND***********/
*zero = count; // 【修正】通过解引用指针,把 count 传回主函数
return max; // 返回最大数字
}
main()
{
unsigned n;
int zero, max;
printf("\nInput n(unsigned): ");
scanf("%d", &n);
max = fun(n, &zero);
printf("\nThe result: max=%d\n zero=%d\n", max, zero);
}

关键知识点#

  • === 的区别== 是比较运算符,= 是赋值运算符,在 if 条件中混用是常见错误
  • 指针参数传回结果:要通过函数参数修改主调函数的变量,必须传入变量地址,并在函数内通过 *指针 解引用
  • do-while 循环:先执行后判断,至少执行一次,适合”至少处理一位”的场景
  • 取位运算n % 10 取个位,n / 10 去个位,是处理整数各位的经典套路

改错题2 - 第一个字母改大写#

题目描述#

下列给定程序的功能是:读入一个英文文本行,将其中每个单词的第一个字母改成大写,然后输出此文本行(这里”单词”是指由空格隔开的字符串)。

例如:若输入 "I am a student to take the examination",则应输出 "I Am A Student To Take The Examination"

错误分析#

错误位置可能的错误形式错误原因正确写法
FOUNDvoid upfst(char p)参数应为字符指针(数组名),写成 char p 只能传单个字符,无法遍历字符串void upfst(char* p)

解题思路#

  1. 使用标志位 k 区分当前是否在单词内部:
    • k = 0:表示在单词开头(下一个非空格字符是首字母,需大写)
    • k = 1:表示已在单词中间
  2. 遍历字符串:
    • k == 1(在单词中):遇到空格则 k = 0,表示即将进入新单词
    • k == 0(在单词开头):遇到非空格字符,则将其转为大写并置 k = 1
  3. 使用 toupper() 函数将小写字母转换为大写

完整代码#

#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
/***********FOUND***********/
void upfst(char* p) // 【修正】参数必须是 char* 指针,才能遍历字符串
{
int k = 0; // k=0 表示在单词开头,k=1 表示在单词中间
for (; *p; p++) // 遍历字符串直到 '\0'
{
if (k) // 若已在单词中间
{
if (*p == ' ') // 遇到空格,说明下一个非空格是新单词首字母
k = 0;
}
else // 若在单词开头
{
if (*p != ' ') // 当前字符非空格,即是单词首字母
{
k = 1; // 标记已进入单词
*p = toupper(*p); // 将首字母转为大写
}
}
}
}
void main()
{
char chrstr[81];
system("CLS");
printf("\nPlease enter an English text line: ");
gets(chrstr);
printf("\nBofore changing:\n %s", chrstr);
upfst(chrstr); // 数组名作实参,传递首地址
printf("\nAfter changing:\n %s\n", chrstr);
}

关键知识点#

  • 数组作函数参数:数组名传递时退化为指针,形参必须声明为 char*char[],不能是 char
  • toupper() 函数:声明在 <ctype.h>,将小写字母转换为大写,非小写字母原样返回
  • 状态标志位:用一个整型变量 k 记录”是否在单词内”的状态,是字符串处理的常用技巧

改错题3 - 查找字符串最后出现地址#

题目描述#

下列给定程序中函数 fun 的功能是:求出 s 所指字符串中最后一次出现t 所指字符串的地址,并通过函数值返回;若未找到,则函数值为 NULL

例如:当字符串 s 中内容为 "abcdabfabcdx"t 中内容为 "ab" 时,输出结果应是 "abcdx"(最后一次出现的 ab 之后的内容)。当 t 中内容为 "abd" 时,输出 "Not found!"

错误分析#

错误位置可能的错误形式错误原因正确写法
FOUND 1a = s; 或缺少初始化若初始化为 s,则未找到时返回的不是 NULL;若不初始化,a 是野指针a = NULL;
FOUND 2if (*r = *p)if (r == p)= 是赋值(恒为真导致死循环);r == p 比较的是指针地址而非字符内容if (*r == *p)

解题思路#

  1. 初始化 a = NULL,表示尚未找到匹配
  2. 外层循环:以 s 中每个字符作为起始位置
  3. 内层循环:从该位置开始,逐个字符与 t 比较
    • 字符相同则 r++p++ 继续比较下一个
    • 字符不同则 break 退出内层循环
  4. 内层循环结束后,若 *r == '\0' 说明 t 已全部匹配,更新 a = s 记录本次匹配地址
  5. s++ 移动到下一个起始位置继续查找
  6. 由于每次匹配都更新 a,循环结束后 a 保存的是最后一次匹配的地址

完整代码#

#include <stdio.h>
#include <string.h>
char* fun(char* s, char* t)
{
char* p, * r, * a;
/***********FOUND***********/
a = NULL; // 【修正】初始化为 NULL,未找到时返回 NULL
while (*s) // 遍历 s 中每个位置作为起始点
{
p = s; // p 指向 s 当前位置
r = t; // r 指向 t 开头
while (*r) // 只要比对未到 t 的结尾
/***********FOUND***********/
if (*r == *p) // 【修正】比较字符内容,用 == 而非 =
{
r++; // t 的指针后移
p++; // s 的指针后移
}
else // 字符不匹配
break; // 退出内层循环
if (*r == '\0') // 若 t 全部匹配完成
a = s; // 更新 a 为当前匹配的首地址
s++; // s 后移一位,继续查找下一个位置
}
return a; // 返回最后一次匹配的首地址(或 NULL)
}
main()
{
char s[100], t[100], * p;
printf("\nPlease enter string S :");
scanf("%s", s);
printf("\nPlease enter substring t :");
scanf("%s", t);
p = fun(s, t);
if (p) // 若 p 非 NULL
printf("\nThe result is : %s\n", p);
else // 若 p 为 NULL
printf("\nNot found !\n");
}

关键知识点#

  • 字符串查找算法:双层循环实现子串查找,外层遍历主串起点,内层逐字符比对
  • “最后一次”的实现技巧:不中断循环,每次找到都更新记录变量,循环结束后自然得到最后一次的结果
  • NULL 指针:表示”未找到”的常用约定,使用前需判断是否为 NULL
  • === 的陷阱:在 if 条件中误用 = 会导致赋值且条件恒为该值的真值

改错题4 - 找到最长子串#

题目描述#

下列给定程序中函数 fun 的功能是:从 N 个字符串中找出最长的串,并将其地址作为函数值返回。各字符串在主函数中输入,并放入一个字符串数组中。

错误分析#

错误位置可能的错误形式错误原因正确写法
FOUND 1char fun(char (*sq)[M])返回类型应为 char*(返回的是字符串地址),写成 char 只能返回单个字符char* fun(char (*sq)[M])
FOUND 2return sq; 或缺少 returnsq 是整个数组指针,类型不匹配;缺少 return 则函数无返回值return sp;

解题思路#

  1. 函数参数 char (*sq)[M] 是指向含 M 个元素的字符数组的指针,即指向二维字符数组的行
  2. 初始化 sp = sq[0],让 sp 指向第一个字符串
  3. 遍历所有 N 个字符串,用 strlen() 比较长度
  4. 若发现更长的字符串,则更新 sp 为该字符串的地址 sq[i]
  5. 循环结束后 sp 指向最长字符串,返回 sp

完整代码#

#include <stdio.h>
#include <string.h>
#define N 5
#define M 81
/***********FOUND***********/
char* fun(char (*sq)[M]) // 【修正】返回类型为 char*,因为要返回字符串地址
{
int i; char* sp;
sp = sq[0]; // 初始化 sp 指向第一个字符串
for (i = 0; i < N; i++)
if (strlen(sp) < strlen(sq[i])) // 若当前最长串比第 i 个串短
sp = sq[i]; // 更新 sp 为第 i 个串的地址
/***********FOUND***********/
return sp; // 【修正】返回 sp(最长串地址),不能返回 sq
}
main()
{
char str[N][M], * longest; int i;
printf("Enter %d lines :\n", N);
for (i = 0; i < N; i++)
gets(str[i]);
printf("\nThe %d string :\n", N);
for (i = 0; i < N; i++)
puts(str[i]);
longest = fun(str); // str 是二维数组名,传递给 sq
printf("\nThe longest string :\n");
puts(longest);
}

关键知识点#

  • 指向数组的指针char (*sq)[M] 是”指向含 M 个 char 元素的数组的指针”,与 char* sq[M](指针数组)完全不同
  • 二维数组与指针:二维数组名 str 作为实参传递时,形参声明为 char (*sq)[M]char sq[][M]
  • 返回字符串地址:函数返回类型声明为 char*,返回的字符串地址在主调函数中仍有效(因为指向的是主调函数中的数组)

改错题5 - 调整ASCII最大字符放首位#

题目描述#

下列给定程序中函数 fun 的功能是:从 p 所指字符串中找出 ASCII 码值最大的字符,将其放在第一个位置上,并将该字符前的原字符向后顺序移动

例如:调用 fun 函数之前给字符串输入 "ABCDeFGH",调用后字符串中的内容应为 "eABCDFGH"

‘e’ 的 ASCII 码(101)最大,原在位置 4,前移到首位后,“ABCD” 顺序后移一位

错误分析#

错误位置可能的错误形式错误原因正确写法
FOUND 1q = p[i];p[i] 是字符值,应赋给 maxq 是指针,应保存地址q = p + i;
FOUND 2while (q < p)while (q >= p)方向反了(qp 之后,应 q > p);>= 会多移一位覆盖首位while (q > p)

解题思路#

  1. 第一次遍历:找出 ASCII 码最大的字符及其位置
    • 假设第一个字符最大 max = p[0]
    • 遍历字符串,若发现更大的字符,更新 max 并用指针 q 记录其地址 q = p + i
  2. 第二次循环(字符后移):从最大字符位置 q 向前,将前一个字符后移
    • while (q > p):只要 q 还没退到首位
    • *q = *(q - 1):把前一个字符复制到当前位置
    • q--:指针前移
  3. 最后 p[0] = max,将最大字符放到首位

字符移动示例#

"ABCDeFGH" 为例,max = 'e'q 指向 p[4]

初始: A B C D e F G H
↑ p (q 指向 e)
第1次后移 (q=p+4): A B C D e F G H -> A B C D D F G H (把 D 复制到 e 位置)
第2次后移 (q=p+3): A B C D D F G H -> A B C C D F G H (把 C 复制到 D 位置)
第3次后移 (q=p+2): A B C C D F G H -> A B B C D F G H (把 B 复制到 C 位置)
第4次后移 (q=p+1): A B B C D F G H -> A A B C D F G H (把 A 复制到 B 位置)
现在 q == p,退出循环
p[0] = max: e A B C D F G H (把 e 放到首位)

完整代码#

#include <stdio.h>
void fun(char* p)
{
char max, * q; int i = 0;
max = p[i]; // 假设第一个字符最大
while (p[i] != 0) // 遍历字符串(0 即 '\0')
{
if (max < p[i]) // 若发现更大的字符
{
max = p[i]; // 更新最大字符值
/***********FOUND***********/
q = p + i; // 【修正】q 是指针,要保存地址 p+i,不能赋字符值
}
i++;
}
/***********FOUND***********/
while (q > p) // 【修正】q 在 p 之后,循环条件应为 q > p
{
*q = *(q - 1); // 把前一个字符后移到当前位置
q--; // 指针前移
}
p[0] = max; // 将最大字符放到首位
}
main()
{
char str[80];
printf("Enter a string: ");
gets(str);
printf("\nThe original string: ");
puts(str);
fun(str);
printf("\nThe string after moving: ");
puts(str); printf("\n\n");
}

关键知识点#

  • 指针与数组的关系p + i 等价于 &p[i],是第 i 个元素的地址
  • 字符顺序移动:从后往前逐个复制 *q = *(q-1); q--;,避免从前往后移动导致的覆盖问题
  • ASCII 码比较:字符比较的本质是比较 ASCII 码值,小写字母(97122)大于大写字母(6590)

三、编程题#

编程题要求在 /**********Program**********//********** End **********/ 之间编写函数实现,不能修改 main 函数和其他函数。

编程题1 - 二维数组变一维#

题目描述#

请编写函数 fun,该函数的功能是:将 MN 列的二维数组中的字符数据,按列的顺序依次放到一个字符串中。

例如:若二维数组中的数据为

W W W W
S S S S
H H H H

则字符串中的内容应是:WSHWSHWSHWSH

按列顺序:先取第0列(W,S,H),再第1列(W,S,H)…共4列

解题思路#

  1. 外层循环控制列 j0N-1
  2. 内层循环控制行 i0M-1
  3. 每次取出 s[i][j] 放入一维数组 b[k]k 递增
  4. 全部放完后在末尾添加字符串结束符 '\0'

完整代码#

#include<stdio.h>
#define M 3
#define N 4
void fun(char (*s)[N], char* b)
{
/**********Program**********/
int i, j, k = 0;
for (j = 0; j < N; j++) // 外层循环控制列(先列后行 = 按列顺序)
{
for (i = 0; i < M; i++) // 内层循环控制行
{
b[k++] = s[i][j]; // 取第 j 列第 i 行的元素放入 b
}
}
b[k] = '\0'; // 添加字符串结束符
/********** End **********/
}
void main()
{
char a[100];
char w[M][N] = { { 'W', 'W', 'W', 'W'},{'S', 'S', 'S', 'S'},
{'H', 'H', 'H', 'H'} };
int i, j;
printf("The matrix:\n");
for (i = 0;i < M;i++)
{
for (j = 0;j < N;j++)
printf("%3c", w[i][j]);
printf("\n");
}
fun(w, a);
printf("The A string:\n");
puts(a);
printf("\n\n");
}

关键知识点#

  • 二维数组按列遍历:外层循环列、内层循环行,即可实现按列优先顺序读取
  • 二维数组作函数参数char (*s)[N] 接收二维字符数组,第二维大小 N 必须指定
  • 字符串结束符:手动构造字符串时,末尾必须添加 '\0',否则 putsprintf("%s") 等会越界读取

编程题2 - 删除字符#

题目描述#

编写函数 fun,其功能是:将 s 所指字符串中 ASCII 值为奇数的字符删除,剩余字符形成的新串放在 t 所指数组中。

例如:若 s 所指字符串中的内容为 "ABCDEFG12345",其中字符 A(ASCII 65,奇数)、字符 1(ASCII 49,奇数)都应当删除,其它依此类推。最后 t 所指的数组中的内容应是 "BDF24"

保留偶数 ASCII 字符:B(66) D(68) F(70) 2(50) 4(52)

解题思路#

  1. 遍历字符串 s 中的每个字符
  2. s[i] % 2 == 0 判断 ASCII 值是否为偶数
  3. 将 ASCII 值为偶数的字符依次复制到数组 t
  4. 注意:遍历结束后必须在 t 末尾添加 '\0',否则 t 不是合法字符串

易错点:原题代码未添加 '\0',会导致输出结果错误(t 数组末尾有未初始化的脏数据)。下面给出修正后的完整版本。

完整代码#

#include <stdio.h>
#include <string.h>
void fun(char* s, char t[])
{
/**********Program**********/
int i, j = 0;
for (i = 0; s[i] != '\0'; i++) // 遍历字符串 s
{
if (s[i] % 2 == 0) // ASCII 值为偶数时保留
{
t[j++] = s[i]; // 复制到 t 数组
}
}
t[j] = '\0'; // 必须添加字符串结束符!
/********** End **********/
}
void main()
{
char s[100], t[100];
printf("\nPlease enter string S:");
scanf("%s", s);
fun(s, t);
printf("\nThe result is: %s\n", t);
}

关键知识点#

  • ASCII 码奇偶性判断ch % 2 == 0 判断偶数,ch % 2 != 0 判断奇数
  • 字符过滤模板:用两个下标,i 遍历原串,j 指向新串写入位置,符合条件的才复制
  • 字符串结束符的重要性:构造新字符串必须以 '\0' 结尾,否则字符串函数无法正确判断边界

编程题3 - 统计数字个数#

题目描述#

请编写函数 fun,其功能是:统计 s 所指字符串中的数字字符个数,并作为函数值返回。

例如:s 所指字符串中的内容是 "2def35adh25 3kjsdf 7/kj8655x",函数 fun 返回值为 11

数字字符:2、3、5、2、5、3、7、8、6、5、5,共 11 个

解题思路#

  1. 遍历字符串中的每个字符
  2. 使用条件 s[i] >= '0' && s[i] <= '9' 判断是否为数字字符
  3. 每找到一个数字字符,计数器加 1
  4. 遍历结束后返回计数器的值

完整代码#

#include <stdio.h>
int fun(char *s)
{
/**********Program**********/
int i, count = 0;
for (i = 0; s[i] != '\0'; i++) // 遍历字符串
{
if (s[i] >= '0' && s[i] <= '9') // 判断是否为数字字符 '0'~'9'
{
count++; // 计数器加 1
}
}
return count; // 返回数字字符个数
/********** End **********/
}
void main()
{
char *s = "2def35adh25 3kjsdf 7/kj8655x";
printf("%s\n", s);
printf("%d\n", fun(s));
}

关键知识点#

  • 数字字符判断s[i] >= '0' && s[i] <= '9',也可使用 isdigit(s[i])(需 <ctype.h>
  • 计数器模式:初始化 count = 0,满足条件时 count++,最后返回 count
  • 字符范围判断:利用字符的有序性,通过比较运算符判断字符属于哪个范围

编程题4 - 返回n-1的数#

题目描述#

编写函数 funw 是一个大于 10 的无符号整数,若 wn(n≥2)位的整数,则函数求出 w后 n-1 位的数作为函数值返回。

例如:w 值为 5923,则函数返回 923;若 w 值为 923,则函数返回 23

5923 有 4 位,返回后 3 位 923;923 有 3 位,返回后 2 位 23

解题思路#

  1. 先计算 w 的位数对应的 10 的幂 t
    • 复制 wn,循环 n = n / 10 直到 n == 0,每次循环 t *= 10
    • 例如 w = 5923:循环 4 次后 t = 10000(比 w 多一位)
  2. t / 10 得到与 w 位数相同的 10 的幂(如 1000
  3. w % (t / 10) 取余,得到去掉最高位后的数(如 5923 % 1000 = 923

计算过程示例#

w = 5923 为例:

循环次数n 的值t 的值
初始59231
第1次59210
第2次59100
第3次51000
第4次010000

循环结束,t = 10000t / 10 = 10005923 % 1000 = 923

完整代码#

#include<conio.h>
#include<stdio.h>
#include<stdlib.h>
unsigned fun(unsigned w)
{
/**********Program**********/
int n = w, t = 1; // n 用于统计位数,t 用于累乘 10
while (n > 0) // 循环直到 n 为 0
{
t = t * 10; // t 每次乘 10
n = n / 10; // n 去掉最低位
}
// 循环结束后,t 是 w 位数 +1 位的 10 的幂
// 例如 w=5923(4位),t=10000(5位)
return w % (t / 10); // t/10 得到与 w 同位的 10 的幂,取余去掉最高位
/********** End **********/
}
void main()
{
unsigned x;
printf("Enter a unsigned integer number: ");
scanf("%u", &x);
printf("The original data is:%u\n", x);
if (x < 10) // w 必须大于 10(至少 2 位)
printf("Data error! ");
else
printf("The result :%u\n", fun(x));
}

关键知识点#

  • 求整数位数:通过 n = n / 10 循环除以 10,直到为 0,循环次数即为位数
  • 10 的幂计算:在统计位数的同时累乘 10,可得到对应位数的 10 的幂
  • 取余去高位w % (10^(n-1)) 可以去掉最高位,保留后 n-1 位
  • %u 格式符:用于输入输出无符号整数(unsigned

总结#

知识点回顾#

类别涉及知识点
字符串处理isdigit()toupper()strlen()gets()puts()、字符串结束符 '\0'
指针指针遍历字符串、指针参数传回结果(*p 解引用)、返回指针的函数、指向数组的指针 char (*p)[N]
数组二维数组按列遍历、二维数组作函数参数、字符数组操作
ASCII 码字符与数值转换(ch - '0')、ASCII 奇偶性判断、字符大小比较
循环结构do-whilewhilefor 的选用;双层循环实现子串查找
常见错误=== 混用、指针未初始化、缺少 '\0'、参数类型错误(charchar*

解题技巧#

  1. 填空题:先理解程序整体功能,再分析空格处应有的逻辑,注意变量类型匹配
  2. 改错题:重点关注 FOUND 标记附近,常见错误类型有:运算符错误(=/==)、类型错误(指针/非指针)、初始化错误(NULL)、循环条件错误(方向、边界)
  3. 编程题:理清输入输出和函数签名,先用伪代码描述算法,再翻译为 C 代码,注意边界处理和字符串结束符

易错点提醒#

  • 构造新字符串时必须在末尾添加 '\0'
  • 函数参数若要通过形参修改实参,必须传地址并用 * 解引用
  • if 条件中比较相等用 ==,赋值用 =,二者不可混用
  • 指针使用前必须初始化,未找到目标时返回 NULL 是良好习惯
  • 二维数组作参数时,第二维大小必须指定(如 char (*s)[N]
分享

如果这篇文章对你有帮助,欢迎分享给更多人!

端午大礼包-C语言练习题
https://blog.radarweb.top/posts/c/端午大礼包-c语言练习题/
作者
Sherry
发布于
2026-06-01
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

目录