第八周:数组 + 指针 + 字符串

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,则该正方形如下:

youan
dmebc
fghij
klpqr
stvwx

在加密一对字母时,如am,在正方形中找到以这两个字母为顶点的矩形(红色字体):

youan
dmebc
fghij
klpqr
stvwx

这对字母的加密字母为该矩形的另一对顶点,如本例中为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;
}

欢迎提问,学弟学妹们加油~

  • 9
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只可爱的小猴子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值