PTA - C程式設計 NoC - 指標 (11道題)

Bob__yuan發表於2018-12-20
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;
}

 

相關文章