這個做業屬於哪一個課程 | C語言程序設計Ⅱ | |
---|---|---|
這個做業要求在哪裏 | http://www.javashuo.com/article/p-rbjtrmhq-hg.html | |
我在這個課程的目標是 | 靈活的使用遞歸函數和宏定義來解決問題 | |
這個做業在那個具體方面幫助我實現目標 | 使我對遞歸函數有了必定的瞭解,瞭解了宏定義函數而且能靈活的使用,本身的知識庫獲得了的拓展 | |
參考文獻 | c語言教課書和百度以及對經典例題的練習 |
7-1 漢諾塔問題* (10 分)html
漢諾塔是一個源於印度古老傳說的益智玩具。聽說大梵天創造世界的時候作了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞着64片黃金圓盤,大梵天命令僧侶把圓盤移到另外一根柱子上,而且規定:在小圓盤上不能放大圓盤,每次只能移動一個圓盤。當全部圓盤都移到另外一根柱子上時,世界就會毀滅。、
程序員
請編寫程序,輸入漢諾塔圓片的數量,輸出移動漢諾塔的步驟。編程
圓盤數 起始柱 目的柱 過分柱
數組
移動漢諾塔的步驟 每行顯示一步操做,具體格式爲: 盤片號: 起始柱 -> 目的柱 其中盤片號從 1 開始由小到大順序編號。
3 a c b
1: a -> c 2: a -> b 1: c -> b 3: a -> c 1: b -> a 2: b -> c 1: a -> c
#include<stdio.h> void hanio (int n,char a,char b,char c); int main() { int n; char a,b,c; scanf ("%d\n",&n); scanf ("%c %c %c",&a,&b,&c); hanio (n,a,b,c); return 0; } void hanio (int n,char a,char b,char c) { if (n==1) { printf ("%d: %c -> %c\n",n,a,b); } else { hanio (n-1,a,c,b); printf ("%d: %c -> %c\n",n,a,b); hanio (n-1,c,b,a); } }
一、在寫題目時出現了答案錯誤和部分正確
解決辦法:本身認真檢查和翻閱資料詢問助教,在輸出時因爲是由我寫的代碼是由a最終移到b,因此輸出語句時,printf ("%d: %c -> %c\n",n,a,b);,以前寫的是a到c,由於它要由c過渡到b嘛,就在中間輸出a到c。還有就是要輸出盤子的編號,以前沒看清,因此沒輸出,在輸出hanio (n-1,a,c,b);本身都不知道什麼意思,最後百度和詢問別人,加上一下午的實驗才懂,按我本身的理解是把n-1由a->c,在c->b,把第n個盤子由a->c,再把n-1個盤子從b移到c。下句也是這樣理解的。
數據結構
7-2 估值一億的AI核心代碼 (20 分)
函數
以上圖片來自新浪微博。
本題要求你實現一個稍微更值錢一點的 AI 英文問答程序,規則是:
不管用戶說什麼,首先把對方說的話在一行中原樣打印出來;
消除原文中多餘空格:把相鄰單詞間的多個空格換成 1 個空格,把行首尾的空格所有刪掉,把標點符號前面的空格刪掉;
把原文中全部大寫英文字母變成小寫,除了 I
;
把原文中全部獨立的can you
、could you
對應地換成I can
、I could
—— 這裏「獨立」是指被空格或標點符號分隔開的單詞;
把原文中全部獨立的 I
和 me
換成 you
;
把原文中全部的問號 ?
換成驚歎號!
;
在一行中輸出替換後的句子做爲 AI 的回答。學習
輸入首先在第一行給出不超過 10 的正整數 N,隨後 N 行,每行給出一句不超過 1000 個字符的、以回車結尾的用戶的對話,對話爲非空字符串,僅包括字母、數字、空格、可見的半角標點符號。
this
按題面要求輸出,每一個 AI 的回答前要加上 AI: 和一個空格。
設計
6 Hello ? Good to chat with you can you speak Chinese? Really? Could you show me 5 What Is this prime? I,don 't know
Hello ? AI: hello! Good to chat with you AI: good to chat with you can you speak Chinese? AI: I can speak chinese! Really? AI: really! Could you show me 5 AI: I could show you 5 What Is this prime? I,don 't know AI: what Is this prime! you,don't know
#include <stdio.h> #include <string.h> int iszf(char a){ if(a>='0' && a<='9'){ return 1; } if(a>='a' && a<='z'){ return 1; } if(a>='A' && a<='Z'){ return 1; } return 0; } char zxxx(char a){ if(a>='A' && a<='Z'){ if(a=='I'){ return 'I'; }else{ return a+32; } } return a; } int main(){ int n; scanf("%d\n",&n); while(n--){ char a[1010],b[1010]; int la=0,lb=0; gets(a); printf("%s\n",a); la=strlen(a); int lk=0; int ff=0; for(int i=0;i<la;i++){ if(a[i]==' '){ lk++; }else if(!iszf(a[i])){ lk=0; ff=1; b[lb++]=zxxx(a[i]); }else{ if(lk>0 && ff){ b[lb++]=' '; } lk=0; ff=1; b[lb++]=zxxx(a[i]); } } b[lb]=0; printf("AI: "); for(int i=0;i<lb;i++){ if( (b[i]=='I')&& (i==0||!iszf(b[i-1]))&& (!iszf(b[i+1])) ){ printf("you"); }else if( (b[i]=='m'&&b[i+1]=='e')&& (i==0||!iszf(b[i-1]))&& (!iszf(b[i+2])) ){ printf("you"); i+=1; }else if(b[i]=='?'){ printf("!"); }else if( (b[i]=='c'&&b[i+1]=='a'&&b[i+2]=='n'&&b[i+3]==' '&&b[i+4]=='y'&&b[i+5]=='o'&&b[i+6]=='u')&& (i==0||!iszf(b[i-1]))&& (!iszf(b[i+7])) ){ printf("I can"); i+=6; }else if( (b[i]=='c'&&b[i+1]=='o'&&b[i+2]=='u'&&b[i+3]=='l'&&b[i+4]=='d'&&b[i+5]==' '&&b[i+6]=='y'&&b[i+7]=='o'&&b[i+8]=='u')&& (i==0||!iszf(b[i-1]))&& (!iszf(b[i+9])) ){ printf("I could"); i+=8; } else{ printf("%c",b[i]); } } printf("\n"); } return 0; }
本題調試過程當中遇到太多的問題了,有不少的不懂的地方,這是借鑑了他人的代碼完成的。
解決辦法:百度和自查資料
在mian函數以前編寫代碼是爲了定義全局變量,從頭日後遍歷,循環比較四個單詞,發現當前位置存在四個單詞之一就判斷它的獨立性; 若是該單詞獨立,那麼替換成目標單詞,而後遍歷的下標加上目標單詞的長度;
若是沒發現或者單詞不獨立,那麼遍歷的下標加 1 。3d
7-3 ***八皇后問題 (20 分)
在國際象棋中,皇后是最厲害的棋子,能夠橫走、直走,還能夠斜走。棋手馬克斯·貝瑟爾 1848 年提出著名的八皇后問題:即在 8 × 8 的棋盤上擺放八個皇后,使其不能互相攻擊 —— 即任意兩個皇后都不能處於同一行、同一列或同一條斜線上。
如今咱們把棋盤擴展到 n × n 的棋盤上擺放 n 個皇后,請問該怎麼擺?請編寫程序,輸入正整數 n,輸出所有擺法(棋盤格子空白處顯示句點「.」,皇后處顯示字母「Q」,每兩格之間空一格)。
正整數 n (0 < n ≤ 12)
若問題有解,則輸出所有擺法(兩種擺法之間空一行),不然輸出 None。
要求:試探的順序逐行從左往右的順序進行,請參看輸出樣例2。
3
None
6
. Q . . . . . . . Q . . . . . . . Q Q . . . . . . . Q . . . . . . . Q . . . Q . . . . . . . . Q . Q . . . . . . . . Q . Q . . . . . . . . Q . . . . . Q . . Q . . . . . . . . . Q . . Q . . . . . . . . . Q . . Q . . . . . . . Q . . . Q . . . Q . . . . . . . . . . Q . . . Q . . . Q . . . .
7-1 求迷宮最短通道 (20 分)
遞歸求解迷宮最短通道的總步長。輸入一個迷宮,求從入口通向出口的可行路徑中最短的路徑長度。爲簡化問題,迷宮用二維數組 int maze[10][10]來存儲障礙物的分佈,假設迷宮的橫向和縱向尺寸的大小是同樣的,並由程序運行讀入, 若讀入迷宮大小的值是n(3<n<=10),則該迷宮橫向或縱向尺寸都是n,規定迷宮最外面的一圈是障礙物,迷宮的入口是maze[1][1],出口是maze[n-2][n-2], 若maze[i][j] = 1表明該位置是障礙物,若maze[i][j] = 0表明該位置是能夠行走的空位(0<=i<=n-1, 0<=j<=n-1)。求從入口maze[1][1]到出口maze[n-2][n-2]能夠走通的路徑上經歷的最短的總步長。要求迷宮中只容許在水平或上下四個方向的空位上行走,走過的位置不能重複走。
輸入迷宮大小的整數n, 以及n行和n列的二維數組(數組元素1表明障礙物,0表明空位)
如有可行的通道則輸出一個整數,表明求出的通道的最短步長;若沒有通道則輸出"No solution"
10 1 1 1 1 1 1 1 1 1 1 1 0 0 1 0 0 0 1 0 1 1 0 0 1 0 0 0 1 0 1 1 0 0 0 0 1 1 0 0 1 1 0 1 1 1 0 0 0 0 1 1 0 0 0 1 0 0 0 0 1 1 0 1 0 0 0 1 0 0 1 1 0 1 1 1 0 1 1 0 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1
上述輸入表明的是以下這樣一個迷宮:
其中紅色的小方塊是障礙物,藍色的小方塊是空位,白色的小圓連起來是一條從入口到出口的通道,兩個圓之間表明一個步長。
14
第十二週的教學內容是:第十一章 指針進階
請你們查閱資料,思考以下問題:
請舉實例解釋如下幾個概念:數組指針,指針數組,指針函數,函數指針,二級指針,單向鏈表。(無實例不給分)
請用本身的理解回答。若是有引用他人的文字,請必定要標出出處(使用Markdown的連接方式)。
數組指針:本質是指針,數組指針,指的是數組名的指針,即數組首元素地址的指針。便是指向數組的指針。例如:int (p) [5]=b,即 (p+i) 是二維數組b[i][0]的地址。
#include <stdio.h> int main(){ int a[5] = { 1,2,3,4,5 }; int len = sizeof(arr) / sizeof(int); //求數組長度 int i; for(i=0; i<len; i++){ printf("%d ", *(a+i) ); //*(arr+i)等價於arr[i] } return 0; }
指針數組:指針數組是數組元素爲指針的數組,本質仍是數組,利用數組和指針的結合體,比起單個更高效,數組各個元素都是指針類型用於存放內存地址,格式爲:類型名 數組名 [數組長度],例如:char a[50]
意思是一個字符型的數組a有50個能夠儲存50個字符型數據。定義了50個a[50] 的指針。
int a[1] = "good"; int *p; p = a; printf("%c", *p++); printf("%c", p[1]);
指針函數:帶有指針的函數,即其本質是一個函數,只不過這種函數返回的是一個對應類型的地址。指向函數代碼首地址的指針變量稱爲函數指針。例如:int (f)(int x) -> double (ptr)(double x);
#include<stdio.h> int main() { int f(); int i,a,b; int (*p)(); /* 定義函數指針 */ scanf("%d",&a); p=f; /* 給函數指針p賦值,使它指向函數f */ for(i=1;i<9;i++) { scanf("%d",&b); a=(*p)(a,b); /* 經過指針p調用函數f */ } printf("The Max Number is:%d",a) } f(int x,int y) { int z; z=(x>y)?x:y; return(z); }
函數指針:定義一個指針變量,接收函數的入口地址,讓它指向函數的指針叫函數指針。例如:int (*p) (int int) 定義了一個函數指針p,它能夠指向有兩個整型參數且返回值類型爲int的函數。
#include "stdio.h" main() { char *ch(char *,char *); char str1[]="nice to meet you!"; char str2[]="me too!"; printf("%s",ch(str1,str2)); } char *ch(char *str1,char *str2) { int i; char *p; p=str2 if(*str2==NULL) exit(-1); do { *str2=*str1; str1++; str2++; }while(*str1!=NULL); return(p); }
二級指針:A(即B的地址)是指向指針的指針,稱爲二級指針.例子:int **p,
int a =1; int *b =&a; int **c=&b; cout<<&a<<endl; cout<<b<<endl; cout<<*c<<endl; /*以上輸出都是a的地址,而下面兩行就是b的地址*/ cout<<&b<<endl; cout<<c<<endl;
void GetMemory( char **p, int num ) { *p = (char *) malloc( num ); } void Test( void ) { char *str = NULL; GetMemory( &str, 100 ); strcpy( str, "hello" ); printf( str ); }
單向鏈表:這是常見的動態存儲分佈的數據結構,由若干個同類型的結點串聯而成,最後的結點叫尾點,鏈表的連接方向是單向的,對鏈表的訪問要經過順序讀取從頭部開始;鏈表是使用指針進行構造的列表;又稱爲結點列表,由於鏈表是由一個個結點組裝起來的;其中每一個結點都有指針成員變量指向列表中的下一個結點;列表是由結點構成,head指針指向第一個成爲表頭結點,而終止於最後一個指向nuLL的指針。
#include <stdio.h> #include <stdlib.h> struct grade { int score; struct grade *next; }; typedef struct grade NODE; //typedef爲C語言的關鍵字,做用是爲一種數據類型定義一個新名字。 //使用typedef目的通常有兩個,一個是給變量一個易記且意義明確的新名字, //另外一個是簡化一些比較複雜的類型聲明。 struct grade *create(); //建立鏈表 void insert(NODE *head,NODE *pnew,int i); //插入鏈表 void pdelete(NODE *head,int i); //刪除列表 void display(NODE *head); //輸出鏈表 void Pfree(NODE *head); //銷燬鏈表 int main(int argc, char *argv[]) { struct grade *head,*pnew; head=create(); if(head==NULL) return 0; printf("輸出建立的鏈表:"); display(head); pnew=(NODE *)malloc(sizeof(NODE)); if(pnew==NULL) { printf("建立失敗!"); return 0; } pnew->score=88; insert(head,pnew, 3); //將新節點插入節點3的後面 printf("插入後的鏈表:"); display(head); pdelete(head,3); //刪除節點3 printf("刪除後的鏈表:"); display(head); Pfree(head); return 0; } struct grade *create() { NODE *head,*tail,*pnew; int score; head=(NODE *)malloc(sizeof(NODE)); //建立頭節點. if(head==NULL) //建立失敗返回 { printf("建立失敗!"); return NULL; } head->next=NULL; //頭節點指針域置NULL tail=head; // 開始時尾指針指向頭節點 printf("輸入學生成績:"); while(1) //建立鏈表 { scanf("%d",&score); if(score<0) //成績爲負是退出循環 break; pnew=(NODE *)malloc(sizeof(NODE)); //建立新節點 if(pnew==NULL) //建立失敗返回 { printf("建立失敗!"); return NULL; } pnew->score=score; //新節點數據域存放輸入的成績 pnew->next=NULL; //新節點指針域置NULL tail->next=pnew; //新節點插入到表尾 tail=pnew; //爲指針指向當前的尾節點 } return head; //返回建立鏈表的頭指針 } void insert(NODE *head,NODE *pnew,int i) { NODE *p; int j; p=head; for(j=0;j<i&&p!=NULL;j++) //p指向要插入的第i個節點 p=p->next; if(p==NULL) //節點i不存在 { printf("與插入的節點不存在!"); return; } pnew->next=p->next; //插入節點的指針域指向第i個節點的後繼節點 p->next=pnew; //犟第i個節點的指針域指向插入的新節點 } void pdelete(NODE *head,int i) { NODE *p,*q; int j; if(i==0) //刪除的是頭指針,返回 return; p=head; for(j=1;j<i&&p->next!=NULL;j++) p=p->next; //將p指向要刪除的第i個節點的前驅節點 if(p->next==NULL) //代表鏈表中的節點不存在 { printf("不存在!"); return; } q=p->next; //q指向待刪除的節點 p->next=q->next; //刪除節點i,也可寫成p->next=p->next->next free(q); //釋放節點i的內存單元 } void display(NODE *head) { NODE *p; for(p=head->next;p!=NULL;p=p->next) printf("%d ",p->score); printf("\n"); } void pfree(NODE *head) { NODE *p,*q; p=head; while(p->next!=NULL) //每次刪除頭節點的後繼節點 { q=p->next; p->next=q->next; free(q); } free (head); //最後刪除頭節點 } void Pfree(NODE *head) { NODE *p,*q; p=head; while(p->next!=NULL) { q=p->next; p->next=q->next; free(q); } free(p); }
轉自:http://hi.baidu.com/y%C9%D9%B0%D7y/blog/item/fa9f1c5b1525b500367abe80.html
天行健,君子以自強不息。此次做業讓我明白我是有多菜。
優勢:
一、程序員互相幫助,互相教對方,能夠獲得能力上的互補。
二、可讓編程環境有效地貫徹Design。
缺點:
一、兩我的在一塊兒工做可能會出現工做精力不能集中的狀況。程序員可能會交談一些與工做無關的事情,反而分散注意力,致使效率比單人更爲低下。
二、結對編程可能讓程序員們相互學習得更快。有些時候,學習對方的長外,可能會和程序員們在起滋生不良氣氛同樣快。好比,合夥應付工做,敷衍項目。
有時候發現結對編程仍是有點用,結隊編程就是讓咱們知道合做的重要性。