導航:首頁 > 源碼編譯 > 用解析式演算法編寫程序代碼

用解析式演算法編寫程序代碼

發布時間:2023-02-11 22:11:04

❶ 用C++函數描述個演算法,並求出時間復雜度

一、什麼是演算法
演算法是一系列解決問題的清晰指令,也就是說,能夠對一定規范的輸入,在有限時間內獲得所要求的輸出。演算法常常含有重復的步驟和一些比較或邏輯判斷。如果一個演算法有缺陷,或不適合於某個問題,執行這個演算法將不會解決這個問題。不同的演算法可能用不同的時間、空間或效率來完成同樣的任務。一個演算法的優劣可以用空間復雜度與時間復雜度來衡量。
演算法的時間復雜度是指演算法需要消耗的時間資源。一般來說,計算機演算法是問題規模n 的函數f(n),演算法執行的時間的增長率與f(n) 的增長率正相關,稱作漸進時間復雜度(Asymptotic Time Complexity)。時間復雜度用「O(數量級)」來表示,稱為「階」。常見的時間復雜度有: O(1)常數階;O(log2n)對數階;O(n)線性階;O(n2)平方階。
演算法的空間復雜度是指演算法需要消耗的空間資源。其計算和表示方法與時間復雜度類似,一般都用復雜度的漸近性來表示。同時間復雜度相比,空間復雜度的分析要簡單得多。

二、演算法設計的方法
1.遞推法
遞推法是利用問題本身所具有的一種遞推關系求問題解的一種方法。設要求問題規模為N的解,當N=1時,解或為已知,或能非常方便地得到解。能採用遞推法構造演算法的問題有重要的遞推性質,即當得到問題規模為i-1的解後,由問題的遞推性質,能從已求得的規模為1,2,…,i-1的一系列解,構造出問題規模為I的解。這樣,程序可從i=0或i=1出發,重復地,由已知至i-1規模的解,通過遞推,獲得規模為i的解,直至得到規模為N的解。
【問題】 階乘計算
問題描述:編寫程序,對給定的n(n≤100),計算並輸出k的階乘k!(k=1,2,…,n)的全部有效數字。
由於要求的整數可能大大超出一般整數的位數,程序用一維數組存儲長整數,存儲長整數數組的每個元素只存儲長整數的一位數字。如有m位成整數N用數組a[ ]存儲:
N=a[m]×10m-1+a[m-1]×10m-2+ … +a[2]×101+a[1]×100
並用a[0]存儲長整數N的位數m,即a[0]=m。按上述約定,數組的每個元素存儲k的階乘k!的一位數字,並從低位到高位依次存於數組的第二個元素、第三個元素……。例如,5!=120,在數組中的存儲形式為:
3 0 2 1 ……
首元素3表示長整數是一個3位數,接著是低位到高位依次是0、2、1,表示成整數120。
計算階乘k!可採用對已求得的階乘(k-1)!連續累加k-1次後求得。例如,已知4!=24,計算5!,可對原來的24累加4次24後得到120。細節見以下程序。
# include <stdio.h>
# include <malloc.h>
......
2.遞歸
遞歸是設計和描述演算法的一種有力的工具,由於它在復雜演算法的描述中被經常採用,為此在進一步介紹其他演算法設計方法之前先討論它。
能採用遞歸描述的演算法通常有這樣的特徵:為求解規模為N的問題,設法將它分解成規模較小的問題,然後從這些小問題的解方便地構造出大問題的解,並且這些規模較小的問題也能採用同樣的分解和綜合方法,分解成規模更小的問題,並從這些更小問題的解構造出規模較大問題的解。特別地,當規模N=1時,能直接得解。
【問題】 編寫計算斐波那契(Fibonacci)數列的第n項函數fib(n)。
斐波那契數列為:0、1、1、2、3、……,即:
fib(0)=0;
fib(1)=1;
fib(n)=fib(n-1)+fib(n-2) (當n>1時)。
寫成遞歸函數有:
int fib(int n)
{ if (n==0) return 0;
if (n==1) return 1;
if (n>1) return fib(n-1)+fib(n-2);
}
遞歸演算法的執行過程分遞推和回歸兩個階段。在遞推階段,把較復雜的問題(規模為n)的求解推到比原問題簡單一些的問題(規模小於n)的求解。例如上例中,求解fib(n),把它推到求解fib(n-1)和fib(n-2)。也就是說,為計算fib(n),必須先計算fib(n-1)和fib(n-2),而計算fib(n-1)和fib(n-2),又必須先計算fib(n-3)和fib(n-4)。依次類推,直至計算fib(1)和fib(0),分別能立即得到結果1和0。在遞推階段,必須要有終止遞歸的情況。例如在函數fib中,當n為1和0的情況。
在回歸階段,當獲得最簡單情況的解後,逐級返回,依次得到稍復雜問題的解,例如得到fib(1)和fib(0)後,返回得到fib(2)的結果,……,在得到了fib(n-1)和fib(n-2)的結果後,返回得到fib(n)的結果。
在編寫遞歸函數時要注意,函數中的局部變數和參數知識局限於當前調用層,當遞推進入「簡單問題」層時,原來層次上的參數和局部變數便被隱蔽起來。在一系列「簡單問題」層,它們各有自己的參數和局部變數。
由於遞歸引起一系列的函數調用,並且可能會有一系列的重復計算,遞歸演算法的執行效率相對較低。當某個遞歸演算法能較方便地轉換成遞推演算法時,通常按遞推演算法編寫程序。例如上例計算斐波那契數列的第n項的函數fib(n)應採用遞推演算法,即從斐波那契數列的前兩項出發,逐次由前兩項計算出下一項,直至計算出要求的第n項。
【問題】 組合問題
問題描述:找出從自然數1、2、……、n中任取r個數的所有組合。例如n=5,r=3的所有組合為: (1)5、4、3 (2)5、4、2 (3)5、4、1
(4)5、3、2 (5)5、3、1 (6)5、2、1
(7)4、3、2 (8)4、3、1 (9)4、2、1
(10)3、2、1
分析所列的10個組合,可以採用這樣的遞歸思想來考慮求組合函數的演算法。設函數為void comb(int m,int k)為找出從自然數1、2、……、m中任取k個數的所有組合。當組合的第一個數字選定時,其後的數字是從餘下的m-1個數中取k-1數的組合。這就將求m個數中取k個數的組合問題轉化成求m-1個數中取k-1個數的組合問題。設函數引入工作數組a[ ]存放求出的組合的數字,約定函數將確定的k個數字組合的第一個數字放在a[k]中,當一個組合求出後,才將a[ ]中的一個組合輸出。第一個數可以是m、m-1、……、k,函數將確定組合的第一個數字放入數組後,有兩種可能的選擇,因還未去頂組合的其餘元素,繼續遞歸去確定;或因已確定了組合的全部元素,輸出這個組合。細節見以下程序中的函數comb。
【程序】
# include <stdio.h>
# define MAXN 100
int a[MAXN];
void comb(int m,int k)
{ int i,j;
for (i=m;i>=k;i--)
{ a[k]=i;
if (k>1)
comb(i-1,k-1);
else
{ for (j=a[0];j>0;j--)
printf(「%4d」,a[j]);
printf(「\n」);
}
}
}

void main()
{ a[0]=3;
comb(5,3);
}
3.回溯法
回溯法也稱為試探法,該方法首先暫時放棄關於問題規模大小的限制,並將問題的候選解按某種順序逐一枚舉和檢驗。當發現當前候選解不可能是解時,就選擇下一個候選解;倘若當前候選解除了還不滿足問題規模要求外,滿足所有其他要求時,繼續擴大當前候選解的規模,並繼續試探。如果當前候選解滿足包括問題規模在內的所有要求時,該候選解就是問題的一個解。在回溯法中,放棄當前候選解,尋找下一個候選解的過程稱為回溯。擴大當前候選解的規模,以繼續試探的過程稱為向前試探。

