谭浩强《C程序设计》书后习题 第七章

最近要复习一下C和C++的基础知识,于是计划把之前学过的谭浩强的《C程序设计》和《C++程序设计》习题重新做一遍。

编译环境为:操作系统32位Win7,编译工具VC++6.0

第七章:数组

7.1)用筛选法求100之内的素数

#include<stdio.h>

void main()
{
    //创建数组并初始化
    int num[101]; //-1:未判断的数字 0:是素数 1:不是素数
    int counter;
    for(counter = 0; counter < 101; counter++)
    {
        num[counter] = -1; 
    }

    num[0] = 0;
    num[1] = 0;
    num[2] = 0;
    
    int i, j, k, sign; //sign 1:不是素数 0:是素数
    for(i = 3; i <= 100; i++)
    {
        //对于已经判断的数字不重复判断
        if(num[i] != -1)
        {
            continue;
        }

        //判断当前数是否为素数
        sign = 0;
        for(j = 2; j < i / 2 + 1; j++)
        {
            if(i % j == 0)
            {
                sign = 1;
                break;
            }
        }
        if(sign) 
        {
            num[i] = 1;
        }
        else 
        {
            num[i] = 0;
        }

        //当前判断数的倍数都不是素数
        for(k = i; k < 100; k = k + i)
        {
            //已判断的数字不重复判断
            if(num[k] != -1)
            {
                continue;
            }
            num[k] = 1;
        }
    }

    //输出标记的素数
    for(i = 2; i < 100; i++)
    {
        if(num[i] == 0)
        {
            printf("%d,", i);
        }
    }
    printf("\b \n");
}

7.2)用选择法对10个整数进行排序

#include<stdio.h>

void main()
{
    int a[10] = { 4, 5, 2, 9, 8, 1, 3, 7, 0, 6};
    
    //选择排序
    //maxx:i之后最大值下标
    int i, j, maxx, temp;
    for(i = 0; i < 9; i++)
    {
        maxx = i;
        for(j = i + 1; j < 10; j++)
        {
            if(a[j] > a[maxx]) maxx = j;
        }
        if(a[maxx] > a[i])
        {
            temp = a[i];
            a[i] = a[maxx];
            a[maxx] = temp;
        }
    }

    //输出排序后数组
    for(i = 0; i < 10; i++)
    {
        printf("%d,", a[i]);
    }
    printf("\b \n");
}

7.3)求一个3×3的整形矩阵对角线元素之和

#include<stdio.h>

void main()
{
    int a[3][3] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
    printf("对角线元素之和:%d\n", a[0][0] + a[1][1] + a[2][2]);
}

7.4)已有一个排好序的数组,要求输入一个数后,按原来排序的规律将它插入数组中

#include<stdio.h>

void main()
{
    //原数组
    int a[10] = { 0, 1, 2, 3, 5, 6, 7, 8, 9, 10 };

    //插入数字
    int num = 4;

    //新数组
    int b[11];

    //为新数组赋值
    int i, sign = 0;
    for(i = 0; i < 10; i++)
    {
        if(num > a[i])
        {
            b[i] = a[i];
        }
        else
        {
            if(!sign)
            {
                b[i] = num;
                sign = 1;
            }
            b[i + 1] = a[i];
        }
    }

    for(i = 0; i < 11; i++)
    {
        printf("%d,", b[i]);
    }
    printf("\b \n");
}

7.5)将一个数组中的值按逆序重新存放

#include<stdio.h>

void main()
{
    int a[5] = { 8, 6, 5, 4, 1 };

    //j:数组长度
    int i, j, temp;
    j = sizeof(a)/sizeof(int);

    //逆序换位
    for(i = 0; i < j / 2; i++)
    {
        temp = a[i];
        a[i] = a[j - i - 1];
        a[j - i - 1] = temp;
    }

    //输出数组内容
    for(i = 0; i < j; i++)
    {
        printf("%d,", a[i]);
    }
    printf("\b \n");
}

7.6)输出杨辉三角形的前10行

#include<stdio.h>

