看板 NTUE-CS102 關於我們 聯絡資訊
鳳狼大大前面PO過一篇了 這篇就簡單講 如果是我改的話 我會注意的點 跟我看到的問題好了 --- 第一題 解ax^2+bx+c=0的x 我想應該沒有人用 因式分解 來解題吧 有的話請受小弟一拜 XD 公式解 -b ±√(b^2-4ac) x = -------------------- 2a 這題考的地方有兩個 1. 會不會把數學式子轉成程式 2. 會不會注意負數開根號 除以零 之類的問題 開根號 請看課本6-30頁 ( sqrt 要 #include<cmath> ) 大部分的人都做到 1 了 但是 2 卻沒有注意到 先看一下下面的程式 double a, b, c, d; cout<<"請輸入 a,b,c 程式將解出 ax^2+bx+c=0 的 x :"; cin>>a>>b>>c; d=sqrt(b*b-4.0*a*c); if(b*b-4.0*a*c<0) { cout<<"無實數解"; } else { cout<<"x= " << (-b+d)/(2*a) <<" or "<< (-b-d)/(2*a); } 再看程式2 double a, b, c, d; cout<<"請輸入 a,b,c 程式將解出 ax^2+bx+c=0 的 x :"; cin>>a>>b>>c; d=b*b-4.0*a*c; if(d<0) { cout<<"無實數解"; } else { d=sqrt(d); cout<<"x= " << (-b+d)/(2*a) <<" or "<< (-b-d)/(2*a); } 有看出差異嗎? 在於 sqrt 使用的時機 因為 sqrt 只能開正的 ( 虛數內建的 sqrt 不支援 課本有說 ) 所以 必須在 sqrt 之前 先檢查 再開根號 類似的例子例如 double h, w; cout<<"請輸入身高(公尺) 體重 計算BMI :" cin>>h>>w; cout<<"你的BMI是"<<w/h/h; 要是哪個傢伙他把身高打成0 你就得去跟微軟回報了 比較好的作法是 cin>>h>>w; if(h==0) cout<<"除出來是無限大耶 你一定比神豬還胖"; else cout<<"你的BMI是"<<w/h/h; --- 第二題 字串排序 字典順序: 比較兩字串的第一個字 若有大小差異就是這兩字串的大小差異 若相同 則比較第二個字 以此類推 字的大小怎麼比較? 電腦裡面 每個字都有個代碼 英文的部份叫做 ascii 例如 A=65, B=66, a=96, d=100 所以比較字元的時候 char c1='a', c2='d' if(c1>c2) // 他會自動轉成 96>100 = false 所以字典順序是這樣 char s1[]="june", s2[]="july", s3[]="may", s4[]="may"; 去比較 s1跟s3的話 先比較第一個字 s1是j, s3是m, j<m 所以 s1<s3 比較 s1跟s2的話 第一個字 s1是j s2是j j=j 所以要比較第二個字 第二個字 s1是u s2是u u=u 好衰 還要比第三個 第三個字 s1是n s2是l n<l 所以 s1<s2 這樣字典順序懂了吧~ 但要是兩個字串根本一樣勒 比較 s3跟s4 第一個字 s3=m s4=m 比下一個 第二個字 s3=a s4=a 比下一個 第三個字 s3=y s4=y 比玩了 所以 s3==s4 但是 這題根本不用這樣做= =+ 請看課本 7-19 字典順序只是個幌子 課本 7-19 有提到 C++ 提供的 strcmp 函數的功能 "函式會取兩字串的第一個字元相減, 如果為0則比較下一個字元 直到差不為零便傳回差值" 這不就是上面提到的作法嗎 XD 回來看題目 排序 -> 請回想兩個迴圈的氣泡排序 先看排序數字 int i,j,n,t; int a[1000]; // 最多可存1000個數字 cout<<"有幾個數字?"; cin>>n; for(i=0;i<n;i++) cin>>a[i]; for(i=0;i<n;i++){ for(j=0;j<n-1;j++){ if(a[j]>a[j+1]){ t=a[j]; a[j]=a[j+1]; a[j+1]=t; } } } 換成字串 看結果你就會發現根本是一樣的作法 int i,j,n; char a[1000][100]; // 最多可存1000個名子 每個名子100個空間 char t[100]; // 交換用 cout<<"有幾個名子?"; cin>>n; for(i=0;i<n;i++) cin>>a[i]; for(i=0;i<n;i++){ for(j=0;j<n-1;j++){ if(strcmp(a[j],a[j+1])>0){ strcpy(t,a[j]); strcpy(a[j],a[j+1]); strcpy(a[j+1],t); } } } 請看我標色的地方 概念 作法 都是類似的 只是語法需要因地事宜一下 另外請記得 要 #include<cstring> --- 第三題 求數列 他有兩個變數 如果先遮掉一個 x, 帶數字進去 x=2 1 Σ a[i]*a[1-i] i=0 這樣就會算了吧? int i, s=0; // 算加總 先設0 ( 連乘設1 ) int a[12]; a[0]=1; a[1]=1; for(i=0;i<2;i++) s+=a[i]*a[1-i]; a[2]=s; 然後 把s替換成a[2] int i; int a[12]; a[0]=1; a[1]=1; a[2]=0; for(i=0;i<2;i++) a[2]+=a[i]*a[1-i]; 接下來把 x 拿回來看 現在a裡面有0~11 每個元素都跟a[2]一樣算法 當然你可以 a[2]=0; for(i=0;i<2;i++) a[2]+=a[i]*a[1-i]; a[3]=0; for(i=0;i<3;i++) a[3]+=a[i]*a[2-i]; a[4]=0; for(i=0;i<4;i++) a[4]+=a[i]*a[3-i]; ... 但你有發現嗎 她們都是一樣的程式碼 為什麼不用迴圈呢? int i, x; int a[12]; a[0]=1; a[1]=1; for(x=2;x<12;x++) { a[x]=0; for(i=0;i<x;i++) a[x]+=a[i]*a[x-i-1]; } 一步一步改成這樣 應該了解要怎麼做了吧XD --- 第四題 成績單 輸入跟排序的部份 就不再解釋了 直接切到重複排名的部份 如果分數長這樣 a 50 b 30 c 30 d 70 e 20 那麼排出來 就會變成 1 d 70 2 a 50 3 b 30 3 c 30 5 e 20 我一樣用前面一步一步做的方法 來看怎麼解 首先 如果你已經排好了 你應該會這樣cow for(i=0;i<n;i++) cout<<"第"<<i+1<<"名"<<'\t'<<name[i]<<'\t'<<ch[i] ... // 輸出每科成績 略 這樣排出來會變成 1 d 70 2 a 50 3 b 30 4 c 30 5 e 20 現在引入新的變數 j 計算名次 int j=1; for(i=0;i<n;i++) { cout<<"第"<<j<<"名"<<'\t'<<name[i]<<'\t'<<ch[i] ... // 輸出每科成績 略 j++; } 排出來的結果 ... 1 d 70 2 a 50 3 b 30 4 c 30 5 e 20 嗯 還是一樣 但是如果我動點手腳 int j=1; for(i=0;i<n;i++) { cout<<"第"<<j<<"名"<<'\t'<<name[i]<<'\t'<<ch[i] ... // 輸出每科成績 略 if(sum[i]!=sum[i+1]) j++; } 齁齁 這時候就有不一樣囉 1 d 70 2 a 50 3 b 30 3 c 30 4 e 20 但是這還不是我們想要的 因為重複排名後 e 應該是第五名 請再觀察正確的成績單 1 d 70 2 a 50 3 b 30 3 c 30 5 e 20 有沒有發現 其實 不看重複的部份 排名(j)就等於i+1 所以 再改一下就完成囉 int j=1; for(i=0;i<n;i++) { cout<<"第"<<j<<"名"<<'\t'<<name[i]<<'\t'<<ch[i] ... // 輸出每科成績 略 if(sum[i]!=sum[i+1]) j=i+2; // 因為 i+1 是現在這個人的排名 i+2是下一個人 } 大功告成 --- 大概是這樣 快點動工寫一寫吧 作業建議還是自己寫 交別人的程式 大二還是得拿人家的程式 有問題 可以打下面這支MSN: yantchen@yahoo.com.tw 會有專人幫你看程式碼 但你要先知道你大概bug在哪 或是有bug找不到 我會幫你看程式碼 跟你說的bug要怎麼改 如果你是改好了 請自己測試 看程式碼找bug那個是打分數的時候才要做的事 寒假來囉 大家加油嘿 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 120.127.36.183 ※ 編輯: yantchen 來自: 120.127.36.183 (01/18 01:24) ※ 編輯: yantchen 來自: 120.127.36.183 (01/18 01:41)
pk873:那個MSN是人工智慧機器人 跟OPEN小將一樣 輸入不同的關鍵字 01/18 02:06
pk873:會回答你不同的話喔 揪咪 ^-< ~* 01/18 02:07