序
准备把之前的作业都再写一遍作为复习,方法可能并不是最佳的,如有大佬请指点啊~
扩展字符A(43min)
扩展字符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。
c
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<ctype.h>
void Expand(char*,int);
int main()
{
char str[1000];
gets(str);
int newlen=strlen(str);
int i=0;
while(str[i]!='\0')
{
if(i>0&&i<newlen&&str[i]=='-')
{
if(str[i-1]>='a'&&str[i+1]<='z'||str[i-1]>='A'&&str[i+1]<='Z'||str[i-1]>='0'&&str[i+1]<='9')
{
int oldlen=strlen(str);
Expand(str,i);
newlen=strlen(str);
i=i+(newlen-oldlen+1);
}
}
i++;
}
printf(str);
}
void Expand(char* str,int i)
{
int expandlen=str[i+1]-str[i-1]-1;
int movelen=strlen(str)-i-1;
memmove(str+i+1+expandlen-1,str+i+1,sizeof(char)*(movelen+1));
int j=i;
for(;j<i+expandlen;j++)
{
str[j]=str[j-1]+1;
}
}
注:此题有以下需要注意的地方
- 第一次做的时候还不知道有memmove这么好的函数,所以多写了好多行用于调整位置,但是这个函数在用的时候要注意,我们这里移动的是从 ' - ' 到字符串末尾,包含'\0',而在代码中,movelen记录的长度仅为有效长度,因此在使用memmove的时候,最后一个参数应该给movelen+1;
- 然后就是更新字符串以及下标这部分,我们画图看:
- 在扩展前,i为4,扩展后,怎么调整呢?
- 扩展后字符串长度 -- 扩展前字符串长度 + 1就是黄色部分的长度,我们设这个长度为x
- i + x是不是就相当于i指向了g?然后在if语句之外,还有一个不受任何if约束的i++,那现在i是不是就指向g的下一位-了呀?至于g,不需要再参与到遍历当中。
表达式计算
这个题留到后面,我整理一个表达式计算的方法合集。
小数形式与科学计数法转换(简)(50min)
【问题描述】
编写一个程序,将用小数表示的浮点数,转换成科学计数法的形式输出。输入的数据没有符号,小数点前后必有数字,且全为有效数据,即小数点后的末尾数字不为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。
输入的小数有以下几种情况:
我们大体可以先分为这几种情况,然后再做具体操作
if(str[0]=='0')
{
}
else if(strlen(str)==1||str[0]>='0'&&str[0]<='9'&&str[1]=='.')
{
}
else if(strlen(str)>=3&&str[0]>='0'&&str[0]<='9'&&str[1]>='0'&&str[1]<='9')
{
}
第一种情况,小数点右移的数目等于从左向右数第一个非零的数的下标 -- 小数点下标。若小数点移到了最后一位,则最后一位赋值为'\0'.
第二种情况,直接输出即可。
第三种情况,小数点左移次数等于小数点下标 -- 1,如果是整数,则假设小数点在字符串末尾。
c
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<stdbool.h>
void transform_1(char*);
void transform_2(char*);
int main()
{
char str[150];
scanf("%s",str);
if(str[0]=='0')
{
transform_1(str);
}
else if(strlen(str)==1||str[0]>='0'&&str[0]<='9'&&str[1]=='.')
{
printf("%se0",str);
}
else if(strlen(str)>=3&&str[0]>='0'&&str[0]<='9'&&str[1]>='0'&&str[1]<='9')
{
transform_2(str);
}
return 0;
}
void transform_1(char* str)
{
int exponent=0;
int i=0;
for(;i<strlen(str);i++)
{
if(str[i]>'0'&&str[i]<'9')
{
exponent=1-i;
break;
}
}
if(str[i+1]!='\0')
{
memmove(str+i+1+1,str+i+1,sizeof(char)*(strlen(str)-i));
str[i+1]='.';
memmove(str,str+i,sizeof(char)*(strlen(str)-i+1));
printf("%se%d",str,exponent);
}
else
{
printf("%ce%d",str[i],exponent);
}
}
void transform_2(char*str)
{
int exponent=0;
char*p=strchr(str,'.');
if(p==NULL)
{
int len=strlen(str);
str[len]='.';
str[len+1]='\0';
exponent=len-1;
memmove(str+2,str+1,sizeof(char)*(strlen(str)));
str[1]='.';
}
else
{
exponent=p-str-1;
int i=p-str;
memmove(str+i,str+i+1,sizeof(char)*(strlen(str)-i));
memmove(str+2,str+1,sizeof(char)*strlen(str));
str[1]='.';
}
int j=strlen(str)-1;
while(str[j]!='.')
{
if(str[j]=='0')
{
str[j]='\0';
j--;
}
else
{
break;
}
}
if(str[strlen(str)]=='.')
str[strlen(str)]='\0';
printf("%se%d",str,exponent);
}
超长正整数的减法(71min)
【问题描述】
编写程序实现两个超长正整数(每个最长80位数字)的减法运算。
【输入形式】
从键盘读入两个整数,要考虑输入高位可能为0的情况(如00083)。
- 第一行是超长正整数A;
- 第二行是超长正整数B;
【输出形式】
输出只有一行,是长整数A减去长整数B的运算结果,从高到低依次输出各位数字。要求:若结果为0,则只输出一个0;否则输出的结果的最高位不能为0,并且各位数字紧密输出。
【输入样例】
234098
134098703578230056
【输出样例】
-134098703577995958
【样例说明】
进行两个正整数减法运算, 234098 -134098703578230056 = -134098703577995958。
【评分标准】
完全正确得20分,每个测试点4分,提交程序文件名为subtract.c。
c
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int flag=0;
void front_zero(char*);
void subtract(char*,char*);
void reverse(char*);
int main()
{
char minuend[100];
char subtran[100];
gets(minuend);
gets(subtran);
front_zero(minuend);
front_zero(subtran);
if(strlen(minuend)<strlen(subtran))
{
flag=1;
char tmp[100];
strcpy(tmp,minuend);
strcpy(minuend,subtran);
strcpy(subtran,tmp);
}
else if(strlen(minuend)==strlen(subtran))
{
int cmp=strcmp(minuend,subtran);
if(cmp==0)
{
printf("0");
exit(1);
}
else if(cmp<0)
{
flag=1;
char tmp[100];
strcpy(tmp,minuend);
strcpy(minuend,subtran);
strcpy(subtran,tmp);
}
}
subtract(minuend,subtran);
}
void reverse(char* a)
{
int i,j;
for(i=0,j=strlen(a)-1;i<j;i++,j--)
{
char tmp=a[i];
a[i]=a[j];
a[j]=tmp;
}
}
void subtract(char*a,char*b)
{
char c[100];
reverse(a);
reverse(b);
int j=0;
int x,y;
while(b[j]!='\0')
{
if(a[j]<b[j])
{
x=a[j]-'0'+10;
y=b[j]-'0';
a[j+1]--;
}
else
{
x=a[j]-'0';
y=b[j]-'0';
}
c[j]=x-y+'0';
j++;
}
c[j]='\0';
if(b[j]=='\0'&&a[j]!='\0')
{
strcat(c,a+j);
}
reverse(c);
front_zero(c);
if(flag==1)
{
printf("-%s",c);
}
else
printf("%s",c);
}
void front_zero(char* str)
{
if(strlen(str)>1&&str[0]=='0')
{
int j=0;
while(str[j++]=='0');
j--;
memmove(str,str+j,sizeof(char)*(strlen(str)-j+1));
}
}
- 这道题要注意的是:
- 要先判断大小,大的做被减数,小的做减数,如果调换,那么最后输出的时候打印负号
- 做减法时要先逆转字符串
- 最后要给差也前端去零
- 调换字符串的时候,不要用指针很容易错,就老老实实地用strcpy三次
全排列数的生成
【问题描述】输入整数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增大时,运行时间将急剧增加。在编程时要注意尽量优化算法,提高运行效率。
【评分标准】该题要求输出若干行整数。。
这道题我当时是看一个b站视频写的,up讲的真的超级好,链接放这里有需要的自取哈,记得给up三连link
主要思想就是递归,想不明白的可以画一画递归展开图,一会儿给大家放个事例:
c
#include<stdio.h>
#include<stdlib.h>
void perm(int [],int,int);
void printArry(int [],int);
void swap(int [],int,int);
void swapback(int [],int,int);
int main()
{
int N;
scanf("%d",&N);
int* arr=(int*)malloc(sizeof(int)*N);
for(int i=0;i<N;i++)
{
arr[i]=i+1;
}
perm(arr,0,N-1);
return 0;
}
void perm(int arr[],int p,int q)
{
if(p==q)
{
printArry(arr,q+1);
return;
}
else
{
for(int i=p;i<=q;i++)
{
swap(arr,p,i);
perm(arr,p+1,q);
swapback(arr,p,i);
}
}
}
void printArry(int arr[],int n)
{
for(int i=0;i<n;i++)
{
printf("%d ",arr[i]);
}
printf("\n");
}
void swap(int arr[],int p,int q)
{
int temp=arr[q];
for(int i=q;i>=p+1;i--)
{
arr[i]=arr[i-1];
}
arr[p]=temp;
}
void swapback(int arr[],int p,int q)
{
int temp=arr[p];
for(int i=p;i<=q-1;i++)
{
arr[i]=arr[i+1];
}
arr[q]=temp;
}
- 简化思路就是,把每一位数与第一位数进行字典序的交换,然后让后面的数进行排列直至只剩一个数。
好啦今天就复习完毕了,明天接着肝剩下的内容(呜呜呜内容好多大佬保佑我)