目录
1.二维数组矩阵转置
题目:
请写一函数,将一个m*n的整型矩阵转置。注意:请将转置后的数据存储到二维数组中以后,再对二维数组进行输出。要求使用如下的三个函数进行三次转置:
void Transpose1(int a[][N], int at[][M], int m, int n);
void Transpose2(int (*a)[N], int (*at)[M], int m, int n); //行指针
void Transpose3(int *a, int *at, int m, int n); //列指针
【输入形式】矩阵长度和宽度及矩阵元素值
【输出形式】调用三个函数转置后的矩阵
【样例输入】
3 4
1 2 3 4
4 5 6 7
7 8 9 0
【样例输出】
1 4 7
2 5 8
3 6 9
4 7 0
1 4 7
2 5 8
3 6 9
4 7 0
1 4 7
2 5 8
3 6 9
4 7 0
【友情提示】注意第三个转置方法在计算行列个数时,使用原始行列总个数。
代码:
#include <stdio.h>
#include <iostream>
using namespace std;
#define M 100
#define N 100
void Input (int a[M][N], int m, int n)
{
for (int i = 0; i < m; i ++)
{
for (int j = 0; j < n; j ++)
{
scanf ("%d", &a[i][j]);
}
}
}
void Output (int at[M][N], int m, int n)
{
printf ("\n");
printf ("\n");
for (int i = 0; i < m; i ++)
{
for (int j = 0; j < n; j ++)
{
printf ("%d ", at[i][j]);
}
printf ("\n");
}
}
void Transpose1 (int a[][N], int at[][M], int m, int n)
{
for (int i = 0; i < m; i ++)
{
for (int j = 0; j < n; j ++)
{
at[j][i] = a[i][j];
}
}
}
void Transpose2 (int (*a)[N], int (*at)[M], int m, int n)
{
for (int i = 0; i < m; i ++)
{
for (int j = 0; j < n; j ++)
{
*(*(at + j) + i) = *(*(a + i) + j);
}
}
}
void Transpose3 (int *a, int *at, int m, int n)
{
for (int i = 0; i < m; i ++)
{
for (int j = 0; j < n; j ++)
{
*(at + M * j + i) = *(a + N * i + j);
}
}
}
int main()
{
int a[M][N];
int at[N][M];
int m, n;
scanf("%d %d", &m, &n);
Input(a, m, n);
Transpose1(a, at, m, n);
Transpose2(a, at, m, n);
Transpose2(a, at, m, n);
Output(at, n, m);
Output(at, n, m);
Output(at, n, m);
}
2.整数的N进制字符串表示
题目:
编写函数itob(n,s,b),用于把整数n转换成以b为基的字符串并存储到s中。编写程序,使用函数itob(n,s,b)将输入的整数n,转换成字符串s,将s输出。转换后的字符串从最高的非零位开始输出。如果n为负数,则输出的字符串的第一个字符为’-‘。b为大于1小于37的任意自然数值。当b=2时,输出字符只可能是’0’和’1’;当b=16时,输出字符串中可能含有字符为’0’-‘9’,‘a’-‘f’(字母以小写输出)。
【输入形式】控制台输入整数n和b,其中n可以为负数。n和b以空格分隔.
【输出形式】控制台输出转化后的字符串s.
【样例输入】5 2
【样例输出】101
【样例说明】5的二进制就是101
代码:
#include <iostream>
#include <cstring>
#define N 1000
using namespace std;
void itob(int n, char *s, int b)
{
for(int i = 0; ; i ++)
{
if(n < 0)
{
n = -n;
}
int y = n % b;
if(y <= 9)s[i] = y + '0'; //输出的s[i]为ASCII对应的字符
if(y > 9)s[i] = y - 10 + 'a';
n = n / b;
if(n == 0)
{
s[i + 1] = '\0';
break;
}
}
}
int main()
{
int n, b;
cin >> n >> b;
char s[N];
itob(n, s, b);
int len = strlen(s);
if(n < 0) cout << '-';
for(int i = len - 1; i >= 0; i --)
{
cout << s[i];
}
return 0;
}
3.整数中相同的数据删除问题(一维数组循环排序)
题目:
对一维数组中存储的数据首先进行从小到大的排序(冒泡、选择、插入、快速排序均可),然后删除序列中相同的数据,仅保留一个,最后输出数组中的数据。务必自行设计函数实现排序功能、删除功能、数组元素录入及个数统计功能、数组元素输出的功能等。
提示:删除时,可额外申请另一个数组存放结果,用len表示新的长度。
for(i=对原一维数组下标的依次循环,原长度为n)
{ 将a[i]放入新的数组b[len];len++;
for(j=从i+1开始向后循环)
{ 如果a[j]!=a[i],则跳出;否则继续i++,j++}
}
【输入形式】一些随机的数据,输入-1代表输入结束
【输出形式】删除后的结果,注意:最后一个数据后面有一个空格
【样例输入】9 9 0 32 2 78 2 8 5 3 1 9 0 2 6 6 7 -1
【样例输出】0 1 2 3 5 6 7 8 9 32 78
代码:
#include <stdio.h>
#define N 100
int Scanf(int num[])
{
int i = 0;
do{
scanf("%d", &num[i]);
i ++;
}while(num[i - 1] != -1);
return i - 1;
}
void DataSort(int num[], int n)
{
int i, j, k, temp;
for(i = 0; i < n - 1; i ++)
{
k = i;
for(j = i + 1; j < n; j ++)
{
if(num[j] < num[k])
k = j;
}
if(k != i)
{
temp = num[k];
num[k] = num[i];
num[i] = temp;
}
}
}
int Delete(int num[], int len)
{
int i;
for(i = 0; i < len; i ++)
{
if(num[i] == num[i + 1])
{
for(int j = i + 1; j < len; j ++)
{
num[j] = num[j + 1];
}
i --;
len --;
}
}
return len;
}
int Printf(int num[], int n)
{
for(int i = 0; i < n; i ++)
printf("%d ", num[i]);
}
int main()
{
int num[N], x, y;
x = Scanf(num);
DataSort(num, x);
y = Delete(num, x);
Printf(num, y);
}
4.二维数组的最大点
题目:
求二维整型数组的“最大点”。二维数组的**“最大点”**定义为:某个数是所在行的最大值,并且是所在列的最大值。注意:某行或某列上可能有多个“最大点”。
请设计函数:
void Read(int *p, int m, int n);获得二维数组数据元素的值;
int MaxPoint(int (*p)[N], int m, int n, int *result);获得二维数组的最大点,并将结果存入result指向的二维数组中,函数返回值代表最大点的个数。
主函数中定义两个二维数组,一个用于存放n行m列的原始数据,另一个用于存放最大点的结果,其中每一列分别代表最大点的值、最大点所在的行、最大点所在的列。
【输入形式】
从控制台读入二维数组。
第一行只有以空格分隔的两个正整数n和m(n,m<=10),n代表二维数组的行数,m代表二维数组的列数。
然后在后续n行上输入二维数组的元素,每行有m个以若干空格分隔的整数,代表二维数组在该行上的所有元素。
【输出形式】
向控制台输出二维数组的*
“最大点”*
,按行下标、列下标从小到大的顺序输出,每行一个,先输出**“最大点”**数值,再输出对应的行数、列数(行列都从1开始计数),以一个空格分隔。
【样例输入】
3 4
8 60 7 100
10 498 12 49
-71 132 4 85
【样例输出】
100 1 4
498 2 2
【样例说明】
输入了一个三行四列的二维数组,第一行第四列的元素100是第一行的最大元素,同时也是第四列的最大元素,所以该元素是“最大点”,输出100 1 4。同样第二行第二列的元素498也是第二行的最大元素,同时是第二列的最大元素,故该元素也是“最大点”,输出498 2 2。
代码:
#include <iostream>
using namespace std;
#define N 100
void Read(int *p, int m, int n)
{
int i, j;
for(i = 0; i < m; i ++)
{
for(j = 0; j < n; j ++)
{
cin >> p[i * 100 + j];
}
}
}
int MaxPoint(int (*p)[N], int m, int n, int *result)
{
int a = 0;
for(int i = 0; i < m; i ++)
{
int maxnum = -999;
int mj = 0;
for(int j = 0; j < n; j ++)
{
if(*(*(p + i) + j) > maxnum)
{
maxnum = *(*(p + i) + j);
mj = j;
int z = 0;
int k = 0;
for(; k < m; k ++)
{
if(*(*(p + k) + mj) <= *(*(p + i) + mj))
z ++;
}
if(z == k)
{
int q = 0;
result[a * 3 + q] = *(*(p + i) + mj);
result[a * 3 + q + 1] = i;
result[a * 3 + q + 2] = mj;
a ++;
}
}
}
}
return a;
}
void Output(int *p, int m)
{
int i, j;
for(i = 0; i < m; i ++)
{
for(j = 0; j < 3; j ++)
{
cout << p[i * 100 + j] << " ";
}
cout << endl;
}
}
int main()
{
int num[100][100], result[100][100];
int m, n, x;
cin >> m >> n;
Read(*num, m, n);
x = MaxPoint(num, m, n, *result);
cout << x;
Output(*result, x);
return 0;
}
5.字串问题
题目:
请编写函数统计子串Substr在母串Str中出现的次数。函数原型如下,返回值为出现的次数:
int Count(char *Str, char *Substr);
【样例说明】第一行为母串、第二行为子串
【样例输入】出现的次数
abcbcbc
bcb
【样例输出】
2
代码:
#include <stdio.h>
#include <string.h>
#define N 100
int Count(char *s, char *str)
{
int k = 0;
char *a ;
char *b ;
while(*s != '\0')
{
a = s;
b = str;
while(*a == *b && *a != '\0' && *b != '\0')
{
a ++;
b ++;
}
if(*b == '\0')
{
k ++;
}
s ++;
}
return k;
}
int main()
{
char Str[N], Substr[N];
int x;
gets(Str);
gets(Substr);
x = Count(Str, Substr);
printf("%d", x);
return 0;
}
6.字符串中的数字
题目:
输入一个字符串,内有数字和非数字字符。如:a123x456 17960?302tab5876,将其中连续的数字作为一个整数,依次存放到一个数组a中。例如,123存放在a[0],456存放在a[1]…统计共有多少个整数,并输出这些整数。输入串中含有空格,可以用cin.getline(str,30,‘\n’)接收串,其中str是char str[50]。
【样例输入】
a123x456 17960?302tab5876
【样例输出】
5
123 456 17960 302 5876
代码:
#include <iostream>
using namespace std;
char str[50];
int main()
{
cin.getline(str, 50);
char* p = str;
int sum = 0;
int i = 0;
int num = 0;
for (i = 0; p[i] != '\0'; ++ i)
{
if ((i - 1) >= 0 && (p[i] < '0' || p[i] > '9'))
{
if (p[i - 1] >= '0' && p[i - 1] <= '9')
sum ++;
}
}
if (p[i - 1] >= '0' && p[i - 1] <= '9')
sum ++;
cout << sum << " \n";
int flag = 0;//假设之前是字母
for (i = 0; p[i] != '\0'; ++ i)
{
if (p[i] >= '0' && p[i] <= '9')
{
if (flag == 0)
flag = 1;
if (p[i] == '0' && p[i + 1] == '0')
;
else
cout << p[i];
}
else
{
if (flag == 0)
;
else
{
cout << " ";
flag = 0;
}
}
}
return 0;
}
7.学生成绩统计
题目:
利用结构体类型编写程序,实现输入5个学生的学号、姓名、性别、四门课程的成绩,然后计算并输出学生的信息及平均成绩。要求定义如下的函数分别实现结构体数组数据的录入、平均分的计算、输出结构体数组数据及平均分数组数据的功能:
void Input(struct Student s[], int n);
void Func(struct Student *p, int n, int ave[]);
void Output(STUDENT *p, int n, int ave[]);
请注意:STUDENT是用typedef定义的数据类型
【输入形式】学生的信息
【输出形式】学生的信息及平均成绩
【样例输入】
2018001 zhangsan f 90 80 70 60
2018002 lisi m 88 55 69 72
2018003 wangwu f 63 89 78 85
2018004 zhaoliu m 93 69 67 68
2018005 sunqi m 85 87 68 78
【样例输出】
2018001 zhangsan f 90 80 70 60 75
2018002 lisi m 88 55 69 72 71
2018003 wangwu f 63 89 78 85 79
2018004 zhaoliu m 93 69 67 68 74
2018005 sunqi m 85 87 68 78 80
代码:
#include <iostream>
using namespace std;
char s[100];
char* ppp = s;
struct Student
{
int xh;
char name[100];
char sex;
int a;
int b;
int c;
int d;
double average;
}Student0[100];
int main()
{
int n = 0;
int pos = -1;
while (cin >> n)
{
pos ++;
Student0[pos].xh = n;
ppp = Student0[pos].name;
cin >> ppp;
cin >> Student0[pos].sex;
cin >> Student0[pos].a;
cin >> Student0[pos].b;
cin >> Student0[pos].c;
cin >> Student0[pos].d;
Student0[pos].average = (Student0[pos].a + Student0[pos].b
+ Student0[pos].c + Student0[pos].d) / 4.0;
}
for (int i = 0; i <= pos; ++ i)
{
cout << Student0[i].xh << " ";
cout << Student0[i].name << " ";
cout << Student0[i].sex << " ";
cout << Student0[i].a << " ";
cout << Student0[i].b << " ";
cout << Student0[i].c << " ";
cout << Student0[i].d << " ";
cout << int(Student0[i].average + 0.5) << "\n";
}
return 0;
}
8.大整数相加
题目:
请编程实现超长位数的大整数的加法运算。
【提示】
定义字符数组接收待相加的两个超长位数的大整数,然后进行单个字符与字符之间的相加,举例如下:
char x[1000],y[1000]; int sum, carry;
sum=carry+x[i]-‘0’+y[i]-‘0’;
其中carry代表进位。
亦可使用结构体实现。
【样例输入】12587469874520145879333211125874698745201458793332111258746987452014587933321112587469874520145879333211
745201458793745201458793745201458793745201458793745201458793745201458793745201458793745201458793745201458793745201458793745201458793745201458793
【样例输出】745201458793745201458793745201458793745214046263619721604673078412584668443946660252538533570052492188910808333134779906332671333313891080792004
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
char x[1000], y[1000];
int str[2000];
int main()
{
int sum, len_x, len_y;
int carry = 0;
gets(x);
gets(y);
len_x = strlen(x);
len_y = strlen(y);
if(len_x == len_y)
{
int a = -1;
for(int i = len_x - 1; i >= 0; i --)
{
sum = 0;
a ++;
sum = carry + x[i] - '0' + y[i] - '0';
if(sum >= 10)
{
carry = 1;
str[a] = sum % 10;
}
if(sum < 10)
{
carry = 0;
str[a] = sum;
}
if(i == 0 && carry == 1)
{
a ++;
str[a] = 1;
}
for(int i = a; i >= 0; i --)
cout << str[i] << endl;
}
if(len_x < len_y)
{
int i = len_x - 1;
int j = len_y;
int a = -1;
for(;i >= 0; i --)
{
a ++;
sum = 0;
j --;
sum = carry + x[i] - '0' + y[j] - '0';
if(sum >= 10)
{
carry = 1;
str[a] = sum % 10;
}
if(sum < 10)
{
carry = 0;
str[a] = sum;
}
if(i == 0 && carry == 1)
{
for(j = len_y - len_x - 1; j >= 0; j --)
{
sum = carry + y[j] - '0';
if(sum >= 10)
{
carry = 1;
str[a] = sum % 10;
}
if(sum < 10)
{
carry = 0;
str[a] = sum;
}
if(j == 0 && carry == 1)
{
a ++;
str[a] = 1;
}
}
}
}
}
return 0;
}
9.playfair密码
题目:
一种Playfair密码变种加密方法如下:首先选择一个密钥单词(pair)(字母不重复,且都为小写字母),然后与字母表中其他字母一起填入至一个5X5的正方形中,填入方法如下:
1.首先按行填入密钥串。
2.然后再按字母序按行填入不在密钥串中的字母。
3.由于正方形中只有25个位置,最后剩下的字母不变换。
如果密钥为youandme,则该正方形如下:
y | o | u | a | n |
---|---|---|---|---|
d | m | e | b | c |
f | g | h | i | j |
k | l | p | q | r |
s | t | v | w | x |
在加密一对字母时,如am,在正方形中找到以这两个字母为顶点的矩形(红色字体):
y |
o |
u |
a |
n |
---|---|---|---|---|
d |
m |
e |
b |
c |
f | g | h | i | j |
k | l | p | q | r |
s | t | v | w | x |
这对字母的加密字母为该矩形的另一对顶点,如本例中为ob。
设计一程序,使用上述方法对输入串进行加密,并输出加密后的字符串。另外有如下规定:
1、如果最后只剩下一个字母,则不变换,直接放入加密串中;
2、如果一对字母中的两个字母相同,则不变换,直接放入加密串中;
3、如果一对字母中有一个字母不在正方形中,则不变换,直接放入加密串中;
4、如果字母对出现在正方形中的同一行或同一列,如df或hi,则只需简单对调这两个字母,即变换为fd或ih;
5、如果在正方形中能够找到以字母对为顶点的矩形,假如字母对为am,则该矩形的另一对顶点字母中,与a同行的字母应在前面,在上例中应是ob;同样若待变换的字母对为ta,则变换后的字母对应为wo;
6、本程序中输入串均为小写字母,并不含其它字符。
解密方法与加密相同,即对加密后的字符串再加密,将得到原始串。
【输入形式】
从控制台输入两行字符串,第一行为密钥单词(长度小于等于25),第二行为待加密字符串(长度小于等于50),两行字符串末尾都有一个回车换行符,并且两行字符串均为小写字母,不含其它字符。
【输出形式】
在标准输出上输出加密后的字符串。
【输入样例】
youandme
welcometohangzhou
【输出样例】
vbrmmomvugnagzguu
【样例说明】
输入的密钥单词为youandme,形成的正方形如上所示;待加密字符串为welcometohangzhou。在正方形中可以找到以第一对字母we为顶点的矩形,对应另一对顶点字母为vb,因此加密后为vb,同理可找到与字母对lc,et,oh,ho对应的顶点字母对。而字母对om位于上述正方形中的同一列,所以直接以颠倒这两个字母来加密,即为mo,字母对an同理。字母对gz中的z不在上述正方形中,因此原样放到加密串中。最后剩一个字母u也原样输出。
算法提示:
1、如果用二维数组保存正方形中的字符,可以先在一维数组中填入密钥单词和不在密钥单词中的字母,然后再把该一维数组中的字符放入二维数组中;
2、在对字母对进行加密时,最好按照上述规定中前五条的顺序进行判断。
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
char num[25], str[5][5], s[17];
int x = -1, y = -1;
int findpos(char t)
{
int i, j;
for(i = 0; i < 5; i ++)
{
for(j = 0; j < 5; j ++)
{
if(str[i][j] == t)
{
x = i;
y = j;
return 1;
}
}
}
return -1;
}
int main()
{
int len, y, i;
char x = 'a' - 1;
gets(num);
len = strlen(num);
for(int i = len; i < 25; i ++)
{
int j;
x += 1;
for(j = 0; j < len; j ++)
{
if(num[j] != x)
continue;
else
{
x += 1;
j = -1;
continue;
}
}
if(j == len)
{
num[i] = x;
}
}
for(int i = 0; i < 25; i ++)
{
str[i / 5][i % 5] = num[i]; //把一维数组转变成二维数组!!字符也可以直接赋值的呢!!
}
gets(s);
int slen = strlen(s);
for( i = 0; i < slen - 1; i+= 2)
{
int t1 = s[i];
int t2 = s[i + 1];
if(t1 == t2)
cout << t1 << t2;
int is1 = findpos(t1);
int t1x = x;
int t1y = y;
int is2 = findpos(t2);
int t2x = x;
int t2y = y;
if(is1 == -1 || is2 == -1)
cout << t1 << t2;
else if(t1x == t2x || t1y == t2y)
cout << t2 << t1;
else
cout << str[t1x][t2y] << str[t2x][t1y];
}
if(i == slen - 1)
cout << s[i];
return 0;
}
欢迎提问,学弟学妹们加油~