【問題】 組合問題
問題描述:找出從自然數1,2,…,n中任取r個數的所有組合。
採用回溯法找問題的解,將找到的組合以從小到大順序存於a[0],a[1],…,a[r-1]中,組合的元素滿足以下性質:
(1) a[i+1]>a,後一個數字比前一個大;
(2) a-i<=n-r+1。
按回溯法的思想,找解過程可以敘述如下:
首先放棄組合數個數為r的條件,候選組合從只有一個數字1開始。因該候選解滿足除問題規模之外的全部條件,擴大其規模,並使其滿足上述條件(1),候選組合改為1,2。繼續這一過程,得到候選組合1,2,3。該候選解滿足包括問題規模在內的全部條件,因而是一個解。在該解的基礎上,選下一個候選解,因a[2]上的3調整為4,以及以後調整為5都滿足問題的全部要求,得到解1,2,4和1,2,5。由於對5不能再作調整,就要從a[2]回溯到a[1],這時,a[1]=2,可以調整為3,並向前試探,得到解1,3,4。重復上述向前試探和向後回溯,直至要從a[0]再回溯時,說明已經找完問題的全部解。按上述思想寫成程序如下:
【程序】
# define MAXN 100
int a[MAXN];
void comb(int m,int r)
{ int i,j;
i=0;
a=1;
do {
if (a-i<=m-r+1
{ if (i==r-1)
{ for (j=0;j<r;j++)
printf(「%4d」,a[j]);
printf(「\n」);
}
a++;
continue;
}
else
{ if (i==0)
return;
a[--i]++;
}
} while (1)
}

main()
{ comb(5,3);
}

4.貪婪法
貪婪法是一種不追求最優解,只希望得到較為滿意解的方法。貪婪法一般可以快速得到滿意的解,因為它省去了為找最優解要窮盡所有可能而必須耗費的大量時間。貪婪法常以當前情況為基礎作最優選擇,而不考慮各種可能的整體情況,所以貪婪法不要回溯。
例如平時購物找錢時,為使找回的零錢的硬幣數最少,不考慮找零錢的所有各種發表方案,而是從最大面值的幣種開始,按遞減的順序考慮各幣種,先盡量用大面值的幣種,當不足大面值幣種的金額時才去考慮下一種較小面值的幣種。這就是在使用貪婪法。這種方法在這里總是最優,是因為銀行對其發行的硬幣種類和硬幣面值的巧妙安排。如只有面值分別為1、5和11單位的硬幣,而希望找回總額為15單位的硬幣。按貪婪演算法,應找1個11單位面值的硬幣和4個1單位面值的硬幣,共找回5個硬幣。但最優的解應是3個5單位面值的硬幣。
【問題】 裝箱問題
問題描述:裝箱問題可簡述如下:設有編號為0、1、…、n-1的n種物品,體積分別為v0、v1、…、vn-1。將這n種物品裝到容量都為V的若干箱子里。約定這n種物品的體積均不超過V,即對於0≤i<n,有0<vi≤V。不同的裝箱方案所需要的箱子數目可能不同。裝箱問題要求使裝盡這n種物品的箱子數要少。
若考察將n種物品的集合分劃成n個或小於n個物品的所有子集,最優解就可以找到。但所有可能劃分的總數太大。對適當大的n,找出所有可能的劃分要花費的時間是無法承受的。為此,對裝箱問題採用非常簡單的近似演算法,即貪婪法。該演算法依次將物品放到它第一個能放進去的箱子中,該演算法雖不能保證找到最優解,但還是能找到非常好的解。不失一般性,設n件物品的體積是按從大到小排好序的,即有v0≥v1≥…≥vn-1。如不滿足上述要求,只要先對這n件物品按它們的體積從大到小排序,然後按排序結果對物品重新編號即可。裝箱演算法簡單描述如下:
{ 輸入箱子的容積;
輸入物品種數n;
按體積從大到小順序,輸入各物品的體積;
預置已用箱子鏈為空;
預置已用箱子計數器box_count為0;
for (i=0;i<n;i++)
{ 從已用的第一隻箱子開始順序尋找能放入物品i 的箱子j;
if (已用箱子都不能再放物品i)
{ 另用一個箱子,並將物品i放入該箱子;
box_count++;
}
else
將物品i放入箱子j;
}
}
上述演算法能求出需要的箱子數box_count,並能求出各箱子所裝物品。下面的例子說明該演算法不一定能找到最優解,設有6種物品,它們的體積分別為:60、45、35、20、20和20單位體積,箱子的容積為100個單位體積。按上述演算法計算,需三隻箱子,各箱子所裝物品分別為:第一隻箱子裝物品1、3;第二隻箱子裝物品2、4、5;第三隻箱子裝物品6。而最優解為兩只箱子,分別裝物品1、4、5和2、3、6。
若每隻箱子所裝物品用鏈表來表示,鏈表首結點指針存於一個結構中,結構記錄尚剩餘的空間量和該箱子所裝物品鏈表的首指針。另將全部箱子的信息也構成鏈表。以下是按以上演算法編寫的程序。
}

5.分治法
任何一個可以用計算機求解的問題所需的計算時間都與其規模N有關。問題的規模越小,越容易直接求解,解題所需的計算時間也越少。例如,對於n個元素的排序問題,當n=1時,不需任何計算;n=2時,只要作一次比較即可排好序;n=3時只要作3次比較即可,…。而當n較大時,問題就不那麼容易處理了。要想直接解決一個規模較大的問題,有時是相當困難的。
分治法的設計思想是,將一個難以直接解決的大問題,分割成一些規模較小的相同問題,以便各個擊破,分而治之。
如果原問題可分割成k個子問題(1<k≤n),且這些子問題都可解,並可利用這些子問題的解求出原問題的解,那麼這種分治法就是可行的。由分治法產生的子問題往往是原問題的較小模式,這就為使用遞歸技術提供了方便。在這種情況下,反復應用分治手段,可以使子問題與原問題類型一致而其規模卻不斷縮小,最終使子問題縮小到很容易直接求出其解。這自然導致遞歸過程的產生。分治與遞歸像一對孿生兄弟,經常同時應用在演算法設計之中,並由此產生許多高效演算法。
分治法所能解決的問題一般具有以下幾個特徵:
(1)該問題的規模縮小到一定的程度就可以容易地解決;
(2)該問題可以分解為若干個規模較小的相同問題,即該問題具有最優子結構性質;
(3)利用該問題分解出的子問題的解可以合並為該問題的解;
(4)該問題所分解出的各個子問題是相互獨立的,即子問題之間不包含公共的子子問題。
上述的第一條特徵是絕大多數問題都可以滿足的,因為問題的計算復雜性一般是隨著問題規模的增加而增加;第二條特徵是應用分治法的前提,它也是大多數問題可以滿足的,此特徵反映了遞歸思想的應用;第三條特徵是關鍵,能否利用分治法完全取決於問題是否具有第三條特徵,如果具備了第一條和第二條特徵,而不具備第三條特徵,則可以考慮貪心法或動態規劃法。第四條特徵涉及到分治法的效率,如果各子問題是不獨立的,則分治法要做許多不必要的工作,重復地解公共的子問題,此時雖然可用分治法,但一般用動態規劃法較好。
分治法在每一層遞歸上都有三個步驟:
(1)分解:將原問題分解為若干個規模較小,相互獨立,與原問題形式相同的子問題;
(2)解決:若子問題規模較小而容易被解決則直接解,否則遞歸地解各個子問題;
(3)合並:將各個子問題的解合並為原問題的解。
6.動態規劃法
經常會遇到復雜問題不能簡單地分解成幾個子問題,而會分解出一系列的子問題。簡單地採用把大問題分解成子問題,並綜合子問題的解導出大問題的解的方法,問題求解耗時會按問題規模呈冪級數增加。
為了節約重復求相同子問題的時間,引入一個數組,不管它們是否對最終解有用,把所有子問題的解存於該數組中,這就是動態規劃法所採用的基本方法。以下先用實例說明動態規劃方法的使用。
【問題】 求兩字元序列的最長公共字元子序列
問題描述:字元序列的子序列是指從給定字元序列中隨意地(不一定連續)去掉若干個字元(可能一個也不去掉)後所形成的字元序列。令給定的字元序列X=「x0,x1,…,xm-1」,序列Y=「y0,y1,…,yk-1」是X的子序列,存在X的一個嚴格遞增下標序列<i0,i1,…,ik-1>,使得對所有的j=0,1,…,k-1,有xij=yj。例如,X=「ABCBDAB」,Y=「BCDB」是X的一個子序列。
考慮最長公共子序列問題如何分解成子問題,設A=「a0,a1,…,am-1」,B=「b0,b1,…,bm-1」,並Z=「z0,z1,…,zk-1」為它們的最長公共子序列。不難證明有以下性質:
(1) 如果am-1=bn-1,則zk-1=am-1=bn-1,且「z0,z1,…,zk-2」是「a0,a1,…,am-2」和「b0,b1,…,bn-2」的一個最長公共子序列;
(2) 如果am-1!=bn-1,則若zk-1!=am-1,蘊涵「z0,z1,…,zk-1」是「a0,a1,…,am-2」和「b0,b1,…,bn-1」的一個最長公共子序列;
(3) 如果am-1!=bn-1,則若zk-1!=bn-1,蘊涵「z0,z1,…,zk-1」是「a0,a1,…,am-1」和「b0,b1,…,bn-2」的一個最長公共子序列。
這樣,在找A和B的公共子序列時,如有am-1=bn-1,則進一步解決一個子問題,找「a0,a1,…,am-2」和「b0,b1,…,bm-2」的一個最長公共子序列;如果am-1!=bn-1,則要解決兩個子問題,找出「a0,a1,…,am-2」和「b0,b1,…,bn-1」的一個最長公共子序列和找出「a0,a1,…,am-1」和「b0,b1,…,bn-2」的一個最長公共子序列,再取兩者中較長者作為A和B的最長公共子序列。
代碼如下:
# include <stdio.h>
# include <string.h>
# define N 100
char a[N],b[N],str[N];

int lcs_len(char *a, char *b, int c[ ][ N])
{ int m=strlen(a), n=strlen(b), i,j;
for (i=0;i<=m;i++) c[0]=0;
for (i=0;i<=n;i++) c[0]=0;
for (i=1;i<=m;i++)
for (j=1;j<=m;j++)
if (a[i-1]==b[j-1])
c[j]=c[i-1][j-1]+1;
else if (c[i-1][j]>=c[j-1])
c[j]=c[i-1][j];
else
c[j]=c[j-1];
return c[m][n];
}

char *buile_lcs(char s[ ],char *a, char *b)
{ int k, i=strlen(a), j=strlen(b);
k=lcs_len(a,b,c);
s[k]=』』;
while (k>0)
if (c[j]==c[i-1][j]) i--;
else if (c[j]==c[j-1]) j--;
else { s[--k]=a[i-1];
i--; j--;
}
return s;
}

void main()
{ printf (「Enter two string(<%d)!\n」,N);
scanf(「%s%s」,a,b);
printf(「LCS=%s\n」,build_lcs(str,a,b));
}
7.迭代法
迭代法是用於求方程或方程組近似根的一種常用的演算法設計方法。設方程為f(x)=0,用某種數學方法導出等價的形式x=g(x),然後按以下步驟執行:
(1) 選一個方程的近似根,賦給變數x0;
(2) 將x0的值保存於變數x1,然後計算g(x1),並將結果存於變數x0;
(3) 當x0與x1的差的絕對值還小於指定的精度要求時,重復步驟(2)的計算。
若方程有根,並且用上述方法計算出來的近似根序列收斂,則按上述方法求得的x0就認為是方程的根。上述演算法用C程序的形式表示為:
程序如下:
【演算法】迭代法求方程組的根
{ for (i=0;i<n;i++)
x=初始近似根;
do {
for (i=0;i<n;i++)
y = x;
for (i=0;i<n;i++)
x = gi(X);
for (delta=0.0,i=0;i<n;i++)
if (fabs(y-x)>delta) delta=fabs(y-x); } while (delta>Epsilon);
for (i=0;i<n;i++)
printf(「變數x[%d]的近似根是 %f」,I,x);
printf(「\n」);
} 具體使用迭代法求根時應注意以下兩種可能發生的情況:
(1)如果方程無解,演算法求出的近似根序列就不會收斂,迭代過程會變成死循環,因此在使用迭代演算法前應先考察方程是否有解,並在程序中對迭代的次數給予限制;
(2)方程雖然有解,但迭代公式選擇不當,或迭代的初始近似根選擇不合理,也會導致迭代失敗。
8.窮舉搜索法
窮舉搜索法是對可能是解的眾多候選解按某種順序進行逐一枚舉和檢驗,並從眾找出那些符合要求的候選解作為問題的解。
【問題】 將A、B、C、D、E、F這六個變數排成如圖所示的三角形,這六個變數分別取[1,6]上的整數,且均不相同。求使三角形三條邊上的變數之和相等的全部解。如圖就是一個解。
程序引入變數a、b、c、d、e、f,並讓它們分別順序取1至6的整數,在它們互不相同的條件下,測試由它們排成的如圖所示的三角形三條邊上的變數之和是否相等,如相等即為一種滿足要求的排列,把它們輸出。當這些變數取盡所有的組合後,程序就可得到全部可能的解。程序如下:
按窮舉法編寫的程序通常不能適應變化的情況。如問題改成有9個變數排成三角形,每條邊有4個變數的情況,程序的循環重數就要相應改變。

❷ 求按照一個演算法寫一個C語言程序

/*
你提供的那個代碼是偽代碼,我幫你寫成了
C
的代碼。
你提供的偽代碼,我用注釋寫到了對應的行的後面。
根據你提供的代碼還只能轉換含有一個字母或
[0,9]
區間內的數字的解析式。
補充了一點棧的基本演算法
執行後輸出:
原式子(中綴表達式):
a+b*c
新式子(後綴表達式):
a
b
c
*
+
代碼使用
linux
+
GCC
3.4.5
編譯通過
July.28th,2009
14:30pm.
main()
在最下邊
*/
#include
struct
_stack
{
char
__stack[1024];
int
__top;
};
//
模擬棧
inline
init_stack(
struct
_stack
*
p_stack
)
//
初始化棧
{
int
i
=
0;
for(
i
=
0;
i
<=
1024;
i++
)
p_stack->__stack[i]
=
'\0';
p_stack->__top
=
0;
}
inline
void
push(
struct
_stack
*
p_stack,
char
p_op
)
//
進棧
{
p_stack->__stack[p_stack->__top]
=
p_op;
(
p_stack->__top
)++;
}
inline
char
pop(
struct
_stack
*
p_stack
)
//
出棧
{
(
p_stack->__top
)--;
return
p_stack->__stack[p_stack->__top];
}
inline
int
precedence(
char
p_char
)
//
比較優先順序
{
if(
p_char
==
'+'
||
p_char
==
'-'
)
return
1;
else
if(
p_char
==
'/'
||
p_char
==
'*'
)
return
2;
else
return
0;
}
char
postString[1024];
char
*
infix_to_postfix(
char
*inString
)
{
int
l
=
strlen(
inString
);
struct
_stack
stack;
char
p
=
'\0';
int
i
=
0;
char
c
=
'\0';
l
=
strlen(
inString
);
//
l
<-
Length
of
inString
for(
i
=
0;
i
<=
1024;
i++
)
postString[i]
=
'\0';
//
postString
<-
empty
string
init_stack(
&stack
);
//
stack
<-
Empty
stack
for(
i
=
0;
i
<=
l;
i++
)
//
for
i
<-
0
to
l
{
c
=
inString[i];
//
c
<-
inString[i]
if(
(
c
>=
'0'
&&
c
<=
'9'
)||(
c
>=
'a'
&&
c
<=
'z'
)||(
c
>=
'A'
&&
c
<=
'Z'
)
)
//
if
c
is
an
operand
{
if(
postString[0]
==
'\0'
){postString[0]
=
c;continue;}
sprintf(
postString,
"%s
%c",
postString,
c
);
//
add
c
at
the
end
of
postString
}//
end
if
if(
c
==
'+'
||
c
==
'-'
||
c
==
'*'
||
c
==
'/'
)
//
if
c
is
an
operator
{
if(
stack.__top==0
||
precedence(
stack.__stack
[stack.__top]
)<
precedence(
c
)
)
//
if
stack
is
empty
OR
if
precedence(
stack_top
)<
precedence(
c
)
{
push(
&stack,
c
);
//
push
c
into
stack
}
else
{
while(
precedence(
stack.__stack
[stack.__top]
)>=
precedence(
c
)
)
//
while
precedence(
stack_top
)>=
precedence(
c
)
{
p
=
pop(
&stack
);
//
p
<-
pop
from
stack
sprintf(
postString,
"%s
%c",
postString,
p
);
//
add
p
at
the
end
of
postString
}
//
end
while
push(
&stack,
c
);
//
push
c
into
stack
}
//
end
if
}
//
end
if
}
//
end
for
while(
stack.__top
)
//
while
stack
is
not
empty
{
p
=
pop(
&stack
);
//
p
<-
pop
from
stack
sprintf(
postString,
"%s
%c",
postString,
p
);
//
add
p
at
the
end
of
postString
}
//
end
while
return
postString;
}
int
main(
)
{
char
exp[]
=
"a+b*c";
char
*
p
=
0;
p
=
infix_to_postfix(
exp
);
printf(
"原式子(中綴表達式):\n\t%s\n新式子(後綴表達式):\n\t%s\n",
exp,
p
);
return
0;
}

❸ 從編程技術角度解析代碼 什麼意思

編程技術角度解析代碼,我的理解是模塊功能的實現,有比較詳細的註解,重點突出採用了什麼獨特的演算法,或者有什麼獨特個性特點,

❹ 急求 程序代碼 c/c++ 操作系統中的 處理機調度演算法

#include <iostream>

#include <stdio.h>

#include <string>

//#include <windows.h>

using namespace std;

//hyugtyftydrtdtrdrrtrdrt

struct Node

{

string name;//進程(作業)名稱

int arriveTime;//到達時間

int ServerTime;//服務時間

int leftTime;//the left time

Node *link;//指向下一個節點的指針

};

class CProcess

{

public:

CProcess();//構造函數

~CProcess();//析構函數

const CProcess &operator =(const CProcess& p);//重載賦值操作符

void insertNode(string &na,int& at,int& st);//插入新元素(at由小到大)到鏈表合適的位置

void sort();//按照服務時間由大到小排序

bool isEmpty();//判斷是否為空

void destroy();//銷毀

int length();//求出鏈表長度

void print();//列印出元素

void FCFS();//先到先服務

void SJF();//短進程(作業)優先

void RR(int& q);//時間片輪轉

void priority();//優先權調度

protected:

Node *first;

Node *last;

};

const CProcess& CProcess::operator=(const CProcess& p)

{

Node *newNode;

Node *Current;

if(this!=&p)//避免自己給自己賦值

{

if(first!=NULL)//如果鏈表不為空

destroy();

if(p.first==NULL)

{//如果要拷貝的對象為空

this->first = NULL;

this->last = NULL;

}

else

{

Current = p.first;

first= new Node;

first->name=Current->name;//

first->arriveTime=Current->arriveTime;

first->ServerTime=Current->ServerTime;

first->link =NULL;

last =first;

Current = Current->link;

while(Current!=NULL)

{

newNode = new Node;

newNode->name=Current->name;

newNode->arriveTime=Current->arriveTime;

newNode->ServerTime=Current->ServerTime;

newNode->link=NULL;

last->link=newNode;

last=newNode;

Current = Current->link;

}

}

}

return *this;

}

CProcess::CProcess()

{//構造函數

first=NULL;

last=NULL;

}

CProcess::~CProcess()

{

Node *temp;

while(first!=NULL)

{

temp=first;

first=first->link;

delete temp;

}

last=NULL;

}

void CProcess::insertNode(string &na,int& at,int& st)

{//按照到達時間升序排序

Node *Current;

Node *trailCurrent;//指向Current的前一個節點

Node *newNode;

bool found;

newNode = new Node;//建立一個新節點

newNode->name=na;

newNode->arriveTime=at;

newNode->ServerTime=st;

newNode->link=NULL;//

if(first==NULL)//如果第一個節點為空(如果是第一次插入元素)

first=newNode;//將新節點賦給第一個節點

else

{//如果不是第一次

Current =first;

found = false;

while(Current!=NULL && !found)

{

if(Current->arriveTime >= at)

found = true;

else

{

trailCurrent = Current;

Current = Current->link;

}

}

if(Current==first)

{

newNode->link = first;

first = newNode;

}

else

{

trailCurrent->link = newNode;

newNode->link = Current;

}

}

}

int CProcess::length()

{

int count =0;//聲明變數,並初始化為0(用來記錄長度)

Node *Current;

Current = first;

while(Current!=NULL)//當前節點不為空,記錄值自加,一直向後遍歷,

{

count++;

Current = Current->link;

}

return count;//返回長度

}

void CProcess::sort()//按照服務時間,升序排列

{//冒泡排序

string sname;

int at;

int st;

Node *Current;//指向當前節點

Node *trailCurrent;//指向當前節點的前一個節點

for(trailCurrent=first->link;trailCurrent!=NULL;trailCurrent=trailCurrent->link)//控制條件有問題

{

for(Current=trailCurrent->link;Current!=NULL;Current=Current->link)//控制條件有問題

{

if(trailCurrent->ServerTime > Current->ServerTime)

{

sname=trailCurrent->name;

at=trailCurrent->arriveTime;

st=trailCurrent->ServerTime;

trailCurrent->name=Current->name;

trailCurrent->arriveTime=Current->arriveTime;

trailCurrent->ServerTime=Current->ServerTime;

Current->name=sname;

Current->arriveTime=at;

Current->ServerTime=st;

}

}

}

}

bool CProcess::isEmpty()//判斷是否為空

{

return (first==NULL);//如果第一個節點為空,返回值

}

void CProcess::print()

{

Node *Current;

Current = first->link;//頭節點賦給當前節點

while(Current!=NULL)//當前節點不為空,一直向後遍歷列印

{

cout<<Current->name<<" ";

cout<<Current->arriveTime<<" ";

cout<<Current->ServerTime<<"\n";

Current = Current->link;

}

}

void CProcess::destroy()

{

Node *temp;//定義一個臨時指針變數

while(first!=NULL)

{

temp=first;

first=first->link;

delete temp;

}

last=NULL;

}

void CProcess::FCFS()//先到先服務

{

Node *Current;

int T0=0;//完成時間

int T1=0;//周轉時間

Current = first->link;//頭節點賦給當前節點

while(Current!=NULL)

{

if(T0 < Current->arriveTime)

{

T0=Current->arriveTime+Current->ServerTime;

T1=T0-Current->arriveTime;

cout<<Current->name<<"\t";//列印出進程名

cout<<T0<<"\t";//列印出完成時間

cout<<T1<<"\n";//列印出周轉時間

Current = Current->link;

}

else

{

T0=Current->ServerTime+T0;

T1=T0-Current->arriveTime;//周轉時間等於,完成時間 - 到達時間

cout<<Current->name<<"\t";//列印出進程名

cout<<T0<<"\t";//列印出完成時間

cout<<T1<<"\n";//列印出周轉時間

Current = Current->link;

}

}

}

void CProcess::SJF()//短進程(作業)優先

{

//首先執行第一個到達的作業

Node *Current;

int T0=0;//完成時間

int T1=0;//周轉時間

T0=first->link->ServerTime+T0;

T1=T0-first->link->arriveTime;

cout<<first->link->name<<"\t";

cout<<T0<<"\t";//列印出完成時間

cout<<T1<<"\n";//列印出周轉時間

first->link=first->link->link;//刪除

//執行剩下的

sort();//對剩下的排序

Current = first->link;//頭節點賦給當前節點

while(Current!=NULL)

{

if(T0 < Current->arriveTime)

{

T0=Current->arriveTime+Current->ServerTime;

T1=T0-Current->arriveTime;

cout<<Current->name<<"\t";//列印出進程名

cout<<T0<<"\t";//列印出完成時間

cout<<T1<<"\n";//列印出周轉時間

Current = Current->link;

}

else

{

T0=Current->ServerTime+T0;

T1=T0-Current->arriveTime;//周轉時間等於,完成時間 - 到達時間

cout<<Current->name<<"\t";//列印出進程名

cout<<T0<<"\t";//列印出完成時間

cout<<T1<<"\n";//列印出周轉時間

Current = Current->link;

}

}

}

void CProcess::RR(int& q)//時間片輪轉

{

cout<<"時間片輪轉操作完成!\n";

}

void CProcess::priority()//優先權調度

{

cout<<"優先權操作完成!\n";

}

void main()

{

CProcess p0,p1,p2,p3,p4;

int at,st;

string na;

int judge=1;//控制退出程序

int choice;//控制選擇操作

while(judge)

{

cout<<"********************************************************\n";

cout<<"****** 說明:本程序適用於單道進程(作業) ******\n";

cout<<"******** 請選擇您的操作 ***************\n";

cout<<"*********輸入相應的數字,按下(Enter)鍵!**************\n";

cout<<"************* 5.錄入信息 ************\n";

cout<<"************* 1.先到先服務 ************\n";

cout<<"************* 2.短進程(作業)優先 ************\n";

cout<<"************* 3.時間片輪轉 ************\n";

cout<<"************* 4.優先權(靜態)調度 ************\n";

cout<<"************* 0.退出程序 ************\n";

cout<<"********************************************************\n";

cin>>choice;

switch(choice)

{

case 0:

judge=0;

break;

case 5:

cout<<"請輸入信息以「end」結束輸入!\n";

cout<<"進程名 到達時間 服務時間"<<endl;

while(na.compare("end"))//如果相等則會返回0

{

p0.insertNode(na,at,st);

cin>>na>>at>>st;

}

cout<<"錄入成功,目前的信息為:\n";

cout<<"進程名 到達時間 服務時間"<<endl;

p0.print();

break;

case 1://先到先服務

p1=p0;//拷貝一份

if(p1.isEmpty())

{

cout<<"請先錄入信息\n";

break;

}

else

{

cout<<"先到先服務\n";

cout<<"進程名 完成時間 周轉時間\n";

p1.FCFS();

break;

}

case 2://短作業優先

p2=p0;//拷貝一份

//p2.sort();

//p2.print();

if(p2.isEmpty())

{

cout<<"請先錄入信息\n";

break;

}

else

{

cout<<"短作業優先\n";

cout<<"進程名 完成時間 周轉時間\n";

p2.SJF();

break;

}

case 3://時間片輪轉

p3=p0;//拷貝一份

int q;

if(p3.isEmpty())

{

cout<<"請先錄入信息\n";

break;

}

else

{

cout<<"請輸入時間片大小";

cin>>q;

cout<<"時間片輪轉\n";

cout<<"進程名 完成時間 周轉時間\n";

p3.RR(q);

break;

}

case 4://優先權

p4=p0;//拷貝一份

if(p4.isEmpty())

{

cout<<"請先錄入信息\n";

break;

}

else

{

cout<<"時間片輪轉\n";

cout<<"進程名 完成時間 周轉時間\n";

p4.priority();

break;

}

default:

cout<<"請選擇目錄中的選項!\n";

break;

}

}

return;

}

❺ 怎樣把一個演算法變成程序

怎樣把一個演算法變成程序

演算法的意義,你網路搜索網路,然後再看我下面的回答:

一個合格的演算法,相當於能通過特定設置生成特定的結果的一段小程序,

通常在編程的時候,我們會這樣做:例如以個加法運算,並顯示結果
製作程序界面,提供2個輸入控制項(假定名稱為A和B)用於輸入數字,1個標簽控制項(假定名稱為C)用於顯示結果!
1個按鈕控制項用於當使用者點擊按鈕時執行 C=加法函數(A,B)
然後在程序中編寫一個加法函數,並制定需提供2個數值型參數,以及提供返回值!
細節略過...
通過這樣設計,就實現了將演算法或者說是函數,運用於能與用戶交互的程序上了!
這就是我們編程的基礎出發點!然而在實際應用中,演算法往往會更為復雜多變!

那麼通過上面的舉例,再來一段簡單點的解答:
將 函數,與界面進行有機結合,就變成了程序!

由於你的提問也許很復雜,那麼我就再復雜點去理解來回答:
也許你在某書本上看到一段演算法,你想把其變成能應用於程序上!又不知道如何著手!

那麼,我建議你要實現為可交互的程序,就需要學會編程,
其次就是你能看懂這段演算法,並把其改寫為程序代碼!
總結這個可能性的疑問,就是需要會編程,看得懂演算法的意思和步驟!

***********回答完畢啦,手工的,希望對你有幫助,有疑問繼續追問吧!
***********如果說我的回答不是你想了解的,那麼還請你詳細描述相關的問題吧!
***********採納答案別忘記點贊同!謝謝,祝您生活愉快!

❻ 高分求解一個VB題,VB程序如下,請在劃線處填入合適代碼,要解析,答案我有,主要要解析

s=text1.text
r=r-1
s=mid(s,p+1)

❼ C語言求助~

(一)「項目驅動」式教學
目前最著名、最有影響、應用最廣泛的windows、linux和UNIX三個操作系統都是用C語言編寫的。0S是計算機系統(由軟硬體兩個子系統構成)的核心和靈魂,它是軟體中最龐大最復雜的系統軟體。既然如此龐大復雜的0S都可以用c語言編寫,從狹義而言,還有什麼系統軟體和應用軟體不能用c語言編寫呢?由此可以肯定的說,c語言是一門十分優秀而又重要的語言。
c語言程序設計是過程性程序設計語言,它的發展貫穿了計算機發展的歷程,它蘊含了程序設計的基本思想,囊括了程序設計的基本概念,所以它是理工科高等院校的一門基礎課程。
從市面上有關c語言的書籍和高等院校採用的教材來看,它們有一個共性,那就是:脫離了實際應用(全是小打小鬧的小例子),純粹的過程性程序設計,沒有軟體工程思想的體現,沒有一定程序設計風格,僅僅是為了讓大家明白什麼是c語言而已。
高等院校開設c語言程序設計的目的是讓學生對程序設計有個入門,有個直觀的理解,同時為其他後續課程作鋪墊。但是如果教學僅僅以此為目的,那麼教學本身就效果而言是個大大的失敗。
大家知道,在商業上講究唯利是圖,「利」是商業追求的目標,離開了「利」經商,則商無動力,其結果是必敗無疑。在c語言程序設計教學當中,教師應該把「唯用是圖」作為教學的首要目標。如果拋開了實際應用進行程序設計教學,就是紙上談兵,就是「說明書」式的教學。印度的程序設計課程採用「事件驅動式

教學,我認為在中國的c語言程序設計教學中應該採用「項目驅動式」教學。「項目驅動式」教學就是以項目為目的,以c語言理論教學為過程,最終能用c語言設計項目,實現項目的要求。「項目驅動式」教學的關鍵在於培養學生「如何做什麼」和「可以干什麼」。一個項目就是一個工程,在「項目驅動式」教學中,首先應該讓學生簡單了解什麼是軟體工程思想,其次在c語言理論教學過程中,讓學生懂得面向對象的程序設計的風格,最後引導他們來設計項目。
(二)「項目驅動」式教學應注意的問題
1.c語言程序設計教學要幫助學生樹立面向工程的觀點
在計算機行業中,軟體是通過人們的智力活動、把知識與技術轉化成信息的一種產品。軟體的設計已經用工程的觀念來進行管理。軟體設計工作被當作一項系統工程來對待。軟體的的生存周期一般可分為以下階段:問題定義、可行性研究、需求分析、概要設計、詳細設計、編碼、測試、運行與維護。我們不難看出軟體工程的復雜程度是很大的。理工科高等院校把c語言作為一門基礎課程,也是為了給社會培養信息技術人才。眾所周知,養成一個好的習慣是非常重要的,所以c語言程序設計作為大多數工科院校學生接觸的第一門程序設計語言(有的院校講pascal),就應該讓學生樹立正確的觀點。那麼當前的程序設計教學也必須以切合將來軟體工程開發的實際需要為第一目標,使學生在學習程序設計的初級階段就樹立正確的軟體工程觀點。這樣做不僅可以為學生將來從事計算機應用設計打下良好的基礎,而且有利於培養學生分析問題的完備性,以及統籌全局,協調關系的基本素質。
2.理論教學應從單一的「結構化程序設計」向「結構化與面向對象並舉」轉變
「結構化程序設計」方法是程序設計的基礎,必須讓學生掌握得堅實可靠。結構化程序設計的過程是培養學生思維能力的過程,在教學中經常發現有些學生的思維混亂。這些都是缺乏思維訓練的結果。結構化程序設計的訓練不僅可以讓學生養成良好的程序設計習慣,而且可以有效地培養學生思維的條理性和邏輯性。所以在授課過程中要注意講解結構化程序設計的思想時應突出兩點:(1)程序的質量首先取決於它的結構。(2)程序設計的基本方法是自頂向下地逐步求精和模塊化。
在c程序教學過程中,越到後面的章節,學生越會產生設計程序逐漸變難的感覺,這是不符合邏輯的一種怪現象。按照常理,C語言學的越多,說明你的程序設計知識越多,設計起程序來應該更加得心應手,那麼出現這種現象的原因何在呢?當然該問題的出現的原因是多方面的,但是其中最重要的一點就是長期以來程序設計的觀念不是以如何處理好對象為出發點,而是以如何使用好語言為基本點。受這種思想的影響,我們的程序設計教學大多數不是以如何解決好問題為重點,而是以講解語法規則和語句格式為重點,是「說明書」式的教學。這樣做造成的結果就是見到一個程序後學生首先想到是該用哪條語句,而不是思考怎樣合理的解析。要切實解決這個問題,首先應該改變程序設計的觀念。「面向對象程序設計」思想是目前最為流行、極為實用的一種程序設計方法,但是讓學生直接接觸「面向對象程序設計」,肯定不能對程序設計打下牢固的基礎。「結構化與面向對象並舉」是現代計算機程序設計的發展趨勢,應該認真探索研究,讓學生有一個較為輕松的學習過程。程序設計的實質就是編寫處理對象的過程,所以將c與c++有機的融為一體的教材應該是首選教材,在教學過程中,我們應該從社會發展的角度進行探索研究,將目前最為流行又極為實用「面向對象程序設計」思想融合到c語言教學中。
3.c語言教學應培養學生良好的程序設計風格
具有良好的設計風格應該是程序員所具備的基本素質,在實際的項目中程序員往往都有自己的一些編程風格。目前95%以上的程序設計書籍不注重程序設計風格問題,這導致了很多學生沒有良好的程序設計風格,在他們剛剛畢業踏入社會時,如果周圍的同事沒有良好的編程風格,那麼很難通過環境來使自己提高這方面的素質,即使有提高也不容易比較全面的提高。因此在學生接觸的第一門程序設計語言教學中,就應該培養學生良好的程序設計風格,使他們一進工作環境就具備這個素質。
Pascal設計者N.Writh教授十分重視程序設計風格的養成,他堅信「教給學生們以表達他們思維的語言會深深地影響他們思維和創造發明的習慣,而正是這些語言本身的混亂直接影響著學生們的程序設計的風格」,他這里所指的「這些運用」是當時那些主要用於程序設計教學的計算機語言。對學生來講,一開始就強調程序設計風格很有必要,良好的程序設計風格不僅有助於提高程序的可靠性、可理解性、可測試性、可維護性和可重用性,而且也能夠促進技術的交流,改善軟體的質量。所以培養良好的程序設計風格對於初學者來說非常重要。
程序設計風格,實際上是指的是編碼風格。在教學過程中應從源程序文檔化,數據說明的原則,輸入/輸出方法這三個方面培養學生的編碼風格,進而從編碼原則探討提高程序的可讀性、改善程序質量的方法。
(1)源程序文檔化。編碼的目的是產生程序,但是為了提高程序的可維護性。源代碼是需要實現文檔化的。源程序文檔化包括選擇標識符(變數和標號)的名字、安排注釋以及標準的書寫格式等。
①選擇標識符的命名規則。標識符包括模塊名、變數名、常量名、標號名、子程序名等。這些名字應能反映它所代表的實際東西,應有一定實際意義,使其能顧名思義。另外在模塊名、變數名、常量名、標號名、子程序名中使用下劃線是一種風格。使用這一技術的一種廣為人知的命名規則就是匈牙利命名法(變數類型由一個或兩個字元表示,並且這些字元將作為變數名的前綴)。當然使用匈牙利命名法與否都沒有錯誤,重要的是要保持一致性——在整個程序中使用相同的命名規則。這就是說,如果你在一個小組環境中編程,你和其他小組成員應該制定一種命名規則。並自始至終使用這種規則。如果有人使用了別的命名規則,那麼集成的程序讀起來將是很費勁的。此外,你還要與程序中用到的第三方庫(如果有的話)所使用的風格保持一致。如果可能的話,你應該盡量使用與第三方庫相同的命名規則,這將加強你的程序的可讀性和一致性。
②注釋。程序中的注釋是程序設計者與程序閱讀者之間通信的重要手段。注釋能夠幫助讀者理解程序,並為後續測試維護提供明確的指導信息。因此,注釋是十分重要的,大多數程序設計語言提供了使用自然語言來寫注釋的環境,為程序閱讀者帶來很大的方便。注釋分為功能性注釋和序言性注釋。
a.功能性注釋。功能性注釋在源程序中,用以描述其後的語句或程序段是在做什麼工作,也就是解釋下面要「做什麼」,而不是解釋下面怎麼做。對於書寫功能性注釋,要注意以下幾點:第一描述一段程序,而不是每一個語句。第二利用縮進和空行,使程序與注釋容易區別。第三注釋要准確無誤。
b.序言性注釋。序言性注釋通常位於每個程序模塊的開頭部分,它給出程序的整體說明,對於理解程序具有引導作用。有些軟體開發部門對序言性注釋做了明確而嚴格的規定,要求程序編制者逐項列出。有關內容包括:程序標題;有關該模塊功能和目的的說明;主要演算法;介面說明:包括調用形式,參數描述,子程序清單;有關數據描述;模塊位置(在哪一個源文件中,或隸屬於哪一個軟體包);開發簡歷:模塊設計者、復審考、復審日期。
③用標準的書寫格式。源程序清單的書寫建議採用以下幾點:
a.每行只寫一條語句;
b.用分層縮進的寫法顯示嵌套結構層次,這樣可使程序的邏輯結構更加清晰,層次更加分明。
c.書寫表達式時適當使用空格或圓括弧作隔離符。
d.在注釋段周圍加上邊框;
e.注釋段與程序段、以及不同的程序段之間插入字行;
(2)數據說明採用的原則。在編寫程序時,要注意數據說明的風格。
數據說明的次序如果規范,將有利於測試,排錯和維護。首先說明的先後次序要固定,例如,按常量說明、簡單變數類型說明、數組說明用數據塊說明、所有的文件說明的順序說明。當然在類型說明中還可進一步要求,例如按如下順序排列:整型量說明、實型量說明、字元量說明、邏輯說明。
其次當用一個語句說明多個變數名時,應當對這些變數按字母的順序排列。
最後對於復雜數據結構,應利用注釋說明實現這個數據結構的特點。
(3)輸入/輸出方法。輸入/輸出的方式和格式應當盡量避免因設計不當給用戶帶來的麻煩。這就要求,源程序的輸入/輸出風格必須滿足能否為用戶接受這一原則。所以在設計程序時,應考慮以下原則:輸入數據時,要使輸入的步驟和操作盡可能簡單,應允許使用自由格式輸入;應允許預設值;對輸入的數據要進行檢驗,以保證每個數據的有效性。
(三)結束語
在教學過程中,我們讓學生設計一個程序模擬體育彩票的銷售與對獎的過程,取得了良好的效果。他不僅啟發和誘導了學生獨立思考、積極思維的主動性,而且充分調動了學生學習的自覺性和積極性,使學生融會貫通地掌握了所學知識,提高了分析問題和解決實際問題的能力。
搞好c程序設計的教學工作涉及的因素很多,如果以項目來驅動教學,首先讓學生樹立面向工程的思想,其次把教學從單一的「結構化程序設計」向「結構化與面向對象並舉」轉變,最後特別要培養學生養成良好的編碼風格,從而使他們學會能夠「干什麼」,那麼我們認為教學目的就達到了。

❽ c語言一點不懂,編程時也不知道怎麼寫

怎樣才能學好C語言

1、學好C語言,你可以很好地應付任何一種編程工具。

2、一定要多上機練習,通過程式了解相關知識。幾經反復方得正果。

3、不要把學習C語言當成一種任務,更不要把它看成很難完成的任務。要充滿自信,只要是一個智力正常的人都能學好C語言。始終保持游戲的心態,多發現其中的樂趣。當感到編程趣味無窮,那你在電腦方面將前程無量。

4、如果一個程式一時無法弄清楚最後暫時放在一邊,過一段時間你可能會從其他的程式中悟出道理。

5、C語言是一個整體,各個方面是有機聯系的,要從總體上把握它,不要把它割裂成互不關聯的部件。

6、不要完全相信教材(包括本講義),所有結論最好都上機驗證。
怎樣學好C語言

1. 工欲善其事,必先利其器

准備工作:一個開發環境,如Turbo C 2.0、Visual C++等開發工具;一本好教材,如譚浩強主編的《C語言程序設計》(第二版)。我當時看的是他的第一版,就為它的簡潔、完美所吸引,簡直愛不釋手,用了兩個星期一口氣看完。

2. 秘密武器

初學者學習計算機語言要會「讀程序」,要對小型的應用型、游戲型程序感興趣,並模仿去加深對C語言程序設計的理解和操作,只有不斷地寫程序、調試程序才能得到編寫程序的經驗和加深對程序的理解,這也是學習編寫優秀高級程序的秘密武器。

3. 發揚探索精神

學習C語言程序設計有點像做數學難題,只要我們善於思考,善於探索,發揚探索精神去尋找好的設計思想和方法,才能把C語言的精髓真正地掌握。

備戰C語言考試要訣

1. 了解大綱,臨陣不亂

各類筆試中,大多數考題是與大綱要求的基本內容一致的,難度不高,但內容十分廣泛,應牢固掌握C語言考試大綱要求的基礎部分。只有熟悉題型,理解語法、句法,做到心中有數,才能臨陣不亂。

2. 善於歸納,強化記憶

對於需要記憶的計算機基礎知識和基本概念,如果考試時因此失分就十分可惜。如:C語言中有幾種不同的數據類型?運算的優先順序別是怎樣的?因此我們需要善於歸納這些計算機基礎知識,並在理解的基礎上強化記憶。

3. 重視實踐,善於調試

計算機科學是一門理論性、實踐性都很強的學科,對C語言考試的參加者來說,基礎理論方面要求不高,而上機試題往往是很多考生不能通過考試的重要原因,因此要勤於實踐。

4. 多做練習,查漏補缺

在認真地學完指定用書後,最好再找些試題,認真地測試一下,一則可以檢查自己的復習情況;二則可以查漏補缺;三則可以調節心理狀況,以備正式考試時沉著冷靜、萬無一失。

===================

C程序設計》的內容很豐富,按照我們現在的教學大綱,教學的主要內容是基礎知識、四種結構的的程序設計、函數與數組的應用和一些簡單的演算法。在學習時,同學們應該把主要精力放在這些部分,通過實踐(練習和上機調試等熟練掌握。當然,在初學C語言時,可能會遇到有些問題理解不透,或者表達方式與以往數學學習中不同(如運算符等),這就要求不氣餒,不明白的地方多問多想,鼓足勇氣進行學習,待學完後面的章節知識,前面的問題也就迎刃而解了,這一方面我感覺是我們同學最欠缺,大多學不好的就是因為一開始遇到困難就放棄,曾經和好多同學談他的問題,回答是聽不懂、不想聽、放棄這樣三個過程,我反問,這節課你聽過課嗎?回答又是沒有,根本就沒聽過課,怎麼說自己聽不懂呢?相應的根本就沒學習,又談何學的好?
學習C語言始終要記住「曙光在前頭」和「千金難買回頭看」,「千金難買回頭看」是學習知識的重要方法,就是說,學習後面的知識,不要忘了回頭弄清遺留下的問題和加深理解前面的知識,這是我們學生最不易做到的,然而卻又是最重要的。比如:在C語言中最典型的是關於結構化程序設計構思,不管是那種教材,一開始就強調這種方法,這時也許你不能充分體會,但是學到函數時,再回頭來仔細體會,溫故知新,理解它就沒有那麼難了。學習C語言就是要經過幾個反復,才能前後貫穿,積累應該掌握的C知識。
那麼,我們如何學好《C程序設計》呢?
一.學好C語言的運算符和運算順序
這是學好《C程序設計》的基礎,C語言的運算非常靈活,功能十分豐富,運算種類遠多於其它程序設計語言。在表達式方面較其它程序語言更為簡潔,如自加、自減、逗號運算和三目運算使表達式更為簡單,但初學者往往會覺的這種表達式難讀,關鍵原因就是對運算符和運算順序理解不透不全。當多種不同運算組成一個運算表達式,即一個運算式中出現多種運算符時,運算的優先順序和結合規則顯得十分重要。在學習中,只要我們對此合理進行分類,找出它們與我們在數學中所學到運算之間的不同點之後,記住這些運算也就不困難了,有些運算符在理解後更會牢記心中,將來用起來得心應手,而有些可暫時放棄不記,等用到時再記不遲。
先要明確運算符按優先順序不同分類,《C程序設計》運算符可分為15種優先順序,從高到低,優先順序為1 ~ 15,除第2、3級和第14級為從右至左結合外,其它都是從左至右結合,它決定同級運算符的運算順序。下面我們通過幾個例子來說明:
(1) 5*8/4%10 這個表達式中出現3種運算符,是同級運算符,運算順序按從左至右結合,因此先計算5 *8=40,然後被4除,結果為10,最後是%(求余數)運算,所以表達式的最終結果為10%10 = 0;
(2)a = 3;b = 5;c =++ a* b ;d =a + +* b;
對於c=++a*b來說,按表中所列順序,+ +先執行,*後執行,所以+ + a執行後,a的值為4,由於+ +為前置運算,所以a的值4參與運算,C的值計算式為4*5=20而不是3*5=15了;而對於d=a++*b來說,由於a + +為後置運算,所以a值為4參與運算,使得d的值仍為20,而a參與運算後其值加1,值為5。 這個例子執行後,a的值為5,b的值為5,c的值為20,d的值也是20;
(3)(a = 3,b = 5,b+ = a,c = b* 5)
例子中的「,」是逗號結合運算,上式稱為逗號表達式,自左向右結合,最後一個表達式的結果值就是逗號表達式的結果,所以上面的逗號表達式結果為40,a的值為3,b的值為8,c的值為40。
(4)a=5;b=6;c=a>b?a:b;
例中的a>b?a:b是一個三目運算,它的功能是先做關系運算a>b部分,若結果為真,則取問號後a的值,否則取冒號後b的值,因此c的值應該為6,這個運算可以用來代替if…else…語句的簡單應用。

二.學好C語言的四種程序結構
(1)順序結構
順序結構的程序設計是最簡單的,只要按照解決問題的順序寫出相應的語句就行,它的執行順序是自上而下,依次執行。
例如;a = 3,b = 5,現交換a,b的值,這個問題就好象交換兩個杯子水,這當然要用到第三個杯子,假如第三個杯子是c,那麼正確的程序為: c = a; a = b; b = c; 執行結果是a = 5,b = c = 3如果改變其順序,寫成:a = b; c = a; b = c; 則執行結果就變成a = b = c = 5,不能達到預期的目的,初學者最容易犯這種錯誤。 順序結構可以獨立使用構成一個簡單的完整程序,常見的輸入、計算,輸出三步曲的程序就是順序結構,例如計算圓的面積,其程序的語句順序就是輸入圓的半徑r,計算s = 3.14159*r*r,輸出圓的面積s。不過大多數情況下順序結構都是作為程序的一部分,與其它結構一起構成一個復雜的程序,例如分支結構中的復合語句、循環結構中的循環體等。
(2) 分支結構
順序結構的程序雖然能解決計算、輸出等問題,但不能做判斷再選擇。對於要先做判斷再選擇的問題就要使用分支結構。分支結構的執行是依據一定的條件選擇執行路徑,而不是嚴格按照語句出現的物理順序。分支結構的程序設計方法的關鍵在於構造合適的分支條件和分析程序流程,根據不同的程序流程選擇適當的分支語句。分支結構適合於帶有邏輯或關系比較等條件判斷的計算,設計這類程序時往往都要先繪制其程序流程圖,然後根據程序流程寫出源程序,這樣做把程序設計分析與語言分開,使得問題簡單化,易於理解。程序流程圖是根據解題分析所繪制的程序執行流程圖。
學習分支結構不要被分支嵌套所迷惑,只要正確繪制出流程圖,弄清各分支所要執行的功能,嵌套結構也就不難了。嵌套只不過是分支中又包括分支語句而已,不是新知識,只要對雙分支的理解清楚,分支嵌套是不難的。下面我介紹幾種基本的分支結構。
①if(條件)
{
分支體
}
這種分支結構中的分支體可以是一條語句,此時「{ }」可以省略,也可以是多條語句即復合語句。它有兩條分支路徑可選,一是當條件為真,執行分支體,否則跳過分支體,這時分支體就不會執行。如:要計算x的絕對值,根據絕對值定義,我們知道,當x>=0時,其絕對值不變,而x<0時其絕對值是為x的反號,因此程序段為:if(x<0) x=-x;
②if(條件)
{分支1}
else
{分支2}
這是典型的分支結構,如果條件成立,執行分支1,否則執行分支2,分支1和分支2都可以是1條或若干條語句構成。如:求ax^2+bx+c=0的根
分析:因為當b^2-4ac>=0時,方程有兩個實根,否則(b^2-4ac<0)有兩個共軛復根。其程序段如下:

d=b*b-4*a*c;
if(d>=0)
{x1=(-b+sqrt(d))/2a;
x1=(-b-sqrt(d))/2a;
printf(「x1=%8.4f,x2=%8.4f\n」,x1,x2);
}
else
{r=-b/(2*a);
i =sqrt(-d)/(2*a);
printf(「x1=%8.4f+%8.4fi\n」r, i);
printf(「x2=%8.4f-%8.4fi\n」r,i)
}
③嵌套分支語句:其語句格式為:
if(條件1) {分支1};
else if(條件2) {分支2}
else if(條件3) {分支3}
……
else if(條件n) {分支n}
else {分支n+1}
嵌套分支語句雖可解決多個入口和出口的問題,但超過3重嵌套後,語句結構變得非常復雜,對於程序的閱讀和理解都極為不便,建議嵌套在3重以內,超過3重可以用下面的語句。
④switch開關語句:該語句也是多分支選擇語句,到底執行哪一塊,取決於開關設置,也就是表達式的值與常量表達式相匹配的那一路,它不同if…else 語句,它的所有分支都是並列的,程序執行時,由第一分支開始查找,如果相匹配,執行其後的塊,接著執行第2分支,第3分支……的塊,直到遇到break語句;如果不匹配,查找下一個分支是否匹配。這個語句在應用時要特別注意開關條件的合理設置以及break語句的合理應用。
(3)循環結構:
循環結構可以減少源程序重復書寫的工作量,用來描述重復執行某段演算法的問題,這是程序設計中最能發揮計算機特長的程序結構,C語言中提供四種循環,即goto循環、while循環、do –while循環和for循環。四種循環可以用來處理同一問題,一般情況下它們可以互相代替換,但一般不提倡用goto循環,因為強制改變程序的順序經常會給程序的運行帶來不可預料的錯誤,在學習中我們主要學習while、do…while、for三種循環。常用的三種循環結構學習的重點在於弄清它們相同與不同之處,以便在不同場合下使用,這就要清楚三種循環的格式和執行順序,將每種循環的流程圖理解透徹後就會明白如何替換使用,如把while循環的例題,用for語句重新編寫一個程序,這樣能更好地理解它們的作用。特別要注意在循環體內應包含趨於結束的語句(即循環變數值的改變),否則就可能成了一個死循環,這是初學者的一個常見錯誤。
在學完這三個循環後,應明確它們的異同點:用while和do…while循環時,循環變數的初始化的操作應在循環體之前,而for循環一般在語句1中進行的;while 循環和for循環都是先判斷表達式,後執行循環體,而do…while循環是先執行循環體後判斷表達式,也就是說do…while的循環體最少被執行一次,而while 循環和for就可能一次都不執行。另外還要注意的是這三種循環都可以用break語句跳出循環,用continue語句結束本次循環,而goto語句與if構成的循環,是不能用break和 continue語句進行控制的。
順序結構、分支結構和循環結構並不彼此孤立的,在循環中可以有分支、順序結構,分支中也可以有循環、順序結構,其實不管哪種結構,我們均可廣義的把它們看成一個語句。在實際編程過程中常將這三種結構相互結合以實現各種演算法,設計出相應程序,但是要編程的問題較大,編寫出的程序就往往很長、結構重復多,造成可讀性差,難以理解,解決這個問題的方法是將C程序設計成模塊化結構。
(4)模塊化程序結構
C語言的模塊化程序結構用函數來實現,即將復雜的C程序分為若干模塊,每個模塊都編寫成一個C函數,然後通過主函數調用函數及函數調用函數來實現一大型問題的C程序編寫,因此常說:C程序=主函數+子函數。 因些,對函數的定義、調用、值的返回等中要尤其注重理解和應用,並通過上機調試加以鞏固。
三.掌握一些簡單的演算法
編程其實一大部分工作就是分析問題,找到解決問題的方法,再以相應的編程語言寫出代碼。這就要求掌握演算法,根據我們的《C程序設計》教學大綱中,只要求我們掌握一些簡單的演算法,在掌握這些基本演算法後,要完成對問題的分析就容易了。如兩個數的交換、三個數的比較、選擇法排序和冒泡法排序,這就要求我們要清楚這些演算法的內在含義,其中選擇法排序和冒泡法排序稍難,但只要明白排序的具體過程,對代碼的理解就不難了。如用選擇法對10個不同整數排序(從小到大),選擇法排序思路:設有10個元素a[1]~a[10],將a[1]與a[2]~a[10]比較,若a[1]比a[2]~a[10]都小,則不進行交換,即無任何操作;若a[2]~a[10] 中有一個比a[1]小,則將其中最大的一個(假設為a[i])與a[1]交換,此時a[1]中存放了10個中最小的數。第二輪將a[2]與a[3]~a[10]比較,將剩下9個數中的最小者a[i]與a[2]交換,此時a[2] 中存放的10個數中第2小的數;依此類推,共進行9輪比較,a[1]到a[10]就已按從小到大的順序存放。即每一輪都找出剩下數中的最小一個,代碼如下:
for(i=1;i<=9;i++)
for(j=i+1;j<=10;j++)
if(a[i]>a[j]
{temp=a[i];
a[i]=a[j];
a[j]=temp;
}
結語:當我們把握好上述幾方面後,只要同學們能克服畏難、厭學、上課能專心聽講,做好練習與上機調試,其實C語言並不難學。

閱讀全文

與用解析式演算法編寫程序代碼相關的資料

熱點內容
加密兔f碼生成器免費 瀏覽:291
思科路由器命令明文加密 瀏覽:171
方舟生存進化伺服器如何改名字 瀏覽:892
央行數字貨幣app怎麼注冊 瀏覽:431
51單片機顯示時間 瀏覽:769
我的世界網易版怎麼壓縮地圖 瀏覽:682
qq小程序雲伺服器和 瀏覽:740
方舟伺服器怎麼玩才好玩 瀏覽:557
單片機的部件 瀏覽:621
編譯原理遍的過程 瀏覽:252
python讀取json字元串 瀏覽:62
ubuntu1404安裝php 瀏覽:634
lua能編譯嗎 瀏覽:118
思仙怎麼看伺服器 瀏覽:660
php微信圖片防盜鏈 瀏覽:800
安卓1怎麼讀音 瀏覽:297
農業app怎麼開通快捷支付 瀏覽:912
pythonredisdict 瀏覽:389
如何攻擊別人網賭伺服器 瀏覽:882
隱私與應用加密的圖案密碼 瀏覽:38