C高級第三次作業


PTA第一部分

6-1 輸出月份英文名(15 分)

本題要求實現函數,可以返回一個給定月份的英文名稱。

函數接口定義:

char *getmonth( int n );

函數getmonth應返回存儲了n對應的月份英文名稱的字符串頭指針。如果傳入的參數n不是一個代表月份的數字,則返回空指針NULL。

裁判測試程序樣例:

#include <stdio.h>

char *getmonth( int n );

int main()
{
    int n;
    char *s;

    scanf("%d", &n);
    s = getmonth(n);
    if ( s==NULL ) printf("wrong input!\n");
    else printf("%s\n", s);

    return 0;
}

/* 你的代碼將被嵌在這里 */

輸入樣例1:

5

輸出樣例1:

May

輸入樣例2:

15

輸出樣例2:

wrong input!

1.設計思路:

(1).題目算法描述
第一步:定義*month[]並初始化為各個月份
第二步:定義*s
第三步:當n是月份時將對應的月份賦值給s,否則將wrong input!賦值給s
第四步:return s

(2).流程圖
暫略

2.實驗代碼

char *getmonth( int n )
{
    char *month[13] = {"January","February","March","April","May","June","July","August","September","October","November","December","wrong input!"};
    char *s;
    if(n>=1 && n<=12)
    {
        s = month[n-1];
    }else
    {
        s = month[12];
    }
    return s;
}

2.錯誤調試

答案正確

答案正確

6-2 查找星期(15 分)

本題要求實現函數,可以根據下表查找到星期,返回對應的序號。

序號 星期
0 Sunday
1 Monday
2 Tuesday
3 Wednesday
4 Thursday
5 Friday
6 Saturday

函數接口定義:

int getindex( char *s );

函數getindex應返回字符串s序號。如果傳入的參數s不是一個代表星期的字符串,則返回-1。

裁判測試程序樣例:

#include <stdio.h>
#include <string.h>

#define MAXS 80

int getindex( char *s );

int main()
{
    int n;
    char s[MAXS];

    scanf("%s", s);
    n = getindex(s);
    if ( n==-1 ) printf("wrong input!\n");
    else printf("%d\n", n);

    return 0;
}

/* 你的代碼將被嵌在這里 */

輸入樣例1:

Tuesday

輸出樣例1:

2

輸入樣例2:

today

輸出樣例2:

wrong input!

1.設計思路:

(1).題目算法描述
第一步:定義*week[]並初始化為各個星期
第二步:遍歷week判斷是否與s相同
第三步:相同返回對應下標,不相同是返回-1

(2).流程圖
暫略

2.實驗代碼