void main()
{
    int a[10] = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
    
    int i, j;
    for(i = 0; i < 10; i++)
    {
        //计算下一行数组
        for(j = i; j > 0; j--)
        {
            a[j] = a[j] + a[j-1];
        }

        //输出当前数组
        for(j = 0; j <= i; j++)
        {
            printf(" %d ", a[j]);
        }
        printf("\n");
    }
}

7.7)输出指定阶幻方

幻方的生成需要分类讨论,分为:

①奇阶幻方,使用Merzirac法生成

②双偶幻方,使用Spring法生成

③单偶幻方,使用Strachey法生成

简易的使用方法见代码中的注释

#include<stdio.h>

#define n    6

void main()
{
    //初始化幻方矩阵
    int a[n][n], i, j;
    for(i = 0; i < n; i++)
    {
        for(j = 0; j < n; j++)
        {
            a[i][j] = 0;
        }
    }

    if(n % 2) //奇数阶幻方(Merzirac法)
    {
        //在第一行居中的方格内放1
        //依次向右上方填入2、3、4...
        //如果右上方已有数字,则向下移一格继续填写

        int x = 0, y = n / 2, tempx, tempy, counter;
        for(counter = 1; counter <= n * n; counter++)
        {
            //赋值
            a[x][y] = counter;
            //考虑右上的数字
            tempx = x - 1;
            if(tempx < 0)
            {
                tempx += n;
            }
            tempy = y + 1;
            if(tempy >= n)
            {
                tempy -= n;
            }

            //右上数字为0则走到右上
            if(a[tempx][tempy] == 0) 
            {
                x = tempx;
                y = tempy;
            }
            else //否则向下走一格
            {
                x++;
                if(x >= n)
                {
                    x -= n;
                }
            }
        }

        //另有Loubere法:在居中的方格向上一格内放1
        //依次向右上方填入2、3、4...
        //如果右上方已有数字,则向上移两格继续填写
    }
    else if(n % 4 == 0) //双偶幻方:能被4整除的偶数阶幻方(Spring法)
    {
        //在方阵内顺序填写1-n^2
        //将所有非主副对角线上的数字交换到其中心对称的位置

        //填写数字
        int counter = 1;
        for(i = 0; i < n; i++)
        {
            for(j = 0; j < n; j++)
            {
                a[i][j] = counter++;
            }
        }

        //交换数字
        int temp;
        for(i = 0; i < n; i++)
        {
            for(j = 0; j < n - i - 1; j++)
            {
                if(i == j)
                {
                    continue;
                }

                temp = a[i][j];
                a[i][j] = a[n - i - 1][n - j - 1];
                a[n - i - 1][n - j - 1] = temp;
            }
        }
    }
    else if(n % 2 == 0) //单偶幻方:不能被4整除的偶数阶幻方(Strachey法)
    {
        //http://en.wikipedia.org/wiki/Strachey_method_for_magic_squares

        //将矩阵分为4部分,分别按n/2阶幻方的方法填数
        // A C | A填1到n*n/4         B填n*n/4+1到n*n/2
        // D B | C填n*n/2+1到n*n/4*3 D填n*n/4*3+1到n*n

        int x = 0, y = n / 4, tempx, tempy, counter;
        for(counter = 1; counter <= n * n / 4; counter++)
        {
            //赋值
            a[x][y] = counter;
            a[x + n / 2][y + n / 2] = counter + n * n / 4;
            a[x][y + n / 2] = counter + n * n / 2;
            a[x + n / 2][y] = counter + n * n / 4 * 3;

            //考虑右上的数字
            tempx = x - 1;
            if(tempx < 0)
            {
                tempx += n / 2;
            }
            tempy = y + 1;
            if(tempy >= n / 2)
            {
                tempy -= n / 2;
            }

            //右上数字为0则走到右上
            if(a[tempx][tempy] == 0) 
            {
                x = tempx;
                y = tempy;
            }
            else //否则向下走一格
            {
                x++;
                if(x >= n / 2)
                {
                    x -= n / 2;
                }
            }
        }

        //将左n/4列的数字,A和D对应位置互换
        int temp;
        for(i = 0; i < n / 2; i++)
        {
            for(j = 0; j < n / 4; j++)
            {
                temp = a[i][j];
                a[i][j] = a[i + n / 2][j];
                a[i + n / 2][j] = temp;
            }
        }

        //将右n/4-1列的数字,B和C对应位置互换
        for(i = 0; i < n / 2; i++)
        {
            for(j = n - 1; j > n - n / 4; j--)
            {
                temp = a[i][j];
                a[i][j] = a[i + n / 2][j];
                a[i + n / 2][j] = temp;
            }
        }

        //交换A和D的中心
        temp = a[n / 4][0];
        a[n / 4][0] = a[n - n / 4 - 1][0];
        a[n - n / 4 - 1][0] = temp;

        //交换A和D中间行最左端的值
        temp = a[n / 4][n / 4];
        a[n / 4][n / 4] = a[n - n / 4 - 1][n / 4];
        a[n - n / 4 - 1][n / 4] = temp;
    }

    //输出幻方
    for(i = 0; i < n; i++)
    {
        for(j = 0; j < n; j++)
        {
            printf("%d\t", a[i][j]);
        }
        printf("\n");
    }
}

