A. c語言如何實現int類型的加法重載
使用編譯程序。在進行使用C語言進和橘行程序編輯時,其中是可以使用程序中的重載代茄余碼對int類型的加法進喚納團行重載,並且配合使用編譯即可進行實現。
B. 如何實現用while語句計算1-n中的奇數之和及偶數之和,在C語言中
代碼資料銀渣臘:
#include "stdio.h"
#define N 10
int main(int argc,char *argv[]){
int i,so,se;
for(so=se=0,i=1;i<梁改=N;i&1 ? so+=i : se+=i,i++);
printf("The ODD are %d The EVEN are %d "鋒滑,so,se);
return 0;
}
C. c語言中創建動態鏈表
給你些資料吧~仔細看,看完就明白鏈表了
10.7 用指針處理鏈表
10.7.1鏈標概述
鏈表是一種常見的重要的數據結構.它是動態地進行存儲分配的一種結構.我們知道,用數組存放數據時,
必須事先定義固定的長度(即元素個數).比如,有的班級有100人,而有的班只有30人,如果要用同一個數組先後存放不同班級的學生數據,則必須定義長度為100的數組.如果事先難以確定一個班的最多人數,則必須把數組定得足夠大,以能存放任何班級的學生數據.顯然這將會浪費內存.鏈表則沒有這種缺點,它根據需要開辟內存單元.圖10.11表示最簡單的一種鏈表(單向鏈表)的結構.鏈表有一個"頭指針"變數,圖中以head表示,它存放一個地址.
該地址指向一個元素.鏈表中每一個元素稱為"結點",每個結點都應包括兩個部分:一為用戶需要用的實際數據,二為下一個結點的地址.課以看出,head指向第一個元素;第一個元素又指向第二個元素;……,直到最後一個元素,該元素不再指向其它元素,它稱為'表尾",它的地址部分放一個"NULL"(表示"空地址").鏈表到此結束.
可以看到:鏈表中各元素在內存中可以不是連續存放的.要找某一元素,必須先找到上一個元素,根據它提供的下一元素地址才能找到下一個元素.
如果不提供"頭指針"(head),則整個鏈表都無法訪問.鏈表如同一條鐵鏈一樣,一環扣一環,中間是不能斷開的.打個通俗的比方:幼兒園的老師帶領孩子出來散步,老師牽著第一個小孩的手,第一個小孩的另一隻手牽著第二個孩子,……,這就是一個"鏈",最後一個孩子有一隻手空著,他是"鏈尾".要找這個隊伍,必須先找到老師,然後順序找到每一個孩子.
可以看到,這種鏈表的數據結構,必須利用指針變數才能實現
.即:一個結點中應包含一個指針變數,用它存放下一結點的地址.
前面介紹了結構體變數,它包含若干成員.這些成員可以是數值類型,字元類型,數組類型,也可以是指針類型.這個指針類型可以是指向其它結構體類型數據,也可以指向它所在的結構體類型.例如:
struct student
{int num;
float score;
struct student *next;
next是成員名,它是指針類型的,它指向struct student類型數據(這就是next所在的結構體類型).用這種方法可以建立鏈表.見圖10.12.
其中每一個結點都屬於struct student類型,它的成員next存放下一結點的地址,程序設計人員可以不必具體知道地址值,
只要保證將下一個結點的地址放到前一結點的成員next中即可.
請注意:上面只是定義了一個struct student類型,並未實際分配存儲空間.前面講過,鏈表結構是動態地分配存儲的,即在需要時才開辟一個結點的存儲單元.怎樣動態地開辟和釋放存儲單元呢 C語言編譯系統的庫函數提供了以下有關函數.
1.malloc(size) 在內存的動態存儲區中分配一個長度為size的連續空間.
此函數的值(即"返回值")是一個指針,它的值是該分配域的起始地址.如果此函數未能成功地執行,則返回值為0.
2.calloc(n,size) 在內存的動態區存儲中分配n個長度為size的連續空間.函數返回分配域的起始地址;如果分配不成功,返回0.
3.free(ptr) 釋放由ptr指向的內存區.ptr是最近一次調用ca11或ma11oc函數時返回的值.
上面三個函數中,參數n和size為整型,ptr為字元型指針.
請注意:許多C版本提供的malloc和call0c函數得到的是指向字元型數據的指針.新標准C提供的ma110c和ca11oc函數規定為void*類型.
有了本節所介紹的初步知識,下面就可以對鏈表進行操作了(包括建立鏈表,插入或刪除鏈表中一個結點等).有些概念需要在後面的應用中逐步建立和掌握.
10.7.2建立鏈表
所謂建立鏈表是指從無到有地建立起一個鏈表,即一個一個地輸入各結點數據,並建立起前後相鏈的關系.下面通過一個例子來說明如何建立一個鏈表.
[例10.7]寫一函數建立一個有5名學生數據的單向鏈表.
先考慮實現此要求的演算法(見圖10. 13).
設三個指針變數:head,p1,p2,它們都指向結構體類型數據.先用mal1oc函數開辟一個結點,並使p1,p2指向它.
然後從鍵盤讀人一個學生的數據給pl所指的結點.我們約定學號不會為零,如果輸入的學號為0,則表示建立鏈表的過程完成,該結點不應連接到鏈表中.先使head的值為NULL(即等於0),這是鏈表為"空"時的情況(即head不指向任何結點,鏈表中無結點),以後增加一個結點就使head指向該結點.
如果輸入的pl一>num不等於0,而且輸入的是第一個結點數據(n=1)時,則令head=p1,
即把p1的值賦給head,也就是使head也指向新開辟的結點(圖10.14).P1所指向的新開辟的結點就成為鏈表中第一個結點.然後再開辟另一個結點並使p1指向它,接著讀入該結點的數據(見圖10.15(a)).如果輸入的p1->num!=0,則應鏈入第2個結點(n=2),由於n!=1,則將p1的值賦給p2-->next,也就是使第一個結點的next成員指向第二個結點(見圖10.15(b)).接著使p2=p1,
也就是使p2指向剛才建立的結點,見圖10.15(c).再開辟一個結點並使pl指向它,並讀入該結點的數據(見圖10.16(a)),在第三次循環中,由於n=3(n!=1),又將pl的值賦給p2一>next,也就是將第3個結點連接到第2個結點之後,並使p2=p1,使p2指向最後一個結點(見圖10.16(b).
再開辟一個新結點,並使pl指向它,
輸入該結點的數據(見圖10.17(a)).由於pl一>num的值為0,不再執行循環,此新結點不應被連接到鏈表中.此時將NULL賦給p2一>next,見圖10.17(b).建立鏈表過程至此結束,pl最後所指的結點未鏈入鏈表中,第3個結點的next成員的值為NULL,它不指向任何結點.雖然pl指向新開辟的結點,但從鏈表中無法找到該結點.
建立鏈表的函數可以如下:
#define NULL 0
#define LEN sizeof(struct student)
struct student
{1ong num;
float score;
struct student *next;
};
int n;
struct student *creat()
/*此函數帶回一個指向鏈表頭的指針*/
{struct student *head;
struct student *p1, *p2;
n=0;
p1=p2=(struct student*)mal1oc(LEN);/*開辟一個新單元*/
scanf("%ld,%f",&pl一>num,&pl一>score);
head=NULL:
while (pl一>num!=0)
{n=n十1;
if(n==1) head=pl;
else p2一>next=p1;
p2=pl;
pl=(struct student*)malloc(LEN);
scanf("%1d,%f",&p1-->num,&pl一>score);
}
p2一>next=NULL;
return(head);
}
請注意:
(1)第一行為#define命令行,令NULL代表0,用它表示"空地址".第二行令LEN代表struct student結構體類型數據的長度,
sizeof是"求位元組數運算符".
(2)第9行定義一個creat函數,它是指針類型,即此函數帶回一個指針值,它指向一個struct student類型數據.實際上此creat函數帶回一個鏈(3)malloc(LEN)的作用是開辟一個長度為LEN的內存區,LEN已定義為sizeof(struct student),即結構體struct student的長度.在一般系統中,malloc帶回的是指向字元型數據的指針.
而p1,p2是指向struct student類型數據的指針變數,二者所指的是不同類型的數據,這是不行的.因此必須用強制類型轉換的方法使之類型一致,在malloc (LEN)之前加了"(struct student*)",它的作用是使malloc返回的指針轉換為指向struct student類型數據的指針.注意"*"號不可省略,否則變成轉換成struct student類型了,而不是指針類型了.
(4)最後一行return後面的參數是head(head已定義為指針變數,指向struct student類型數據).因此函數返回的是head的值,也就是鏈表的頭地址.
(5)n是結點個數.
(6)這個演算法的思路是:讓pl指向新開的結點,p2指向鏈表中最後一個結點,把pl所指的結點連接在p2所指的結點後面,用"p2一>next=pl"來實現.
我們對建立鏈表過程作了比較詳細的介紹,
讀者如果對建立鏈表的過程比較清楚的話,對下面介紹的刪除和插入過程也就比較容易理解了.
10.7.3輸出鏈麥
將鏈表中各結點的數據依次輸出.這個問題比較容易處理.首先要知道鏈表頭元素的地址,也就是要知道head的值.然後設一個指針變數p,先指向第一個結點,輸出p所指的結點,然後使p後移一個結點,再輸出.直到鏈表的尾結點.
「例10.8]寫出輸出鏈表的函數print.
void print(head)
struct student *head;
{struct student *p;
printf("\nNow,These%drecords are:\n",n);
p=head;
if(head!=NULL)
do
{printf("%ld%5.1f\",p一>num,p—>score);
p=p一>next;
}while(p!=NULL);
演算法可用圖10.18表示.
其過程可用圖10.19表示.p先指向第一結點,在輸出完第一個結點之後,p移到圖中p'虛線位置,指向第二個結點.程序中p=p一>next的作用是:將p原來所指向的結點中next的值賦給p,
而p一>next的值就是第二個結點的起始地址.將它賦給p就是使p指向第二個結點.
head的值由實參傳過來,也就是將已有的鏈表的頭指針傳給被調用的函數,在print函數中從head所指的第一個結點出發順序輸出各個結點.
10.7.4 對鏈麥的刪除操作
已有一個鏈表,希望刪除其中某個結點.怎樣考慮此問題的演算法呢,先打個比方:
一隊小孩(A.B.C.D.E)手拉手,如果某一小孩(C)想離隊有事,而隊形仍保持不變.只要將C的手從兩邊脫開,B改為與D拉手即可,見圖10.20.圖10.20(a)是原來的隊伍,圖10.20(b)是c離隊後的隊伍.
與此相仿,從一個鏈表中刪去一個結點,並不是真正從內存中把它抹掉,而是把它從鏈表中分離開來,即改變鏈接關系即可.
[例10.9]寫一函數以刪除指定的結點.
我們以指定的學號作為刪除結點的標志.例如,輸入89103表示要求刪除學號為89103的結點.解題的思路是這樣的:從p指向的第一個結點開始,檢查該結點中的num值是否等於輸入的要求刪除的那個學號.如果相等就將該結點刪除,如不相等,就將p後移一個結點,再如此�下去,直到遇到表尾為止.
可以設兩個指針變數pl和p2,先使pl指向第一個結點(圖10.21(a)).如果要刪除的不是第一個結點,
則使pl後指向下一個結點(將pl一>next賦給pl),在此之前應將pl的值賦給p2,使p2指向剛才檢查過的那個結點,見圖10.21(b).如此一次一次地使p後移,直到找到所要刪除的結點或檢查完全部鏈表都找不到要刪除的結點為止.如果找到某一結點是要刪除的結點,還要區分兩種情況:①要刪的是第一個結點(pl的值等於head的值,如圖10.21(a)那樣),則應將pl一>next賦給head.見圖10.21(c).
這時head指向原來第二個結點.第一個結點雖然仍存在,但它已與鏈表脫離,因為鏈表中沒有一個元素或頭指針指向它.雖然p1還指向它,它仍指向第二個結點,但仍無濟於事,現在鏈表的第一個結點是原來第二個結點,原來第一個結點"丟失".②如果要刪除的不是第一個結點,則將pl一>next賦給p2一>next,見圖10.21(d).p2一>next原來指向pl指向的結點(圖中第二個結點),現在p2一>next改為指向p1一>next所指向的結點
(圖中第三個結點).pl所指向的結點不再是鏈表的一部分.
還需要考慮鏈表是空表(無結點)和鏈表中找不到要刪除的結點的情況.
圖10.22表示解此題的演算法.
刪除結點的函數del如下:
struct student *del(head,num)
struct student *head;
1ong num;
{struct student *p1,*p2;
if(head==NULL) {printf("\nlist null!\n");goto end;}
p1=head;
whi1e (num!=pl一>num&&pl一>next!一NULL)/*pl指向的不是所要找的結點,並且後面還有結點點*/
{p2=p1;pl=pl一>next;}/*後移一個結點*/
if (num==pl一>num) /*找到了*/
{if (n1==head) head=pl一>next;/*若pl指向的是頭結點,把第二個結點地址賦予head*/
e1se p2一>next=pl一>next;/*否則將下一結點地址賦給前一結點地址*\
printf("delete:%ld\n",num);
n=n-1;
}
else printf("%ld not been found!\n",num);/*找不到該結點*/
end:
return(head);
}
函數的類型是指向struct student類型數據的指針,
它的值是鏈表的頭指針.函數參數為head和要刪除的學號num.head的值可能在函數執行過程中被改變(當刪除第一個結點時).
10.7.5對鏈表的插入操作
將一個結點插入到一個已有的鏈表中.設已有的鏈表中各結點中的成員項num(學號)是按學號由小到大順序排列的.
用指針變數p0指向待插入的結點,pl指向第一個結點.見圖10.23(a).
將p0一>num與pl一>num相比較,如果p0一>num>pl一>num,則待插入的結點不應插在pl所指的結點之前.此時將pl後移,並使p2指向剛才pl所指的結點,見圖10.23(b).再將p1一>num與p0一>num比.如果仍然是p0一>num大,則應使pl繼續後移,直到p0一>numnum為止.這時將p0所指的結點插到pl所指結點之前.但是如果p1所指的已是表尾結點,則pl就不應後移了.如果p0一>num比所有結點的num都大,
則應將p0所指的結點插到鏈表末尾.
如果插入的位置既不在第一個結點之前,又不在表尾結點之後,則將p0的值賦給p2一>next,即使p2一>next指向待插入的結點,然後將pl的值賦給p0->next,即使得p0一>next指向pl指向的變數.見圖10.23(c).可以看到,在第一個結點和第二個結點之間已插入了一個新的結點.
如果插入位置為第一結點之前(即pl等於head時),
則將p0賦給head,將p1賦給p0->next.見圖10.23(d).如果要插到表尾之後,應將p0賦給pl一>next,NULL賦給p0一>next,見圖10.23(e).
以上演算法可用圖10.24表示.
[例10. 10]插入結點的函數insert如下.
struct student *insert(head,stud)
struct student *head,*stud:
{struct student *p0,*p1,*p2;
pl=head;/*使pl指向第一個結點*/
p0=stud;/*p0指向要插入的結點*/
if (head==NULL)/*原來是空表*/
{head=p0;p0一>next=NULL;}/*使p0指向的結點作為第一個結點*/
else
{while ((p0一>num>pl一>num)&&(pl一>next!=NULL))
{p2=p1;p1=pl一>next;}/*p2指向剛才pl指向的結點,p1後移一個結點*/
if(p0->numnext=p0;/*插到p2指向的結點之後*/
p0—>next=p1;}
else
{pl一>next=p0;p0一>next=NULL;}}/*插到最後的結點之後*/
n=n+1; /*結點數加1*/
return(head);
}
函數參數是head和stud.stud也是一個指針變數,從實參傳來待插入結點的地址給stud.語句p0=stud的作用是使p0指向待插入的結點.
函數類型是指針類型,函數值是鏈表起始地址head.
將以上建立,輸出,刪除,插入的函數組織在一個程序中,用main函數作主調函數.可以寫出以下main函數.
main()
{struct student *head,stu;
1ong de1_num;
printf("input records:\n");
head=creat(); /*返回頭指針*/
print(head); /*輸出全部結點*/
printf("\ninput the deleted 0number:");
scanf("%ld",&de1_mum);/*輸入要刪除的學號*/
head=del(head,de1_num);/*刪除後的頭地址*/
print(head); /*輸出全部結點*/
prinif("/ninput the inserted record:")/*輸入要插入的記錄*/
scanf("%ld,%f",&stu.num,&stu.score);
head=insert(head,&stu);/*返回地址*/
print(head);
}
此程序運行結果是正確的.
它只刪除一個結點,插入一個結點.但如果想再插入一個結點,重復寫上程序最後四行,即共插入兩個結點.運行結果卻是錯誤的.
input records:(建立鏈表)
89101,90
89103,98
89105,76
0,0
Now,These 3 records are:
89101 90.0
89103 98.0
89105 76.0
inpu the deleted number:
89103 (刪除)
delete:89103
Now,These 2 records are:
89101 90.0 89105 76.0
input the inserted record:89102
90 (插入第一個結點)
Now,These 3 records are:
89101 90.0
89102 90.0
89105 76.0
input the inserted record:89104,99/(插入第二個結點)
Now,The 4 records are:
89101 90.0
89104 99.0
89104 99.0
89104 99.0
...
...
(無終止地輸出89104的結點數據)
請讀者將main與insert函數結合起來考察為什麼會產生以上運行結果.
出現以上結果的原因是:stu是一個有固定地址的變數.第一次把stu結點插入到鏈表中.第二次若再用它來插入第二個結點,就把第一次結點的數據沖掉了.
實際上並沒有開辟兩個結點.讀者可根據insert函數畫出此時鏈表的情況.為了解決這個問題,必須在每插入一個結點時新開辟一個內存區.我們修改main函數,使之能刪除多個結點(直到輸入要刪的學號為0),能插入多個結點(直到輸入要插入的學號為0).
main函數如下:
main()
{struct student *head,*stu;
1ong de1_num;
printf("input records:/n");
head=creat();
print (head);
printf("/ninput the deleted number:");
scanf("%1d",&del_num);
while (de1_num!=0)
{head=del(head,del_num);
print(head);
printf("input the deleted number:");
scanf("%ld",&del_num);
printf("\ninput the inserted record:");
stu=(struct student*)malloc(LEN);
scanf("%1d,%f,",&stu一>num,&stu一>scor);
while (stu一>num!=0)
{head=insert(head,stu):
print(head);
prinif("input the inserted record:");
stu=(struct student*)malloc(LEN);
scanf("%1d,%f,&stu一>num,&stu一>score);
}
}
sum定義為指針變數,在需要插入時先用malloc函數開辟一個內存區,將其起始地址經強制類型轉換後賦給stu,然後輸入此結構體變數中各成員的值.對不同的插入對象,stu的值是不同的,每次指向一個新的結構體變數.在調用insert函數時,實參為head和stu,將已建立的鏈表起始地址傳給insert函數的形參,將stu(既新開辟的單元的地址)傳給形參stud,函數值返回經過插入之後的鏈表的頭指針(地址).
運行情況如下:
input records:
89101,99
89103,87
89105,77
0,0
Now, These 3 records are.
89101 99.0
89103 87.0
89105 77.0
input the deleted number:89103
delete:89103
Now,These 2 records are:
89101 99.0
89105 77.0
input the de1eted number:89105
delete:89105
Now,These l records are:
89101 99.0
input the de1eted number:0
1nput the inserted record:89104,87
NOw,These 2 records are:
89101 99.0
89104 87.0
input the inserted record:89106,65
Now,These 3 records are:
89101 99.0
89104 87.0
89106 65.0
input the inserted record:0,0
對這個程序請讀者仔細消化.
指針的應用領域很寬廣,除了單向鏈表之外,還有環形鏈表,雙向鏈表.此外還有隊列,樹,棧,圖等數據結構.
有關這些問題的演算法可以學習《數據結構>>課程,在此不作詳述.
D. C語言如何定義n=8則1n=18、2n=28、3n=38
你這個用好野如的都是脊姿整數友啟,所以用int。
int n = 8, _1n = 18, _2n = 28, _3n = 38;
E. 急求c語言改錯!輸入一個數字,若存在該數字並位置正確就是1M,數字存在但位置不對應則是1N。
1. M N必須初始化為0.
2.
if(a==e)
M++;
if((a==f)||(a==g)||(a==h))
{
if(a!=e)//這種情況必須判斷a是否唯睜等於e,攜伏比如abcd=1234,efgh=1111時,會造成N++,而此時N不該++
N++;
}
其他三組也要做這樣的修改。
3.printf("%dA%dB",M,N);應該放到while循指隱歲環中最後一句