PTA - C编程 NoC - 指针 (11道题)

6-1 计算两数的和与差
6-2 利用指针找最大值
6-3 在数组中查找指定元素
6-4 使用函数的选择法排序
6-5 判断回文字符串
6-6 数组循环右移
6-7 拆分实数的整数与小数部分
6-8 分类统计各类字符个数
7-1 冒泡法排序
7-2 猴子选大王
7-3 组合数的和

6-1 计算两数的和与差

本题要求实现一个计算输入的两数的和与差的简单函数。

函数接口定义:

void sum_diff( float op1, float op2, float *psum, float *pdiff );

其中op1op2是输入的两个实数,*psum*pdiff是计算得出的和与差。

void sum_diff(float op1, float op2, float *psum, float *pdiff)
{
    *psum = op1 + op2;
    *pdiff = op1 - op2;
}

6-2 利用指针找最大值

本题要求实现一个简单函数,找出两个数中的最大值。

函数接口定义:

void findmax( int *px, int *py, int *pmax );

其中pxpx是用户传入的两个整数的指针。函数findmax应找出两个指针所指向的整数中的最大值,存放在pmax指向的位置。

void findmax(int *px, int *py, int *pmax)
{
    if(*px > *py) *pmax = *px;
    else          *pmax = *py;
}

6-3 在数组中查找指定元素

本题要求实现一个在数组中查找指定元素的简单函数。

函数接口定义:

int search( int list[], int n, int x );

其中list[]是用户传入的数组;n(≥0)是list[]中元素的个数;x是待查找的元素。如果找到

则函数search返回相应元素的最小下标(下标从0开始),否则返回−1。

int search(int list[], int n, int x)
{
    for(int i = 0; i < n; i++)
        if(list[i] == x)
            return i;
    return -1;
}

6-4 使用函数的选择法排序

本题要求实现一个用选择法对整数数组进行简单排序的函数。

函数接口定义:

void sort( int a[], int n );

其中a是待排序的数组,n是数组a中元素的个数。该函数用选择法将数组a中的元素按升序排列,结果仍然在数组a中。

解:

    刚开始写错了,写了个插入排序,也放进来吧。

void sort(int a[], int n)
{
    int cur = 1;  // 从第1个数开始(第0个相当于已排序)
    while(cur < n)
    {
        for(int i = 0; i < cur; i++)
            if(a[i] > a[cur]) // 在已排序序列中找到比它大的
            {
                // a[i] 及后边所有数后移一位,然后把 a[cur] 插入在 a[i] 位置
                int tmp = a[cur];
                for(int j = cur; j > i; j--)
                    a[j] = a[j - 1];
                a[i] = tmp;
                break;
            }
        // 已排序序列中没有比它大的,相当于已经排好序了,不需要处理
        ++cur;
    }
}

    下边是重新写的选择排序,每次在未排序序列里选一个最小的,放在已排序序列最后边。

void sort(int a[], int n)
{
    if(n == 1) return;
    int cur = 0;
    while(cur < n)
    {
        int min_val = a[cur], min_idx = cur;
        for(int i = cur + 1; i < n; i++)
            if(a[i] < min_val)
            {
                min_val = a[i];
                min_idx = i;
            }
        // 交换 a[cur] 和 a[min_idx],使得最小的数放到正确的位置
        int tmp = a[cur];
        a[cur] = min_val;
        a[min_idx] = tmp;
        ++cur;
    }
}

6-5 判断回文字符串

本题要求编写函数,判断给定的一串字符是否为“回文”。所谓“回文”是指顺读和倒读都一样的字符串。如“XYZYX”和“xyzzyx”都是回文。

函数接口定义:

bool palindrome( char *s );

函数palindrome判断输入字符串char *s是否为回文。若是则返回true,否则返回false

解:

    要注意两点:

  1.  要先以 '\0' 结尾来判断计算出字符串的长度
  2.  不能对 s 进行 ++ 操作,否则指针指向的元素就变了,需要一个 tmp 指针来遍历 s 字符串。
bool palindrome(char *s)
{
    int len = 0;
    char *tmp = s;
    while(*tmp != '\0')
    {
        ++tmp;
        ++len;
    }
    int l = 0, r = len - 1;
    while(l < r)
    {
        if(s[l] != s[r]) return false;
        --r;
        ++l;
    }
    return true;
}

6-6 数组循环右移

本题要求实现一个对数组进行循环右移的简单函数:一个数组a中存有n(>0)个整数,将每个整数循环向右移m(≥0)个位置,即将a中的数据由(a​0​​a​1​​⋯a​n−1​​)变换为(a​n−m​​⋯a​n−1​​a​0​​a​1​​⋯a​n−m−1​​)(最后m个数循环移至最前面的m个位置)。

函数接口定义:

int ArrayShift( int a[], int n, int m );

其中a[]是用户传入的数组;n是数组的大小;m是右移的位数。函数ArrayShift须将循环右移后的数组仍然存在a[]中。

解:

    用一个tmp数组,存需要移到后边的数,分三步完成右移操作即可。

int ArrayShift(int a[], int n, int m) // 返回值没有用到没有意义
{
    if(m == 0) return 0;
    m = m % n;
    int t[m];
    for(int i = 0; i < m; i++)      // 把 a[n - m] ~ a[n - 1] 存起来
        t[i] = a[n - m + i];
    for(int i = n - 1; i >= m; i--) // 赋值 a[m] ~ a[n - 1] 为 a[0] ~ a[n - m - 1],但是必须从右往左
        a[i] = a[i - m];
    for(int i = 0; i < m; i++)      // 赋值 a[0] ~ a[m - 1] 为 a[n - m] ~ a[n - 1]
        a[i] = t[i];
}