7.8)找出一个二维数组中的鞍点,即该位置上的元素在该行上最大,在该列上最小。一个二维数组也可能没有鞍点

#include<stdio.h>

#define width    5
#define height    5

void main()
{
    //创建二维数组
    int a[height][width] = 
    {
        { 5, 0, 0, 0, 0 }, 
        { 5, 0, 0, 0, 0 },
        { 3, 1, 1, 1, 1 },
        { 5, 0, 0, 0, 0 },
        { 5, 0, 0, 0, 0 }
    };

    int row_max;    //行最大值
    int row_max_x;    //行最大值横坐标
    int row_max_y;    //行最大值纵坐标
    int column_min;    //行最小值

    //遍历各行
    int i, j, k;
    for(i = 0; i < height; i++)
    {
        //寻找第i行的最大值
        row_max = a[i][0];
        for(j = 1; j < width; j++)
        {
            if(a[i][j] > row_max)
            {
                row_max = a[i][j];
            }
        }

        //所有满足最大值的点,查看是否是该列的最小值
        for(j = 0; j < width; j++)
        {
            if(a[i][j] == row_max)
            {
                column_min = a[0][j];
                for(k = 0; k < height; k++)
                {
                    if(a[k][j] < column_min)
                    {
                        column_min = a[k][j];
                    }
                }
                if(row_max == column_min)
                {
                    printf("Find saddle point: (%d,%d)\n", i, j);
                }
            }
        }
    }
}

7.9)有15个数按由大到小顺序存放在一个数组中,输入一个数,要求用折半查找法找出该数是数组中第几个元素的值。如果该数不再数组中,则输出“无此数”

#include<stdio.h>

#define length    15

void main()
{
    int a[length] = { 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };

    int n, left, right;
    scanf("%d", &n);

    left = 0;            //左边界
    right = length - 1; //右边界

    while(true)
    {
        //与左边界吻合的情况
        if(a[left] == n)
        {
            printf("Number Found: a[%d] is %d\n", left, a[left]);
            break;
        }
        //与右边界吻合的情况
        if(a[right] == n)
        {
            printf("Number Found: a[%d] is %d\n", right, a[right]);
            break;
        }
        //未找到的情况
        if((left >= right - 1) || a[left] > n || a[right] < n)
        {
            printf("Number Not Found!\n");
            break;
        }

        //折半缩小排查区域
        if(a[(left + right) / 2] > n)
        {
            right = (left + right) / 2;
        }
        else 
        {
            left = (left + right) / 2;
        }
    }
}

7.10)有一篇文章,共有3行文字,每行有80个字符。要求分别统计出其中英文大写字母、小写字母、数字、空格以及其他字符的个数

#include<stdio.h>

#define row_count    3
#define row_length    100

