前言
本文来讲解:
查找字母以及其他字符个数、数字字符串转双精度值、二维数组上下三角区域数据对调C语言二级,最好是能弄懂每一道程序题,这样会对自己的编程能力有很大的提升
适用人群:
- 要参加C语言二级
- 中职学生
- 想提升C语言编程思维
- C语言爱好者
一、程序填空题 --- 查找字母以及其他字符个数
难度:⭐
题目
以下程序的功能是:
统计字符串 (长度不超过 1000 个字符) 中每个字母的个数(不区分大小写),若字符不是字母,则统一归为其他字符。
请在程序的下划线处填入正确的内容并把下划线删除,使程序得出正确的结果。
代码如下:
在1️⃣2️⃣3️⃣处填空
#include<stdio.h> #include<string.h> void countstr(char *st,int cutor[]); void main() { char s[1000]; /**********************found***********************/ int counters[27]= ___1️⃣___,i; printf("Input a string\n"); gets(s); countstr(s,counters); /**********************found***********************/ for(i=0; i<=___2️⃣___;i++) printf("%c : %d\n",i+65,counters[i]); printf("others : %d\n",counters[i]); } void countstr(char *st,int cutor[]) { int i,j; char t; i=strlen(st); for(j=0;j<i;j++) { t=st[j]; if(t>='a'&&t<='z') t=t-'a'+'A'; if(t>='A'&&t<='Z') /**********************found***********************/ cutor[t- ___3️⃣___]++; else cutor[26]++; } }
分析
根据题意以及代码可知
利用27个元素的cutor数组存储26个元素以及1个其他符号
当遇到字母a或A(不区分大小写),则在0号元素位置加一
也就是:'A' - 'A' ----> '任意字母' - 'A' 就是对应的数组下标了
解答代码如下:
#include<stdio.h> #include<string.h> void countstr(char *st,int cutor[]); void main() { char s[1000]; /**********************found***********************/ //因为数组里存放的是26个字母以及其他字符的个数 //所以要先初始化为 0 int counters[27]= 1️⃣{0},i; printf("Input a string\n"); gets(s); countstr(s,counters); /**********************found***********************/ //因为由for循环下面的输出语句可以知道 //最下面个的是输出其他字符 //那么当前的这个循环就是输出字母 //字母有26个,从0开始就是到25 for(i=0; i<=2️⃣25;i++) printf("%c : %d\n",i+65,counters[i]); printf("others : %d\n",counters[i]); } void countstr(char *st,int cutor[]) { int i,j; char t; i=strlen(st); for(j=0;j<i;j++) { t=st[j]; if(t>='a'&&t<='z') t=t-'a'+'A'; if(t>='A'&&t<='Z') /**********************found***********************/ //因为这里要保存某个字母的出现次数 //所以就要将对应的字母转换为相应的元素 //也就是字母 - 字符A就可以求得当前元素位置了 cutor[t- 3️⃣'A']++; else cutor[26]++; } }
二、程序修改 --- 数字字符串转双精度值
难度:⭐⭐⭐
题目
函数 int strtoval (char pst [], double* p) 的功能是,将 pst 中带符号的数字字符串转换成双精度数值,直到遇到非数字字符为止。函数返回值为 1 表示转换成功,为 0 表示转换失败,函数成功转换后的数值存储在指针 p 所指的存储单元中。
如:
+123.65a 转换数值后输出 + 123.650000,函数返回值为 1。
-32-3 转换数值后输出 - 32.000000,函数返回值为 1。
56.76a 转换数值后输出 + 56.760000,函数返回值为 1。
283.125 转换数值后输出 + 283.125000,函数返回值为 1。
对 + a8.6 转换失败,函数返回值为 0,输出出错信息。
请改正函数 fun 中指定部位的错误,使它能得出正确的结果。
注意:不要改动 main 函数,不得增行或删行,也不得更改程序的结构。
代码如下:
在代码中找出3个错误并修改
#include<stdio.h> int strtoval(char pst[],double* p) { int sucs; int plus; int i=0; double frac=0.1; *p=0.0; while(pst[i]==' ') i++; /**********************found***********************/ if(pst[i]=='+'&& pst[i]>='0'&&pst[i]<='9') { plus=1; sucs=1; } else if(pst[i]=='-') { plus=0; sucs=1; } else { sucs=0; return sucs; } /**********************found***********************/ if(pst[i]=='+'&& pst[i]=='-') i++; if(pst[i]==' ') i++; if(!(pst[i]>='0'&&pst[i]<='9')) { sucs=0; return sucs; } while(pst[i]!='\0') { if(pst[i]>='0'&&pst[i]<='9') { *p=*p*10+pst[i]-'0'; i++; } else if(pst[i]== '.') break; else { if(plus==0) *p=-1.0**p; return sucs; } } /**********************found***********************/ if(pst[i]!= '.') { i++; while(pst[i]!='\0') { if(pst[i]>='0'&&pst[i]<='9') { *p=*p+(pst[i]-'0')*frac; frac/=10; i++; } else { if(plus==0) *p=-1.0**p; return sucs; } } return sucs; } return sucs; } void main() { char str[][100]={ " +123.65a", " -32-3", " 56.76a", " + 283.125", " +a8.6" }; double a; int i; for(i=0;i<5;i++) if(strtoval(str[i],&a)==1) printf("vol=%f\n",a); else printf("error,the string is %s\n",str[i]); }
分析
简要分析题意:
函数 strtoval 的功能是将字符串 pst 转换为双精度浮点数
并将结果存储在指针 p 所指向的内存中
函数返回一个整数,表示转换是否成功,1 表示成功,0 表示失败
根据题意可以知道(可以先分析变量的作用):
sucs 用于检测转换是否成功
plus 用于标记数值是正数还是负数
frac 用于处理小数部分,初始值为 0.1
解答代码如下:
#include<stdio.h> int strtoval(char pst[], double* p) { // sucs 用于记录转换是否成功,1 表示成功,0 表示失败 int sucs; // plus 用于记录数值是正数还是负数,1 表示正数,0 表示负数 int plus; // i 作为数组的索引,用于遍历字符串 int i = 0; // frac 用于处理小数部分,初始值为 0.1,后续每处理一位小数就缩小 10 倍 double frac = 0.1; // 将指针 p 所指向的内存初始化为 0.0,为后续存储转换后的双精度浮点数做准备 *p = 0.0; // 跳过字符串开头的空格字符 // 因为输入的字符串可能在数字或符号前有多个空格,所以使用循环跳过这些空格 while (pst[i] == ' ') i++; /**********************found***********************/ // 如果当前字符是 '+' 或者是数字字符 // 这意味着字符串开头可能是正号或者直接是数字 //所以要用逻辑或 if (pst[i] == '+'|| (pst[i] >= '0' && pst[i] <= '9')) { // 记录为正数 plus = 1; // 记录转换可能成功,因为当前字符符合预期,后续还需继续检查 sucs = 1; } // 如果当前字符是 '-' // 表示字符串代表的是一个负数 else if (pst[i] == '-') { // 记录为负数 plus = 0; // 记录转换可能成功,后续同样要继续检查剩余字符 sucs = 1; } // 若既不是 '+'、'-' 也不是数字字符 // 说明字符串的起始部分不符合数字转换的要求 else { // 记录转换失败 sucs = 0; // 返回失败结果,终止函数执行 return sucs; } /**********************found***********************/ // 如果当前字符是 '+' 或者 '-' // 这是符号位,在后续处理数字时需要跳过 if (pst[i] == '+' || pst[i] == '-') // 跳过符号字符 i++; // 如果跳过符号后当前字符是空格 // 同样需要跳过,保证后续处理的是有效的数字字符 if (pst[i] == ' ') // 继续跳过空格 i++; // 如果当前字符不是数字字符 // 即跳过符号和可能的空格后,没有紧接着有效的数字,说明转换无法继续 if (!(pst[i] >= '0' && pst[i] <= '9')) { // 记录转换失败 sucs = 0; // 返回失败结果,终止函数执行 return sucs; } // 以下开始处理整数部分,直到字符串结束 while (pst[i] != '\0') { // 如果当前字符是数字字符 if (pst[i] >= '0' && pst[i] <= '9') { // 将当前数字字符转换为数字并累加到 *p 中 // 通过 pst[i] - '0' 把字符形式的数字转换为对应的数值,然后更新 *p *p = *p * 10 + (pst[i] - '0'); // 移动到下一个字符,继续处理后续内容 i++; } // 如果遇到小数点 // 意味着整数部分处理结束,要开始处理小数部分 else if (pst[i] == '.') // 跳出循环,开始处理小数部分 break; // 如果遇到非数字和非小数点的字符 // 说明字符串中出现了不符合数字格式的内容 else { if (plus == 0) *p = -1.0 * *p; return sucs; } } /**********************found***********************/ //如果是小数点的话,就进行小数位的运算 if(pst[i]== '.') { i++; while(pst[i]!='\0') { if(pst[i]>='0'&&pst[i]<='9') { //小数位的转换 //先让小数位的数字乘frac(初始为0.1) //之后再将frac*10也就是小数的又后一位 //就可以让其变成小数了 *p=*p+(pst[i]-'0')*frac; frac/=10; i++; } else { if(plus==0) *p=-1.0**p; return sucs; } } return sucs; } return sucs; } void main() { char str[][100] = { " +123.65a", " -32-3", " 56.76a", " + 283.125", " +a8.6" }; double a; int i; for (i = 0; i < 5; i++) { if (strtoval(str[i], &a) == 1) printf("vol=%f\n", a); else printf("error,the string is %s\n", str[i]); } }
程序修改题里面,如果没有思路,可以根据运算符来猜测怎样修改
因为计算机二级考试会有
/**********************found***********************/
这一行进行注释,那么这一行的下面一般就是程序错的位置了
小数位字符串转数字
这里提到了小数位数的字符串转小数,还是很实用的,这里再讨论一下这里
int frac = 0.1; int i; for(i = 0; pst[i] != '\0'; i++) { //小数位的转换 //先让小数位的数字乘frac(初始为0.1) //之后再将frac*10也就是小数的又后一位 //就可以让其变成小数了 *p=*p+(pst[i]-'0')*frac; frac/=10; i++; }
三、程序设计 --- 二维数组上下三角区域数据对调
难度:⭐⭐⭐
题目
编写一个函数 void change(int p[][N], int n),其功能是将一个 int 型二维数组的上下三角区域的数据对调,数组大小限制在 100X100。
例如,N = 7 时,有二维数组:
上下三角区域的数据对调后 a 数组内容为:
int a[N][N] = { {11,12,13,14,15,16,17}, {21,22,23,24,25,26,27}, {31,32,33,34,35,36,37}, {41,42,43,44,45,46,47}, {51,52,53,54,55,56,57}, {61,62,63,64,65,66,67}, {71,72,73,74,75,76,77} };
{11,21,31,41,51,61,71, 12,22,32,42,52,62,72, 13,23,33,43,53,63,73, 14,24,34,44,54,64,74, 15,25,35,45,55,65,75, 16,26,36,46,56,66,76, 17,27,37,47,57,67,77}
代码如下:
在change函数中编写
#include<stdio.h> #define N 7 void change(int p[][N],int n) { } void main() { int i,j; int a[N][N]={ {11,12,13,14,15,16,17}, {21,22,23,24,25,26,27}, {31,32,33,34,35,36,37}, {41,42,43,44,45,46,47}, {51,52,53,54,55,56,57}, {61,62,63,64,65,66,67}, {71,72,73,74,75,76,77} }; for(i=0;i<N;i++) { for(j=0;j<N;j++) printf("%4d",a[i][j]); printf("\n"); } change(a,N); printf("对调后的二维数组:\n"); for(i=0;i<N;i++) { for(j=0;j<N;j++) printf("%4d",a[i][j]); printf("\n"); } }
分析
本题看似偏难,但是往正确的方向去想了,找到规律了,就容易了
上下三角区域:也就是右斜中心线不动,对应的行和列进行对调,如图
所以可以先定义i和j两个变量来充当二维数组的行和列
i为行下标,j为列下标
解答代码如下:
#include<stdio.h> #define N 7 void change(int p[][N],int n) { int i, j; //控制行 for( i = 0; i < n; i++ ) //控制列 //i + 1是因为在i的左边是已经换好了的 //那么i的右边则是没有交换过的 //而与i相等没必要做交换所以j = i + 1; for( j = i+1; j < n; j++ ) { //行列行列进行交换 int flag = p[i][j]; p[i][j] = p[j][i]; p[j][i] = flag; } } void main() { int i,j; int a[N][N]={ {11,12,13,14,15,16,17}, {21,22,23,24,25,26,27}, {31,32,33,34,35,36,37}, {41,42,43,44,45,46,47}, {51,52,53,54,55,56,57}, {61,62,63,64,65,66,67}, {71,72,73,74,75,76,77} }; for(i=0;i<N;i++) { for(j=0;j<N;j++) printf("%4d",a[i][j]); printf("\n"); } change(a,N); printf("对调后的二维数组:\n"); for(i=0;i<N;i++) { for(j=0;j<N;j++) printf("%4d",a[i][j]); printf("\n"); } }
这里就是要注意列j的变化
希望本文对您有所帮助(* ̄︶ ̄)
本文专栏:C语言二级
苟日新,又日新,日日新