6-7 拆分实数的整数与小数部分

函数接口定义:

void splitfloat( float x, int *intpart, float *fracpart );

其中x是被拆分的实数(0≤x<10000),*intpart*fracpart分别是将实数x拆分出来的整数部分与小数部分。

void splitfloat(float x, int *intpart, float *fracpart)
{
    *intpart  = (int)x;
    *fracpart = x - *intpart;
}

6-8 分类统计各类字符个数

本题要求实现一个函数,统计给定字符串中的大写字母、小写字母、空格、数字以及其它字符各有多少。

函数接口定义:

void StringCount( char *s );

其中 char *s 是用户传入的字符串。函数StringCount须在一行内按照

大写字母个数 小写字母个数 空格个数 数字个数 其它字符个数

的格式输出。

void StringCount(char *s)
{
    int upper = 0, lower = 0, number = 0, space = 0, others = 0;
    while(*s != '\0')
    {
        if(*s >= 'A' && *s <= 'Z')      ++upper;
        else if(*s >= 'a' && *s <= 'z') ++lower;
        else if(*s == ' ')              ++space;
        else if(*s >= '0' && *s <= '9') ++number;
        else                            ++others;
        ++s;
    }
    printf("%d %d %d %d %d\n", upper, lower, space, number, others);
}

7-1 冒泡法排序

将N个整数按从小到大排序的冒泡排序法是这样工作的:从头到尾比较相邻两个元素,如果前面的元素大于其紧随的后面元素,则交换它们。通过一遍扫描,则最后一个元素必定是最大的元素。然后用同样的方法对前N−1个元素进行第二遍扫描。依此类推,最后只需处理两个元素,就完成了对N个数的排序。

本题要求对任意给定的K(<N),输出扫描完第K遍后的中间结果数列。

输入格式:

输入在第1行中给出N和K(1≤K<N≤100),在第2行中给出N个待排序的整数,数字间以空格分隔。

输出格式:

在一行中输出冒泡排序法扫描完第K遍后的中间结果数列,数字间以空格分隔,但末尾不得有多余空格。

输入样例:

6 2
2 3 5 1 6 4

输出样例:

2 1 3 4 5 6
#include <stdio.h>
int main()
{
    int n, k;
    scanf("%d%d", &n, &k);
    int a[n];
    for(int i = 0; i < n; i++) scanf("%d", &a[i]);
    for(int i = 0; i < k; i++)
        for(int j = 0; j < n - i - 1; j++)
            if(a[j] > a[j + 1])
            {
                int tmp = a[j];
                a[j] = a[j + 1];
                a[j + 1] = tmp;
            }
    printf("%d", a[0]);
    for(int i = 1; i < n; i++)
        printf(" %d", a[i]);
    return 0;
}

7-2 猴子选大王

一群猴子要选新猴王。新猴王的选择方法是:让N只候选猴子围成一圈,从某位置起顺序编号为1~N号。从第1号开始报数,每轮从1报到3,凡报到3的猴子即退出圈子,接着又从紧邻的下一只猴子开始同样的报数。如此不断循环,最后剩下的一只猴子就选为猴王。请问是原来第几号猴子当选猴王?

输入格式:

输入在一行中给一个正整数N(≤1000)。

输出格式:

在一行中输出当选猴王的编号。

输入样例:

11

输出样例:

7

解:

    用纯计算机方法解,不用任何数学公式,就是用一个长度为 n 的数组(全部初始化为1),每遍历3个让当前这个位置的值变为0。报数的时候,只有值为1的位置才能报数,值为0的不能报数即可。

#include <stdio.h>
int main()
{
    int n;
    scanf("%d", &n);
    if(n == 1)
    {
        printf("1\n");    // 就一个人的情况
        return 0;
    }
    int a[n];
    for(int i = 0; i < n; i++) a[i] = 1;
    int remain = n, cur = 0;
    while(1)
    {  
        int i = 0;
        while(i < 2)
        {
            if(a[cur] == 1)
                ++i;
            cur = (cur + 1) % n;    // 每次报数不能 ++cur,必须 cur = (cur + 1) % n
        }
        while(a[cur] == 0)  cur = (cur + 1) % n;
        a[cur] = 0;
        --remain;
        while(a[cur] == 0)  cur = (cur + 1) % n;
        if(remain == 1)
        {
            printf("%d\n", cur + 1);
            return 0;
        }
    }
    return 0;
}

7-3 组合数的和

给定 N 个非 0 的个位数字,用其中任意 2 个数字都可以组合成 1 个 2 位的数字。要求所有可能组合出来的 2 位数字的和。例如给定 2、5、8,则可以组合出:25、28、52、58、82、85,它们的和为330。

输入格式:

输入在第一行中给出 N(1 < N < 10),随后一行给出 N 个不同的非 0 个位数字。数字间以空格分隔。

输出格式:

输出所有可能组合出来的2位数字的和。

#include <stdio.h>
int main()
{
    int n,sum = 0;
    scanf("%d", &n);
    int a[n];
    for(int i = 0; i < n; i++)  scanf("%d", &a[i]);
    for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++)
            if(i != j)
                sum += a[i] * 10 + a[j];
    printf("%d\n", sum);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Bob__yuan/article/details/85115477