c語言中pl
Ⅰ P乚C有哪些主要特點
C的特點 1. 簡潔緊湊、靈活方便 c語言一共只有32個關鍵字,9種控制語句,程序書寫自由,主要用小寫字母表示。它把高級語言的基本結構和語句與低級語言的實用性結合起來。 C 語言可以象匯編語言一樣對位、位元組和地址進行操作, 而這三者是計算機最基本的工作單元。 2. 運算符豐富 C的運算符包含的范圍很廣泛,共有種34個運算符。C語言把括弧、賦值、強制類型轉換等都作為運算符處理。從而使C的運算類型極其豐富表達式類型多樣化,靈活使用各種運算符可以實現在其它高級語言中難以實現的運算。 3. 數據結構豐富 C的數據類型有:整型、實型、字元型、數組類型、指針類型、結構體類型、共用體類型等。能用來實現各種復雜的數據類型的運算。並引入了指針概念,使程序效率更高。另外C語言具有強大的圖形功能, 支持多種顯示器和驅動器。且計算功能、邏輯判斷功能強大。 4. C是結構式語言 結構式語言的顯著特點是代碼及數據的分隔化,即程序的各個部分除了必要的信息交流外彼此獨立。這種結構化方式可使程序層次清晰, 便於使用、維護以及調試。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
對這個程序請讀者仔細消化.
指針的應用領域很寬廣,除了單向鏈表之外,還有環形鏈表,雙向鏈表.此外還有隊列,樹,棧,圖等數據結構.
有關這些問題的演算法可以學習《數據結構>>課程,在此不作詳述.
Ⅲ c語言擴展pl/0時怎麼判斷讀到文件尾部
#include
#include
#include
#include
#define max 20
typedef struct student //學生
{
char sno[max]; // 學號
char sname[max]; //姓名
char sex[max]; //性別
char age[max]; //年齡
char depart[max]; //系
char classs[max]; //班
char grade[max]; //年級
struct student* next;
} student;
student* head;
int LogOn() //登錄模塊,已實現輸入密碼不回顯,如果中途發現輸錯某幾位,可退格鍵重輸
{
char username[max],password[max];
printf("\n請輸入用戶名:");
scanf("%s",username);
printf("\n請輸入密碼(最多15位):");
//開始以不回顯且支持退格方式獲取輸入密碼
int i=0;
while((i>=0)&&(password[i++]=getch())!=13)//條件i>=0是用於限制退格的范圍
{
if(password[i-1]=='\b')//對退格鍵的處理
{
printf("%c%c%c",'\b','\0','\b');
i=i-2;
}
else
printf("*");
}
password[--i]='\0';
//已獲取密碼。驗證用戶身份
if(!strcmp(username,"zhang")&&!strcmp(password,"8147086"))
{
printf("\n登錄成功!");
return 1;
}
else
return 0;
}
void regist()
{
char ch;
student *s,*ptr; //s用來建新結點,ptr用來暫存頭結點
do
{
s=(student*)malloc(sizeof(student)); // 新建一個學生結點
printf("\n開始注冊..."); //開始注冊
printf("\n請輸入該學生的學號:");
scanf("%s",s->sno);
printf("\n請輸入該學生的姓名:");
scanf("%s",s->sname);
printf("\n請輸入該學生的性別:");
scanf("%s",s->sex);
printf("\n請輸入該學生的年齡:");
scanf("%s",s->age);
printf("\n請輸入該學生的系:");
scanf("%s",s->depart);
printf("\n請輸入該學生所在的班:");
scanf("%s",s->classs);
printf("\n請輸入該學生所在的年級");
scanf("%s",s->grade);
ptr=head;
head=s;//將新結點插入隊頭
s->next=ptr;
fflush(stdin);
printf("\n請問是否繼續注冊?(Y/N)");
scanf("%c",&ch);
}while(ch=='Y'||ch=='y');
return;
}
void ElePrint(char str[]) //輸出單個元素
{
if(str==NULL) exit(0);
printf("%s",str);
for(unsigned int i=0;i<12-strlen(str);i++) printf(" ");//為了對齊輸出,需插入一些空格
return;
}
int LinePrint(student *ptr) //輸出一行
{
if(ptr==NULL) //檢查傳進來的指針
return 0;
printf("\n");
ElePrint(ptr->sno);
ElePrint(ptr->sname);
ElePrint(ptr->age);
ElePrint(ptr->sex);
ElePrint(ptr->depart);
ElePrint(ptr->classs);
ElePrint(ptr->grade);
return 1;
}
void print() //輸出全部學生信息
{
student *ptr=head;
printf("\n學號 姓名 年齡 性別 系 班 年級 ");
while(ptr)
{
LinePrint(ptr);
ptr=ptr->next;
}
printf("\n");
return;
}
void search()//查詢模塊
{
int method;//查詢方式
char no[max],name[max],departm[max],clss[max],grades[max]; //用來接收查詢關鍵字
while(1)
{
printf("\n請選擇查詢方式");
printf("\n1.按學號查詢");
printf("\n2.按姓名查詢");
printf("\n3.按所在系查詢");
printf("\n4.按所在班級查詢");
printf("\n5.按所在年級查詢");
printf("\n6.列印全部學生信息");
printf("\n7.返回主菜單\n");
scanf("%d",&method);
student *p=head,*temp;
switch(method)
{
case 1:
printf("\n請輸入要查詢的學號:");
scanf("%s",no);
while(p)
{
if(!strcmp(p->sno,no))
break;
else
{
temp=p;
p=p->next;
}
}
printf("\n學號 姓名 年齡 性別 系 班 年級 ");
LinePrint(p);
break;
case 2:
printf("\n請輸入要查詢的姓名:");
scanf("%s",name);
printf("\n學號 姓名 年齡 性別 系 班 年級 ");
while(p)
{
if(!strcmp(p->sname,name))
LinePrint(p);
p=p->next;
}
break;
case 3:
printf("\n請輸入學生所在的系:");
scanf("%s",departm);
printf("\n學號 姓名 年齡 性別 系 班 年級 ");
while(p)
{
if(!strcmp(p->depart,departm))
LinePrint(p);
p=p->next;
}
break;
case 4:
printf("\n請輸入學生所在的班:");
scanf("%s",clss);
printf("\n請輸入學生所在的年級:");
scanf("%s",grades);
printf("\n學號 姓名 年齡 性別 系 班 年級 ");
while(p)
{
if(!strcmp(p->classs,clss)&&!strcmp(p->grade,grades))
LinePrint(p);
p=p->next;
}
break;
case 5:
printf("\n請輸入學生所在的年級:");
scanf("%s",grades);
printf("\n學號 姓名 年齡 性別 系 班 年級 ");
while(p)
{
if(!strcmp(p->grade,grades))
LinePrint(p);
p=p->next;
}
break;
case 6:
print();
break;
case 7:
return;
default:
printf("很抱歉,暫無此查詢方式!");
break;
}
}
}
void modify()//修改學生信息
{
char num[max];
student *p=head;
printf("\n請輸入要修改的學生的學號:");
scanf("%s",num);
while(p)
{
if(!strcmp(p->sno,num))
break;
else
p=p->next;
}
if(p==NULL)
{
printf("\n錯誤:沒有此學生的信息!\n");
return;
}
LinePrint(p);
printf("\n請輸入要修改的該學生的信息:");
printf("\n1.姓名");
printf("\n2.性別");
printf("\n3.年齡");
printf("\n4.所在的系");
printf("\n5.所在的班");
printf("\n6.所在的年級");
char name1[max],sex1[max],age1[max],depart1[max],class1[max],grade1[max];
int select;
fflush(stdin);
scanf("%d",&select);
printf("\n請輸入新的信息:");
switch(select)
{
case 1:
scanf("%s",name1);
strcpy(p->sname,name1);
break;
case 2:
scanf("%s",sex1);
strcpy(p->sex,sex1);
break;
case 3:
scanf("%s",age1);
strcpy(p->age,age1);
break;
case 4:
scanf("%s",depart1);
strcpy(p->depart,depart1);
break;
case 5:
scanf("%s",class1);
strcpy(p->classs,class1);
break;
case 6:
scanf("%s",grade1);
strcpy(p->grade,grade1);
break;
default:
printf("\nError!");
break;
}
LinePrint(p);
return;
}
void del()// 刪除某學生的信息
{
student *p=head,*temp=head,*s;
char num1[max];
printf("\n請輸入要刪除的學生的學號:");
scanf("%s",num1);
while(p)//查找該學生所在的結點
{
if(!strcmp(p->sno,num1))
break;
else
{
temp=p;
p=p->next;
}
}//while
if(!p)
{
printf("\n不存在此學生的信息.");
return;
}
LinePrint(p);//輸出該學生的信息
printf("\n請問真的要刪除該學生的信息嗎?(Y/N)");
char ch;
fflush(stdin);
scanf("%c",&ch);
if(ch=='Y'||ch=='y')
{
s=p->next;
temp->next=s;
free(p);
printf("\n已經刪除該學生的信息.");
}
return;
}
void sort() //排序模塊。將學生記錄按學號從小到大排列。用起泡排序演算法實現
{
student *ptr,*s=head,*p;
int count=0,count1;
while(s)//統計鏈表結點個數
{
count++;
s=s->next;
}
for(int i=1;i<count;i++)
{
ptr=head;
p=NULL;
count1=count-i; //用來控制每輪起泡排序的終點,即每次把學號最小的結點移到倒數第i個結點
while(ptr&&ptr->next&&(count1--))
{
if(strcmp(ptr->sno,ptr->next->sno)>0)
{
s=ptr->next;
ptr->next=s->next;
if(p==NULL) //ptr處於隊頭時
head=s;
else
p->next=s;
s->next=ptr;
p=s;
}
else
{
ptr=ptr->next;
if(p==NULL) //ptr處於隊頭時
p=head;
else
p=p->next;
}
}
}
return;
}
void quit()
{
char ch;
printf("\n真的要退出?(Y/N)");
fflush(stdin);
scanf("%c",&ch);
if(ch=='Y'||ch=='y')
exit(0);
return;
}
int main()
{
int option;
printf("\nCopyright@2005 KongXinCai All rights reserved.");
printf("\n歡迎使用學生信息管理系統!\n");
//登錄模塊
int icheck=0;
while(icheck<3)
{
if(LogOn()==0)
icheck++;
else
break;
}
if(icheck==3)
{
printf("\n連續登錄三次不成功,退出!");
exit(0);
}
//系統界面
while(1)
{
printf("\n\n請選擇需要的服務:");
printf("\n1.注冊");
printf("\n2.查詢");
printf("\n3.修改");
printf("\n4.刪除");
printf("\n5.排序");
printf("\n7.求平均");
printf("\n6.退出\n");
scanf("%d",&option);
switch(option)
{
case 1:
regist();
break;
case 2:
search();
break;
case 3:
modify();
break;
case 4:
del();
break;
case 5:
sort();
break;
case 6:
quit();
break;
}
}
return 0;
}
Ⅳ C語言編程,想了很久,沒想出來
這個問題很簡單,定義兩個數組就行了,每次間隔提取字元
char a[100];
char b[100];
int i,j;
scanf("%s",a);
for(i=0;i<strlen(a);i+=2)//加上string.h頭文件
b[j++]=a[i];
遍歷輸出就行了
Ⅳ C語言中 可以只改變字元串字面量中的字元,而不改變它所在的地址嗎
這個不行,這樣聲明是字元串常量,是不可變的,運行會報錯。
如果你聲明為char pl[] = "Yes";就沒問題
Ⅵ plc語言與單片機語言和c語言有什麼共同點-區別
單片機匯編和C都可以編的,你說的單片機語言特指匯編嗎?編譯之後在單片機上燒錄的機械語言 是由操作碼和操作數,全是0和1表示的,把用類似單詞的助記符一一對應操作碼,就是匯編。C語言是高級語言,需要有軟體包降譯成機器語言再燒入單片機。PLC的核心是單片機,可以用梯形圖、指令表、功能框圖來編程,指令表像匯編,梯形圖、功能框圖是經過了一層很「厚」的封裝高級語言,類似C語言 最後都是要編譯成機械語言燒入核心的
Ⅶ park *pl在c語言中是什麼意思
這個語句的意思是,聲明了一個名為pl的指針,它指向的目標是一個類型為park的數據結構。
Ⅷ 在c語言的指針運算中*(p+1)與p+1有什麼區別 p是指針
一、指代不同
1、*(p+1):表示具體的數值。
2、p+1:表示內存地址。
二、指向的值不同
1、*(p+1):指針p所指向的內存地址單元的下一個內存地址單元中的值。
2、p+1:指針p所指向的內存地址的下一個內存地址。
三、內存表示不同
1、*(p+1):*的優先順序比+的優先順序高,所以*P+1在編譯器中是先取出p指向的int值然後加1。
2、p+1:直接將內存中指向的地址加1,就是將要指向的地址。