int getindex( char *s )
{
    int i=0;
    char *week[8] = {"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
    for(i=0;i<7;i++)
    {
        if(strcmp(s,week[i])==0)
        {
            break;
        }
    }
    if(i<7){
        return i;
    }else{
        return -1;
    }
}


2.錯誤調試

答案正確

答案正確

6-3 計算最長的字符串長度(15 分)

本題要求實現一個函數,用於計算有n個元素的指針數組s中最長的字符串的長度。

函數接口定義:

int max_len( char *s[], int n );

其中n個字符串存儲在s[]中,函數max_len應返回其中最長字符串的長度。

裁判測試程序樣例:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAXN 10
#define MAXS 20

int max_len( char *s[], int n );

int main()
{
    int i, n;
    char *string[MAXN] = {NULL};

    scanf("%d", &n);
    for(i = 0; i < n; i++) {
        string[i] = (char *)malloc(sizeof(char)*MAXS);
        scanf("%s", string[i]);
    }
    printf("%d\n", max_len(string, n));

    return 0;
}

/* 你的代碼將被嵌在這里 */

輸入樣例:

4
blue
yellow
red
green

輸出樣例:

6

1.設計思路:

(1).題目算法描述
第一步:定義i,max
第二步:for循環遍歷s判斷每個字符串長度與max的關系將最大長度賦值給max
第三步:返回max

(2).流程圖
流程圖

2.實驗代碼

int max_len( char *s[], int n )
{
    int i=0,max=0;
    for(i=0;i<n;i++)
    {
        if(strlen(s[i])>max){
            max = strlen(s[i]);
        }
    }
    return max;

}

2.錯誤調試

答案正確

答案正確

6-4 指定位置輸出字符串(20 分)

本題要求實現一個函數,對給定的一個字符串和兩個字符,打印出給定字符串中從與第一個字符匹配的位置開始到與第二個字符匹配的位置之間的所有字符。

函數接口定義:

char *match( char *s, char ch1, char ch2 );

函數match應打印s中從ch1ch2之間的所有字符,並且返回ch1的地址。

裁判測試程序樣例:

#include <stdio.h>

#define MAXS 10

char *match( char *s, char ch1, char ch2 );

int main()
{
    char str[MAXS], ch_start, ch_end, *p;

    scanf("%s\n", str);
    scanf("%c %c", &ch_start, &ch_end);
    p = match(str, ch_start, ch_end);
    printf("%s\n", p);

    return 0;
}

/* 你的代碼將被嵌在這里 */

輸入樣例1:

program
r g

輸出樣例1:

rog
rogram

輸入樣例2:

program
z o

輸出樣例2:

(空行)
(空行)

輸入樣例3:

program
g z

輸出樣例3:

gram
gram

1.設計思路:

(1).題目算法描述
第一步:定義整型變量i,j,len
第二步:定義指針變量並初始化為NULL
第三步:統計len的長度並將值賦給len
第四步:遍歷s當找到與找到第一個與ch1相同的字符是讓p指向它
第五步:從第一個與ch1相同字符串之后繼續向下遍歷,如果其后的字符串與ch2不相同則輸出此字符串繼續向下遍歷,如果相同輸出此字符串並換行返回p
第六步:當遍歷全部完成后則換行返回p

(2).流程圖
暫略

2.實驗代碼

char *match( char *s, char ch1, char ch2 )
{
    int i = 0, j = 0,len = 0;
    char *p=NULL;
    len = strlen(s);//統計字符串長度
    for(i = 0;i < len;i++)//遍歷s
    {
        if(*(s+i)==ch1){
            p = &s[i];//讓p指向第一個與ch1相同的字符
            for(j = i;j < len;j++)//從第一個相同的字符開始繼續向下遍歷
            {
                if(s[j]!=ch2){
                    printf("%c",*(s+j));//第一個字符之后的字符如果與最后一個字符串不相同則輸出此字符
                }
                if(s[j] == ch2){
                    printf("%c\n",*(s+j));//當與第二個字符相同時則輸出此字符並換行后返回p
                    return p;
                }
            }
            printf("\n");
            return p;
        }
    }
    printf("\n");
    return p;
}


2.錯誤調試

錯誤提示1:段錯誤
改正方法:將指針p初始化為NULL
改正后的代碼在Cold::Blocks上每個示例均能運行出正確答案,但是在PTA上仍是部分正確
錯誤提示

求大佬指教!!!

編程題

有一個axb的數組,該數組里面順序存放了從1到a*b的數字。其中a是你大學號的前三位數字,b是你大學號的后四位數字,比如你的學號是2017023936,那么數組大小是201 x 3936,數組中順序存放了1到791136(201和3936的積)的整數. 要求用篩選法,把該數組里的質數找出並打印出來,打印格式為5個質數一行,數字間用空格隔開。

篩選法具體做法是:先把N個自然數按次序排列起來。1不是質數,也不是合數,要划去。第二個數2是質數留下來,而把2后面所有能被2整除的數都划去。2后面第一個沒划去的數是3,把3留下,再把3后面所有能被3整除的數都划去。3后面第一個沒划去的數是5,把5留下,再把5后面所有能被5整除的數都划去。這樣一直做下去,就會把不超過N的全部合數都篩掉,留下的就是不超過N的全部質數。

1.設計思路:

參考教程:https://baike.baidu.com/item/篩選法/9393288?fr=aladdin#2_2(來源百度百科)
(1).題目算法描述
第一步:計算學號前三位和后四位的乘積並賦值給n
第二步:定義大小為n的數組axb
第三步:遍歷數組輸入1到n的值
第四步:從2開始遍歷數組將所有合數和能被此合數整除的數全都賦值為一
第五步:輸出值不是1的數

(2).流程圖
流程圖

2.實驗代碼

#include <stdio.h>
#include <math.h>
int main ()
{
    long int n=0,i=0,j=0,x=0;
    n = 201*3990;
    int axb[n];

    for(i=1;i<n;i++)
    {
        axb[i-1] = i;
    }
    for(i=1;i<=n;i++)
    {
        for(j=2;j<=sqrt(i);j++)
        {
            if(i%j==0){
                axb[i-1]=1;
            }
        }
    }
    for(i=0,x=0;i<n;i++)
    {
        if(axb[i]!=1){
            printf("%d ",axb[i]);
            x++;
            if(x%5 == 0){
            printf("\n");
            }
        }
    }
    return 0;
}

2.錯誤調試

修改

經過課堂講解后發現自己的錯誤,沒有將存儲學號的數組寫成二維數組。
修改后的代碼如下


#include <stdio.h>
#define N 201
#define M 3990

int a[N][M];//全局變量
void del(int a[N][M],int x){
     int i=0,j=0;
     for(i=0;i<N;i++){
        for(j=1;j<M;j++){
             if(i==0 && j==0){
                    continue;
             }
             if(a[i][j]>x &&(a[i][j] % x== 0)){
                    a[i][j]=0;
             }
        }
    }
}

int main ()
{
    int i=0,j=0,num=1,count=0;
    for(i=0;i<N;i++){
        for(j=0;j<M;j++){
             a[i][j] = num++;
        }
    }
    a[0][0]=0;//去掉a[0][0]從第一個數開始
    for(i=0;i<N;i++){
        for(j=0;j<M;j++){
             if(a[i][j] != 0){
                del(a,a[i][j]);
             }
        }
    }
    for(i=0;i<N;i++){
        for(j=0;j<M;j++){
             if(a[i][j] != 0){
                printf("%d ",a[i][j]);
                count++;
                if(count%5 == 0){
                    printf("\n");
                }
             }
        }
    }
    return 0;
}


答案正確

輸出結果截圖

PTA第二部分

6-1 奇數值結點鏈表(20 分)

本題要求實現兩個函數,分別將讀入的數據存儲為單鏈表、將鏈表中奇數值的結點重新組成一個新的鏈表。鏈表結點定義如下:

struct ListNode {
    int data;
    ListNode *next;
};

函數接口定義:

struct ListNode *readlist();
struct ListNode *getodd( struct ListNode **L );

函數readlist從標准輸入讀入一系列正整數,按照讀入順序建立單鏈表。當讀到−1時表示輸入結束,函數應返回指向單鏈表頭結點的指針。

函數getodd將單鏈表L中奇數值的結點分離出來,重新組成一個新的鏈表。返回指向新鏈表頭結點的指針,同時將L中存儲的地址改為刪除了奇數值結點后的鏈表的頭結點地址(所以要傳入L的指針)。

裁判測試程序樣例:

#include <stdio.h>
#include <stdlib.h>

struct ListNode {
    int data;
    struct ListNode *next;
};

struct ListNode *readlist();
struct ListNode *getodd( struct ListNode **L );
void printlist( struct ListNode *L )
{
     struct ListNode *p = L;
     while (p) {
           printf("%d ", p->data);
           p = p->next;
     }
     printf("\n");
}

int main()
{
    struct ListNode *L, *Odd;
    L = readlist();
    Odd = getodd(&L);
    printlist(Odd);
    printlist(L);

    return 0;
}

/* 你的代碼將被嵌在這里 */

輸入樣例:

1 2 2 3 4 5 6 7 -1

輸出樣例:

1 3 5 7 
2 2 4 6

1.設計思路:

(1).題目算法描述
第一個部分:
第一步:定義num並初始化為0
第二步:定義結構指針head p tail並初始化
第三步:用動態內存分配為p申請空間;讀入num,當num不是-1時將其賦給p->data;如果head是空head=p否則tail->next=p
第四步:重復以上過程知道讀入的數據為-1
第五步:釋放p
第六步:return head
第二部分:
第一步:定義n並初始化為0
第二步:定義結構指針head,tail,q,p,p1,p2,ptr
第三步:當p->data為奇數時,用動態內存分配為q申請空間q->data = p->data;q->next = NULL;如果head為空則head=q否則tail->next=q然后將q的值賦給tail將p的值賦給ptr,p指向下一個節點,並釋放申請的空間
第四步:當p->data不是奇數時,如果p1為空p1=p否則p2->next =p; p2=p; p= p->next; n=1
第五步:判斷當n=1時p2->next為空
第六步:*L = p1
第七步:return head
(2).流程圖
暫略

2.實驗代碼

struct ListNode *readlist(){
    int num=0;
    struct ListNode *head=NULL, *p=NULL, *tail=NULL;
    p = (struct ListNode*)malloc(sizeof(struct ListNode));
    scanf("%d", &num);
    while(num != -1){
        p->data = num;
        p->next=NULL;
        if(head == NULL){
            head=p;
        }
        else{
            tail->next=p;
        }
        tail=p;
        p=(struct ListNode*)malloc(sizeof(struct ListNode));
        scanf("%d", &num);
    }
    free(p);
    return head;
}
  struct ListNode *getodd(struct ListNode **L){
      int n = 0;
      struct ListNode *head=NULL, *tail=NULL, *q=NULL, *p=*L, *p1=NULL, *p2=NULL, *ptr=NULL;

      while (p!=NULL)
      {
          if (p->data % 2 != 0)
          {
              q = (struct ListNode *) malloc(sizeof(struct ListNode));
              q->data = p->data;
              q->next = NULL;
              if (head == NULL)
                  head = q;
              else
                  tail->next = q;
              tail = q;
              ptr = p;
              p = p->next;
              free(ptr);
          }
          else
          {
              if (p1 == NULL){
                p1 = p;
              }
              else{
                p2->next = p;
              }
              p2 = p;
              p = p->next;
              n = 1;
          }
      }
      if (n==1){
        p2->next = NULL;
      }
      *L = p1;
      return head;
  }


2.錯誤調試

錯誤提示:全是奇數全是偶數第一個是奇數的測試點答案錯誤
錯誤改正:第一次上完課后對相關鏈表的操作只是知道大概的操作思路,並不清楚相關的代碼應該怎么寫,對於相關插入、刪除的寫法更是一頭霧水,在網上簡單的看來相關的資料但並不是十分理解。上了第二次課后理解的相對好了一些,重新寫了所有代碼,以上貼的是修改后的代碼

6-2 學生成績鏈表處理(20 分)

本題要求實現兩個函數,一個將輸入的學生成績組織成單向鏈表;另一個將成績低於某分數線的學生結點從鏈表中刪除。

函數接口定義:

struct stud_node *createlist();
struct stud_node *deletelist( struct stud_node *head, int min_score );

函數createlist利用scanf從輸入中獲取學生的信息,將其組織成單向鏈表,並返回鏈表頭指針。鏈表節點結構定義如下:

struct stud_node {
    int              num;      /*學號*/
    char             name[20]; /*姓名*/
    int              score;    /*成績*/
    struct stud_node *next;    /*指向下個結點的指針*/
};

輸入為若干個學生的信息(學號、姓名、成績),當輸入學號為0時結束。

函數deletelist從以head為頭指針的鏈表中刪除成績低於min_score的學生,並返回結果鏈表的頭指針。

裁判測試程序樣例:

#include <stdio.h>
#include <stdlib.h>

struct stud_node {
     int    num;
     char   name[20];
     int    score;
     struct stud_node *next;
};

struct stud_node *createlist();
struct stud_node *deletelist( struct stud_node *head, int min_score );

int main()
{
    int min_score;
    struct stud_node *p, *head = NULL;

    head = createlist();
    scanf("%d", &min_score);
    head = deletelist(head, min_score);
    for ( p = head; p != NULL; p = p->next )
        printf("%d %s %d\n", p->num, p->name, p->score);

    return 0;
}

/* 你的代碼將被嵌在這里 */

輸入樣例:

1 zhang 78
2 wang 80
3 li 75
4 zhao 85
0
80

輸出樣例:

2 wang 80
4 zhao 85

1.設計思路:

(1).題目算法描述
第一部分:
第一步:定義結構指針head,tail,q並初始化
第二步:定義num並讀入num
第三步:當num不等於0時,動態內存分配為q申請空間;讀入q->name和q->score;當head為空的時候head=q否則tail->next=q
第四步:tail=q;繼續讀入num
第五步:當num等於0時停止讀入並return head
第二部分:
第一步:定義結構指針ptr1和ptr2
第二步:當head不為空並且head->score小於min->score時ptr2=head;head=head->next;並釋放ptr2的空間
第三步:當head為空時return NULL;
第四步:ptr1=head;ptr2=head->next
第五步:當ptr2不為空時 判斷如果ptr2->score小於min_score則ptr1->next = ptr2->next;並釋放ptr2的空間否則ptr1=ptr2然后ptr2=ptr1->next
第六步:return head;
(2).流程圖
流程圖
流程圖

2.實驗代碼

struct stud_node *createlist()
{
    struct stud_node *head, *tail, *q;
    head = NULL;
    tail = NULL;
    int num;
    scanf ("%d", &num);
    while (num != 0)
    {
        q = (struct stud_node *)malloc (sizeof (struct stud_node));
        scanf ("%s %d", q->name, &q->score);
        q->num = num;
        q->next = NULL;
        if (head == NULL){
            head = q;
        }
        else{
            tail->next = q;
        }
        tail = q;
        scanf ("%d", &num);
    }
    return head;
}

struct stud_node *deletelist( struct stud_node *head, int min_score )
{
    struct stud_node *ptr1, *ptr2;
    while (head != NULL && head->score < min_score)
    {
        ptr2 = head;
        head = head->next;
        free(ptr2);
    }
    if (head == NULL){
        return NULL;
    }
    ptr1 = head;
    ptr2 = head->next;
    while (ptr2 != NULL)
    {
        if (ptr2->score < min_score) {
            ptr1->next = ptr2->next;
            free(ptr2);
        }
        else{
             ptr1 = ptr2;
        }
        ptr2 = ptr1->next;
    }
    return head;
}

2.錯誤調試

6-3 鏈表拼接(20 分)

本題要求實現一個合並兩個有序鏈表的簡單函數。鏈表結點定義如下:

struct ListNode {
    int data;
    struct ListNode *next;
};

函數接口定義:

struct ListNode *mergelists(struct ListNode *list1, struct ListNode *list2);

其中list1list2是用戶傳入的兩個按data升序鏈接的鏈表的頭指針;函數mergelists將兩個鏈表合並成一個按data升序鏈接的鏈表,並返回結果鏈表的頭指針。

裁判測試程序樣例:

#include <stdio.h>
#include <stdlib.h>

struct ListNode {
    int data;
    struct ListNode *next;
};

struct ListNode *createlist(); /*裁判實現,細節不表*/
struct ListNode *mergelists(struct ListNode *list1, struct ListNode *list2);
void printlist( struct ListNode *head )
{
     struct ListNode *p = head;
     while (p) {
           printf("%d ", p->data);
           p = p->next;
     }
     printf("\n");
}

int main()
{
    struct ListNode  *list1, *list2;

    list1 = createlist();
    list2 = createlist();
    list1 = mergelists(list1, list2);
    printlist(list1);
	
    return 0;
}

/* 你的代碼將被嵌在這里 */

輸入樣例:

1 3 5 7 -1
2 4 6 -1

輸出樣例:

1 2 3 4 5 6 7

1.設計思路:

(1).題目算法描述
第一步:定義結構指針p,head,tail並初始化
第二步:定義整型數組list[100]和整型變量i,j,swap,count並初始化為0
第三步:當list1不為空時list[i]=list1->data;list1=list1->next;i++;count++;
第四步:當list2不為空時list[i]=list2->data;list2=list2->next;i++;count++;
第五步:對list進行排序
第六步:遍歷list用動態內存分配為p申請空間p->data=list[i];p->next=NULL;判斷當head=NULL時head=p否則tail->next=p;然后tail=p;
第七步:return head
(2).流程圖
流程圖

2.實驗代碼

struct ListNode *mergelists(struct ListNode *list1, struct ListNode *list2){
    struct ListNode *p=NULL,*head=NULL,*tail=NULL;
    int list[100],i=0,j=0,swap=0,count=0;
    while(list1!=NULL){
        list[i]=list1->data;
        list1=list1->next;
        i++;
        count++;
    }
    while(list2!=NULL){
        list[i]=list2->data;
        list2=list2->next;
        i++;
        count++;
    }
    for(i=0;i<count;i++){
        for(j=i+1;j<count;j++){
                if(list[i]>list[j]){
                    swap=list[i];list[i]=list[j];list[j]=swap;
                }
        }
    }
    for(i=0;i<count;i++){
        p=(struct ListNode*)malloc(sizeof(struct ListNode));
        p->data=list[i];
        p->next=NULL;
        if(head==NULL){
            head=p;
        }
        else{
            tail->next=p;
        }
        tail=p;
    }
    return head;
}


2.錯誤調試


題目提交列表:

1.學習進度總結

(1).指針數組:學習了用指針數組對字符串進行相關的處理
(2).篩選法:學習了篩選法的相關思路和具體的程序實現方法
(3).鏈表:學習並了解了鏈表的相關知識,明確了鏈表的優點,掌握了鏈表的相關思路但是鏈表具體的代碼實現方法還有待加強練習
(4).結構:為了更好的學習鏈表在mooc復習了相關結構的內容
(5)二級指針:還是感覺用起來很混亂,不清晰

2.問題回答

(1)如何理解指針數組,它與指針、數組有何關系?為何可以用二級指針對指針數組進行操作?

指針數組:元素全都是指針的數組
數組的名稱可以代表數組首元素的地址,有了首元素的地址就可以用二級指針對數組的元素進行操作

(2)將C高級第三次PTA作業(1)任何一個題目改為使用二級指針對指針數組進行操作。

修改C高級第三次PTA作業(1)中的第一題
修改后的代碼:

char *getmonth( int n )
{
    char *month[13] = {"January","February","March","April","May","June","July","August","September","October","November","December","wrong input!"};
    char **s;
    if(n>=1 && n<=12)
    {
        s = &month[n-1];
    }
    else
    {
        s = &month[12];
    }
    return *s;
}

(3)用指針數組處理多個字符串有何優勢?可以直接輸入多個字符串給未初始化的指針數組嗎?為什么?

優勢:處理起來更加便捷
不可以,指針沒有初始化的話就不知道指向哪里,有可能指的是不允許用戶更改的區域,這時候就會出現段錯誤

2.代碼托管

我的GitHub地址:https://github.com/XINJY/The-homework-of-C
上傳成功截圖:

3.作業點評

李伍壹:http://www.cnblogs.com/chenxidream/p/8778302.html
李新華:http://www.cnblogs.com/Lixinhua18/p/8810369.html
馬鈺娟:http://www.cnblogs.com/dfgfds/p/8906883.html

4.表格和折線圖(由於博客字數太多,所以單獨做了折線圖)




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM