原文发布于Hibiki33’s Blog,转载请标明出处。
代码仅供参考,查重结果自负。
1. 扩展字符A
【问题描述】
从键盘输入包含扩展符 '-'
的字符串,将其扩展为等价的完整字符,例如将 a-d
扩展为 abcd
,并输出扩展后的字符串。
要求:只处理[a-z]
、[A-Z]
、[0-9]
范围内的字符扩展,即只有当扩展符前后的字符同时是小写字母、大写字母或数字,并且扩展符后的字符大于扩展符前的字符时才进行扩展,其它情况不进行扩展,原样输出。例如:a-R
、D-e
、0-b
、4-B
等字符串都不进行扩展。
【输入形式】
从键盘输入包含扩展符的字符串
【输出形式】
输出扩展后的字符串
【输入样例1】
ADEa-g-m02
【输出样例1】
ADEabcdefghijklm02
【输入样例2】
cdeT-bcd
【输出样例2】
cdeT-bcd
【样例说明】
将样例1的输入ADEa-g-m02
扩展为:ADEabcdefghijklm02
;样例2的输入cdeT-bcd
中,扩展符前的字符为大写字母,扩展符后的字符为小写字母,不在同一范围内,所以不进行扩展。
【评分标准】
该题要求扩展字符,提交程序文件 expand.c
。
【参考答案】
按照题目要求分析和输出即可,注意判断 [a-z]
、[A-Z]
和 [0-9]
可用 <ctype.h>
中现成的函数,没必要自己造轮子。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
int is_fit(char c1, char c2)
{
if (((islower(c1) && islower(c2))
|| (isupper(c1) && isupper(c2))
|| (isdigit(c1) && isdigit(c2))) && (c1 < c2))
{
return 1;
}
return 0;
}
int main()
{
char str_in[100];
gets(str_in);
char *start = str_in;
char *end;
while ((end = strchr(start, '-')) != NULL)
{
while(start != end)
{
printf("%c", *start++);
}
if (is_fit(*(end - 1), *(end + 1)))
{
for (char i = *(end - 1) + 1; i != *(end + 1); i++)
{
printf("%c", i);
}
}
else
{
printf("%c", *end++);
}
start++;
}
while (*start != 0)
{
printf("%c", *start++);
}
return 0;
}
2. 表达式计算(支持空格,连乘,连除)
【问题描述】
从标准输入中读入一个整数算术运算表达式,如5 - 1 * 2 * 3 + 12 / 2 / 2 =
。计算表达式结果,并输出。
要求:
1、表达式运算符只有+、-、*、/,表达式末尾的’=’字符表示表达式输入结束,表达式中可能会出现空格;
2、表达式中不含圆括号,不会出现错误的表达式;
3、出现除号/时,以整数相除进行运算,结果仍为整数,例如:5/3结果应为1。
【输入形式】
在控制台中输入一个以’=’结尾的整数算术运算表达式。
【输出形式】
向控制台输出计算结果(为整数)。
【样例1输入】
5 - 1 * 2 * 3 + 12 / 2 / 2 =
【样例1输出】
2
【样例2输入】
500 =
【样例2输出】
500
【样例1说明】
输入的表达式为5 - 1 * 2 * 3 + 12 / 2 / 2 =
,按照整数运算规则,计算结果为2,故输出2。
【样例2说明】
输入的表达式为500 = ,没有运算符参与运算,故直接输出500。
算法之一提示:
1、可以利用gets函数,读取整行表达式;
2、对于空格,可以考虑首先去除表达式中的所有空格
3、可以设一计数器用来记录已读取、但未参加运算的运算符的个数,根据该计数器来判断如何进行运算;
4、可以设计一函数:实现二元整数算术运算。
【评分标准】
该题要求输出整数表达式的计算结果,共有5个测试点。上传C语言文件名为example1c.c
。
【参考答案】
表达式计算是一种非常经典的题目,通过数据结构的学习你会掌握至少3种计算算术表达式的方法,之后还会出现括号等各种情况。单纯对这题来讲,因为不涉及括号,所以如果用最基本的方法,那么先算乘除后算加减即可。
简单的表达式计算:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int calc(int a, char op, int b)
{
switch (op)
{
case '+':
return a + b;
case '-':
return a - b;
case '*':
return a * b;
case '/':
return a / b;
default : break;
}
return 0;
}
int main()
{
char expr_in[200];
gets(expr_in);
int expr[200] = {0};
int sign_cnt = 0;
for (int i = 0, j = 0; expr_in[i] != '='; i++)
{
if (expr_in[i] == ' ')
{
continue;
}
if (isdigit(expr_in[i]) && !(j % 2)) // 偶数位存数字 奇数位存符号
{
expr[j] = expr[j] * 10 + expr_in[i] - '0';
}
else if (isdigit(expr_in[i]) && j % 2)
{
expr[++j] = expr_in[i] - '0';
}
else
{
expr[++j] = expr_in[i];
sign_cnt++;
}
}
for (int i = 0, flag = 1; i < sign_cnt; i++)
{
int pos = 2 * i + 1;
switch (expr[pos])
{
case '*':
case '/':
expr[pos + 1] = calc(expr[pos - 1], (char)expr[pos], expr[pos + 1]);
expr[pos - 1] = 0;
expr[pos] = 44 - flag; // 通过flag标记正负
break;
case '+':
flag = 1;
break;
case '-':
flag = -1;
break;
default: break;
}
}
for (int i = 0; i < sign_cnt; i++)
{
int pos = 2 * i + 1;
expr[pos + 1] = calc(expr[pos - 1], (char)expr[pos], expr[pos + 1]);
}
printf("%d", expr[2 * sign_cnt]);
return 0;
}
用压栈的方法计算:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int num[1005];
char sign[1005];
int pn = 0;
int ps = 0;
char c;
char scan()
{
char tmp;
do
{
tmp = getchar();
} while (tmp == ' ');
if (isdigit(tmp))
{
num[pn] = tmp - '0';
tmp = getchar();
while (isdigit(tmp))
{
num[pn] = num[pn] * 10 + tmp - '0';
tmp = getchar();
}
pn++;
}
while (tmp == ' ')
tmp = getchar();
return tmp;
}
int compare(char a, char b)
{
switch (a)
{
case '+':
case '-':
switch (b)
{
case '+':
case '-':
case '=':
case ')':
return 1;
default:
return -1;
}
case '*':
case '/':
switch (b)
{
case '(':
return -1;
default:
return 1;
}
case '(':
switch (b)
{
case ')':
return 0;
default:
return -1;
}
case ')':
return 1;
case '=':
return -1;
}
}
int operate(int a, int b, char x)
{
switch (x)
{
case '+':
return a + b;
case '-':
return a - b;
case '*':
return a * b;
case '/':
return a / b;
}
}
int main()
{
sign[ps++] = '=';
c = scan();
while (c != '=' || sign[ps - 1] != '=')
{
switch (compare(sign[ps - 1], c))
{
case -1:
sign[ps++] = c;
c = scan();
break;
case 1:
num[pn - 2] = operate(num[pn - 2], num[pn - 1], sign[ps - 1]);
num[--pn] = 0;
sign[--ps] = 0;
break;
case 0:
sign[--ps] = 0;
c = scan();
break;
}
}
printf("%d", num[pn - 1]);
return 0;
}
3. 小数形式与科学计数法转换(简)
【问题描述】
编写一个程序,将用小数表示的浮点数,转换成科学计数法的形式输出。输入的数据没有符号,小数点前后必有数字,且全为有效数据,即小数点后的末尾数字不为0;小数点前若只有一位数字,可以为0,否则小数点前的最高位数字不为0。
提示:以字符串形式保存相关数据。
【输入形式】
从控制台输入一小数,最后有回车换行符,所有输入的字符数不会超过100。
【输出形式】
以科学计数法形式输出数据。输出的数据由以下几部分构成:
1.底数部分是一个小数或整数,若为小数,则小数点前后必有数字,而且都为有效数字。即:小数点前只有一位大于0的数字,小数点后的末尾数字不能为0。若为整数,则只有一位数字,不带小数点。
2.必有小写字母“e”。
3.指数部分是一个整数,若大于等于0,则不带正号“+”。若小于0,则需要带负号“-”,且整数的最高位数字不为0。
【输入样例1】
0.000000000000002
【输出样例1】
2e-15
【输入样例2】
8.9845623489651700659
【输出样例2】
8.9845623489651700659e0
【输入样例3】
367298599999093453490394859509568659795603.4
【输出样例3】
3.672985999990934534903948595095686597956034e41
【样例说明】
以小数形式输入数据,然后转换成科学计数法形式输出。
【评分标准】
该题要求以科学计数法形式输出数据,提交程序文件名为notation.c
。
【参考答案】
没啥难度,看清题目就行。
#include <stdio.h>
#include <string.h>
char s[10000];
char zhengshu[10000];
char xiaoshu[10000];
int main()
{
int cnt1 = 0;
int cnt2 = 0;
int i = 0;
int j;
int tmp;
gets(s);
while (s[i] != '.')
{
zhengshu[cnt1++] = s[i++];
}
for (cnt2 = 0, i += 1; s[i] != '\0'; cnt2++)
{
xiaoshu[cnt2] = s[i++];
}
if (cnt1 > 1)
{
printf("%c.", zhengshu[0]);
for (j = 1; j < cnt1; j++)
{
printf("%c", zhengshu[j]);
}
for (j = 0; j < cnt2; j++)
{
printf("%c", xiaoshu[j]);
}
printf("e%d", cnt1 - 1);
}
else if (cnt1 == 1 && zhengshu[0] != '0')
{
printf("%c.", zhengshu[0]);
for (j = 0; j < cnt2; j++)
{
printf("%c", xiaoshu[j]);
}
printf("e0");
}
else
{
for (j = 0; j < cnt2; j++)
{
if (xiaoshu[j] != '0')
{
break;
}
}
printf("%c", xiaoshu[j]);
tmp = j + 1;
if (j + 1 < cnt2)
{
printf(".");
for (j++; j < cnt2; j++)
{
printf("%c", xiaoshu[j]);
}
printf("e-%d", tmp);
}
else
{
printf("e-%d", tmp);
}
}
return 0;
}
4. 超长正整数的减法
【问题描述】
编写程序实现两个超长正整数(每个最长80位数字)的减法运算。
【输入形式】
从键盘读入两个整数,要考虑输入高位可能为0的情况(如00083
)。
-
第一行是超长正整数A;
-
第二行是超长正整数B;
【输出形式】
输出只有一行,是长整数A减去长整数B的运算结果,从高到低依次输出各位数字。要求:若结果为0,则只输出一个0;否则输出的结果的最高位不能为0,并且各位数字紧密输出。
【输入样例】
234098
134098703578230056
【输出样例】
-134098703577995958
【样例说明】
进行两个正整数减法运算, 234098 -134098703578230056 = -134098703577995958
。
【评分标准】
完全正确得20分,每个测试点4分,提交程序文件名为subtract.c
。
【参考答案】
就是高精减,类比于列竖式。对于字符串的处理会比较麻烦。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void high_sub(char *up, char *down)
{
char res[200];
char *p = res;
for (int i = strlen(up) - 1; i >= 0; i--)
{
if (up[i] >= down[i])
{
res[i] = up[i] - down[i] + '0';
}
else
{
res[i] = 10 + up[i] - down[i] + '0';
int j = i - 1;
while (up[j] == 0)
{
up[j] = 9;
}
up[j]--;
}
}
while (*p == '0')
{
p++;
}
puts(p);
}
int main()
{
char a0[200];
char b0[200];
memset(a0, '0', 50);
memset(b0, '0', 50);
char *a1 = a0 + 50;
char *b1 = b0 + 50;
while ((*a1 = getchar()) == '0') {}
gets(a1 + 1);
while ((*b1 = getchar()) == '0') {}
gets(b1 + 1);
int l1 = strlen(a1);
int l2 = strlen(b1);
char *a;
char *b;
if (l1 > l2)
{
a = a1;
b = b1 - l1 + l2;
}
else
{
b = b1;
a = a1 - l2 + l1;
}
if (strcmp(a, b) > 0)
{
high_sub(a, b);
}
else if (strcmp(a, b) < 0)
{
printf("-");
high_sub(b, a);
}
else
{
printf("0");
}
return 0;
}
5. 全排列数的生成
【问题描述】输入整数N( 1 <= N <= 10 ),生成从1~N所有整数的全排列。
【输入形式】输入整数N。
【输出形式】输出有N!行,每行都是从1~N所有整数的一个全排列,各整数之间以空格分隔。各行上的全排列不重复。输出各行遵循“小数优先”原则, 在各全排列中,较小的数尽量靠前输出。如果将每行上的输出看成一个数字,则所有输出构成升序数列。具体格式见输出样例。
【样例输入1】1
【样例输出1】1
【样例说明1】输入整数N=1,其全排列只有一种。
【样例输入2】3
【样例输出2】
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
【样例说明2】输入整数N=3,要求整数1、2、3的所有全排列, 共有N!=6行。且先输出1开头的所有排列数,再输出2开头的所有排列数,最后输出3开头的所有排列数。在以1开头的所有全排列中同样遵循此原则。
【样例输入3】10
【样例输出3】
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 10 9
1 2 3 4 5 6 7 9 8 10
1 2 3 4 5 6 7 9 10 8
1 2 3 4 5 6 7 10 8 9
1 2 3 4 5 6 7 10 9 8
1 2 3 4 5 6 8 7 9 10
1 2 3 4 5 6 8 7 10 9
1 2 3 4 5 6 8 9 7 10
1 2 3 4 5 6 8 9 10 7
……………………
【样例说明3】输入整数N=10,要求整数1、2、3、……、10的所有全排列。上例显示了输出的前10行。
【运行时限】要求每次运行时间限制在20秒之内。超出该时间则认为程序错误。提示:当N增大时,运行时间将急剧增加。在编程时要注意尽量优化算法,提高运行效率。
【评分标准】该题要求输出若干行整数。
【参考答案】
这题的难点在于怎样按照字典序输出,并且要保证时间复杂度。如果有一定知识储备不难发现这题是一道典型的DFS,如果不知道可以学习这个回溯算法入门级详解 + 练习 - 全排列 。
#include <stdio.h>
#include <stdlib.h>
int finished[10];
int answer[10];
int n;
void dfs(int cnt)
{
if (cnt == n)
{
for (int i = 0; i < n; i++)
{
printf("%d ", answer[i]);
}
printf("\n");
return;
}
else
{
for (int i = 1; i <= n; i++)
{
if (!finished[i])
{
answer[cnt] = i;
finished[i] = 1;
dfs(cnt + 1);
finished[i] = 0;
}
}
}
}
int main()
{
scanf("%d", &n);
dfs(0);
return 0;
}