void main()
{
    char words[row_count][row_length] = 
    {
        { "abcdefg HIJKLMN 1234_5678" },
        { "!@#$%^&*() 0987654321" },
        { "kakaka_gagaga" }
    };

    int count_of_AtoZ = 0; //大写字母数
    int count_of_atoz = 0; //小写字母数
    int count_of_0to9 = 0; //数字数
    int count_of_spac = 0; //空格数
    int count_of_othr = 0; //其他字符数

    int i, j;
    for(i = 0; i < row_count; i++)
    {
        for(j = 0; words[i][j] != '\0'; j++)
        {
            if(words[i][j] >= 'A' && words[i][j] <= 'Z')
            {
                count_of_AtoZ++;
            }
            else if(words[i][j] >= 'a' && words[i][j] <= 'z')
            {
                count_of_atoz++;
            }
            else if(words[i][j] >= '0' && words[i][j] <= '9')
            {
                count_of_0to9++;
            }
            else if(words[i][j] == ' ')
            {
                count_of_spac++;
            }
            else
            {
                count_of_othr++;
            }
        }
    }

    printf("A-Z:   %d\n", count_of_AtoZ);
    printf("a-z:   %d\n", count_of_atoz);
    printf("0-9:   %d\n", count_of_0to9);
    printf("space: %d\n", count_of_spac);
    printf("other: %d\n", count_of_othr);
}

7.11)输出图案

#include<stdio.h>

void main()
{
    char s[14] = "*  *  *  *  *";
    
    int i, j;
    for(i = 0; i < 5; i++)
    {
        for(j = 0; j < 2 * i; j++)
        {
            printf(" ");
        }
        printf("%s\n", s);
    }
}

谭浩强《C程序设计》书后习题 第七章

7.12)有一行电文,已按下面的规律译成密码

A→Z a→z

B→Y b→y

C→X c→x

。。。。。。

要求编写程序将密码译回原文

#include<stdio.h>

void main()
{
    char s[100];

    gets(s); //读取一行内容
    printf("Your input: %s\n", s);

    int i;
    char c;

    //逐个筛查读取到的内容并输出
    printf("My output: ");
    for(i = 0; (c = s[i]) != '\0'; i++)
    {
        if(c >= 'A' && c <= 'Z')
        {
            c = 'A' + 26 - (c - 'A') - 1;
        }
        if(c >= 'a' && c <= 'z')
        {
            c = 'a' + 26 - (c - 'a') - 1;
        }
        printf("%c", c);
    }
    printf("\n");
}

7.13)将两个字符串连接起来,不使用strcat函数

#include<stdio.h>

void main()
{
    char a[100], b[100], c[200];

    printf("Input string a: ");
    gets(a);
    printf("Input string b: ");
    gets(b);

    int i, j;
    for(i = 0; a[i] != '\0'; i++)
    {
        c[i] = a[i];
    }
    for(j = 0; b[j] != '\0'; i++, j++)
    {
        c[i] = b[j];
    }
    c[i] = '\0';

    printf("%s\n", c);
}

7.14)比较两个字符串大小,不使用strcpy函数

#include<stdio.h>

void main()
{
    char a[100], b[100];

    printf("Input string a: ");
    gets(a);
    printf("Input string b: ");
    gets(b);

    int i;
    for(i = 0; i < 100; i++)
    {
        if(a[i] == '\0' && b[i] == '\0')
        {
            printf("0\n");
            break;
        }
        else if(a[i] == b[i])
        {
            continue;
        }
        else
        {
            printf("%d\n", a[i] - b[i]);
            break;
        }
    }
}

7.15)将字符数组s2中的全部字符复制到字符数组s1中,不用strcpy函数

#include<stdio.h>

void main()
{
    char a[100], b[100];

    printf("Input string a: ");
    gets(a);
    printf("Input string b: ");
    gets(b);

    int i;
    for(i = 0; b[i] != '\0'; i++)
    {
        a[i] = b[i];
    }
    a[i] = '\0';

    printf("%s\n", a);
}

END

你可能感兴趣的:(习题,谭浩强,C程序设计,第六章)