C語言學習與感悟——《C語言學習基礎程序》

前言

博主在幾年前的C語言後中,結合自身學習情況和學習感悟在當時的一個寒假做了兩份C語言學習的經驗總結,分別爲 《C語言學習基本框架》《C語言學習基礎程序》
現在把它們分享出來,供大家交流學習,如果能給初學C語言的小夥伴們提供一些幫助也是不錯的,想當初我也是從C語言的折磨中走出來的,吼吼吼!

一、常見練習題

1. 計算1!+2!+n!

思路:運用兩層for循環,一層進行階乘計算,一層進行加法運算.

#include
int main()
{
int n,i,j,k=1,s=0;
printf("請輸入項數:\n");
scanf("%d",&n);
for(i=1;i<=n;i++)
{
               k=1;  
for(j=1;j<=i;j++)
{
k=k*j;
}
s=s+k;
}
printf("結果=%d\n",s);
return 0; }

2. 計算斐波那列數列第n項

思路:先對項數進行判斷,分爲兩部分計算,第二部分運用遞歸的思想.

#include
int main()
{
int n,i,f,f1=1,f2=1;
printf("請輸入項數:\n");
scanf("%d",&n);
if(n<=2)
f=1;
else
for(i=3;i<=n;i++)
{
f=f1+f2;
f1=f2;
f2=f;
}
printf("結果=%d\n",f);
return 0;
}

3. 愛因斯坦階梯問題

思路:通過while循環判斷,不斷增加倍數,直至循環結束.

#include
int main()
{
int x=7,i=1;
while(!((x%2==1)&&(x%3==2)&&(x%5==4)&&(x%6==5)))
{
i++;
x=7*i;
}
printf("%d\t",x);
return 0;
}

4. 求勾股數

思路:通過三層for循環依次遞增,再運用if語句進行判斷.

#include
int main()
{
int x,y,z,k=0;
for(x=1;x<100;x++)
{
for(y=1;y<100;y++)
{
for(z=1;z<100;z++)
{
if(x*x+y*y==z*z&&x<y&&y<z)< p=""></y&&y<z)<>
printf("x=%dy=%dz=%d\n",x,y,z),k++;
}
}
}
printf("%d\n",k);
return 0;
}

5. 百錢百雞問題

思路:通過三層for循環將雞翁,雞母,雞雛依次遞增,在運用if語句進行兩個條件合併判斷.

#include
int main()
{
int x,y,z;
for(x=1;x<=20;x++)
{
for(y=1;y<=33;y++)
{
for(z=1;z<=100;z++)
{
if(15*x+9*y+z==300&&x+y+z==100)
printf("公雞:%d母雞:%d雞雛:%d\n",x,y,z);
}
}
}
return 0;
}

6. 編寫函數,一趟循環,找出數組的最大元素和最小元素

思路:以a[0]爲比較元素,與數組其他元素依次判斷,如果大於則記錄max,如果小於則記錄min.

#include<stdio.h>
void max_min(int p[]);
int main()
{
int a[10],i;
printf("input 10 integers:\n");
for(i=0;i<10;++i)
scanf("%d",&a[i]);
max_min(a);
return 0;
}
void max_min(int p[])
{
int i,max=0,min=0;
for (i=0;i<10;i++)
{
if(p[max]<p[i])
max=i;
if(p[min]>p[i])
min=i;
}
printf("最大值=%d\t最小值=%d\n",p[max],p[min]);
}

7. 編寫函數,倒排數組元素

思路:將數組元素分爲前後兩個部分,然後兩個部分頭尾對應函數依次交換. 解法:

#include <stdio.h>
void RevertToSelf(int p[],int n);
int main()
{
   int a[6],i;
printf("input 6 integers:\n");
for (i=0;i<6;i++)
{
scanf("%d",&a[i]);
}
printf("倒排後:\n");
  RevertToSelf(a,6);
   return 0;
}
void RevertToSelf(int p[],int n)
{
int temp,i;
for(i=0;i<n/2;i++)
   {
       temp=p[i];
       p[i]=p[n-1-i];
       p[n-1-i]=temp;
   }
   for(i=0;i<n;i++)
    printf("%d\t",p[i]);
printf("\n"); }

8. 編寫函數,從數組元素中挑選出百位數比十位數和個位數之和還大的元素

思路:將數組元素個位數,十位數,百位數分別賦值,後運用if語句比較判斷. 解法

#include<stdio.h>
void compare(int p[]);
int main()
{
int a[5],i;
printf("input 5 integers:\n");
for(i=0;i<5;i++)
{
scanf("%d",&a[i]);
}
compare(a);
return 0;
}
void compare(int p[])
{
int i,k,x,y,z;
for (i=0;i<5;i++)
{
k=p[i];
   x=k%10;
   k=k/10;
   y=k%10;
   k=k/10;
   z=k%10;
if(x+y<z)
printf("元素:%d\n",p[i]); } }

9. 編寫檢驗密碼函數,密碼輸入錯誤時,允許重新輸入,最多3次

思路:首先運行for語句設置3次循環,進入for循環後首先進行strcmp判斷,若爲是則通過,不是則記錄次數,達到3次則退出.

#include<stdio.h>
#include<string.h>
int main()
{
char a[10];
char b[10]="123456";//初始化密碼
int i;
printf("請輸入密碼:\n");
for(i=0;i<3;i++)//輸入三次密碼
{
scanf("%s",&a);
if(strcmp(a,b)==0)//比較字符串
{
   printf("歡迎使用!\n");
   return 0;
}
else
if(i<2)
 printf("輸入錯誤,請重新輸入:\n");
if(i==2)
 printf("非法用戶!\n");
}
return 0;
}

二、常見問題

1. Josephus問題

問題描述:假設有n個人圍坐一圈,現在要求從第k個人開始報數,報到第m個數的人退出。然後從下一個人開始繼續報數並按照同樣的規則退出,直至所有人都退出。按照順序輸出各出列人的編號

#include<stdio.h>
#include<stdlib.h>
int josephus(int n,int m);
int main()
{
	int num,counter;
	printf("請輸出總人數和循環數:\n");
	scanf("%d%d",&num,&counter);
	printf("獲勝者=%d\n",josephus(num,counter));
	return 0;
}
int josephus(int n,int m)
{
	int i,j,winner,*p;
	p=(int*)malloc(n*sizeof(int));
	for(i=0;i<n;i++)
	p[i]=i+1;
	i=0;
	while(n>1)
	{
		i=(i+m-1)%n;
		printf("淘汰者:%d\n",p[i]);
		for(j=i+1;j<n;j++)
			p[j-1]=p[j];
		n--;
		if(i==n)
			i=0;
	}
	winner=p[0];
	free(p);
	return winner;
}

2. 模擬洗牌

問題模擬:編程用C語言模擬人工洗牌過程

#include<stdio.h>
#include<stdlib.h>
#include <time.h>
typedef struct 
 {
	char suit;
	int pips;
}Card;
void shuffle(Card pa[],int n);
void display(const Card pa[],int n);
int main()
{
	int i;
	Card deck[52];
	for (i=0;i<52;i++)
	{
		deck[i].suit=i/13+3;
		deck[i].pips=i%13+1;
	}
	printf("before suffling:\n");
	display(deck,52);
	shuffle(deck,52);
	printf("after shuffling:\n");
	display(deck,52);
	return 0;
}
void shuffle(Card pa[],int n)
{
	int i,j;
	Card temp;
	srand(time(0));
	for (i=0;i<n;i++)
	{
		j=rand()%n;
		temp=pa[i];
		pa[i]=pa[j];
		pa[j]=temp;
	}
}
void display(const Card pa[],int n)
{
	int i;
	for (i=0;i<n;i++)
	{
		printf("(%c-",pa[i].suit);
		printf("%d)",pa[i].pips);
		if((i+1)%13==0)
			printf("\n");
	}
}

3. 起泡排序

問題描述:編程用起泡排序給一組數組從小到大進行排序

#include <stdlib.h>
#include<stdio.h>
void bubble(int p[],int n);
int main()
{
	int i,a[5];
	printf("input 5 integers:\n");
	for(i=0;i<5;i++)
		scanf("%d",&a[i]);
	bubble(a,5);
	return 0;
}
void bubble(int p[],int n)
{
	int i,j,last,temp;
	i=0;
	while(i<n-1)
	{
		last=n-1;
		for (j=n-1;j>i;j--)
		{
			if(p[j]<p[j-1])
			{
				temp=p[j-1];
				p[j-1]=p[j];
				p[j]=temp;
				last=j;
			}
		}
		i=last;
	}
	for(i=0;i<5;i++)
		printf("%d\t",p[i]);
	printf("\n");
}

4. 順序表練習

問題描述:編程使用順序表對數組進行一些基本操作

//Test.c(主函數)
typedef int Type;
#include "seqlist.h"
#include <stdlib.h>
int main()
{
	int i,n;
	Seqlist L;
	IniList(&L,10);//建立空表
	InsertRear(&L,5);//尾插入5
    InsertRear(&L,15);//尾插入15
    InsertRear(&L,20);//尾插入20
	Insert(&L,1,10);//在下標爲1的位置插入10
	Erase(&L,0);//刪除下標爲1的數據元素
    n=Size(&L);//取數據個數
	for (i=0;i<n;i++)
	{
		printf("%d\t",Getdate(&L,i));//打印出現存數據元素
	}
	printf("\n");
	Clear(&L);//清表
	FreeList(&L);//撤銷動態空間
	return 0;
}
//Seqlist.h(順序表聲明)
typedef int Type;
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
	Type * date;
	int size;
	int max;
}Seqlist;
void IniList(Seqlist *l,int n);
void FreeList(Seqlist *l);
void InsertRear(Seqlist *l,Type item);
void Insert(Seqlist *l,int id,Type item);
void Erase(Seqlist *l,int id);
void Clear(Seqlist *l);
Type Getdate(const Seqlist *l,int id);
int Size(const Seqlist *l);
//Seqlist.c(順序表實現)
#include <stdio.h>
#include <stdlib.h>
#include "seqlist.h"
void IniList(Seqlist *l,int n)
{
	l->date=(Type*)malloc(n*sizeof(Type));
	l->size=0;
	l->max=n;
}
void FreeList(Seqlist *l)
{
	free(l->date);
}
void InsertRear(Seqlist *l,Type item)
{
	if (l->size==l->max)
	{
		printf("list is full!\n");
		exit(1);
	}
	l->date[l->size]=item;
	l->size++;
}
void Insert(Seqlist *l,int id,Type item)
{
	int i;
	if(l->size==l->max||id<0||id>l->size)
	{
		printf("list is full or id is illegal!\n");
		exit(1);
	}
	for (i=l->size-1;i>=id;--i)
	{
		l->date[i+1]=l->date[i];
	}
	l->date[id]=item;
	l->size++;
}
void Erase(Seqlist *l,int id)
{
	int i;
	if (id<0||id>l->size-1)
	{
		printf("list is empty or id is illegal!\n");
		exit(1);
	}
	for (i=id+1;i<l->size;++i)
	{
		l->date[i-1]-l->date[i];
	}
	l->size--;
}
void Clear(Seqlist *l)
{
	l->size=0;
}
Type Getdate(const Seqlist *l,int id)
{
	if (id<0||id>l->size-1)
	{
		printf("list is empty or id is illegal!\n");
		exit(1);
	}
	return l->date[id];
}
int Size(const Seqlist *l)
{
	return l->size;
}

5. 鏈表練習

問題描述:編程使用鏈表對數組進行一些基本操作

//Test.c(主函數)
typedef int Type;
#include<stdio.h>
#include"List.h"
void display_list(Node *first,Node *last);
int main()
{
	int i,item;
	Node *current;
	List L;
	Init(&L);
	printf("input 10 integers:\n");
	for(i=0;i<10;++i)
	{
		scanf("%d",&item);
		Push_back(&L,item);
	}
	current=Begin(&L);
	current=Get_next(current);
	printf("the second:\n");
	printf("%d\n",Get_date(current));
	current=Get_prev(current);
	printf("the first :\n");
	printf("%d\n",Get_date(current));
	Erase(&L,current);
	printf("after erasing the first:\n");
	display_list(Begin(&L),End(&L));
	Pop_back(&L);
	printf("after erasing the last:\n");
	display_list(Begin(&L),End(&L));
	printf("the first and the last:\n");
	printf("%d\n",Front_date(&L));
	printf("%d\n",Back_date(&L));
	printf("update the first and the last:\n");
	*Front_pointer(&L)=100;
	*Back_pointer(&L)=200;
	display_list(Begin(&L),End(&L));
	Free(&L);
	return 0;
}
void display_list(Node *first,Node *last)
{
	for(;first!=last;first=Get_next(first))
		printf("%d\t",Get_date(first));
	printf("\n");
}
//Node.h(結點聲明)
#ifndef NODE_H
#define NODE_H
typedef int Type;
struct Node
{
	Type date;
	struct Node *prev;
	struct Node *next;
};
typedef struct Node Node;
Node *Get_node(Type item,Node *prev0,Node *next0);
Type Get_date(Node *current);
Node *Get_next(Node *current);
Node *Get_prev(Node *current);
void Set_date(Node *current,Type item);
#endif
//Node.c(結點實現)
#include"Node.h"
#include<stdio.h>
Type Get_date(Node *current)
{
	return current->date;
}
Node *Get_next(Node *current)
{
	return current->next;
}
Node *Get_prev(Node *current)
{
	return current->prev;
}
Node *Get_node(Type item,Node *prev0,Node *next0)
{
	Node *p;
	p=(Node*)malloc(sizeof(Node));
	if(p==NULL)
	{
		printf("Memory allocation failure!");
		exit(1);
	}
	p->date=item;
	p->prev=prev0;
	p->next=next0;
	return p;
}
void Set_date(Node *current,Type item)
{
	current->date=item;
}
//List.h(鏈表聲明)
#ifndef LIST_H
#define LIST_H
#include"Node.h"
typedef struct
{	
	Node *head;
	Node *tail;
	int size;
}List;
void Init(List *L);
Node *Begin(List *L);
Node *End(List *L);
Node *Insert(List *L,Node *current,Type item);
Node *Erase(List *L,Node *current);
Type *Front_pointer(List *L);
Type Front_date(List *L);
Type *Back_pointer(List *L);
Type Back_date(List *L);
void Push_front(List *L,Type item);
void Push_back(List *L,Type item);
void Pop_front(List *L);
void Pop_back(List *L);
int Empty(List *L);
void Clear(List *L);
void Free(List *L);
#endif
//List.c(鏈表實現)
#include"List.h"
#include<stdio.h>
void Init(List *L)
{
	L->head=(Node*)malloc(sizeof(Node));
	if(L->head==NULL)
	{
		printf("Memory allocation failure!");
		exit(1);
	}
	L->head->next=L->head->prev=NULL;
	L->tail=(Node*)malloc(sizeof(Node));
	if(L->tail==NULL)
	{
		printf("Memory allocation failure!");
		exit(1);
	}
	L->tail->next=L->tail->prev=NULL;
	L->head->next=L->tail;
	L->tail->prev=L->head;
	L->size=0;
}
Node *Begin(List *L)
{
	return L->head->next;
}
Node *End(List *L)
{
	return L->tail;
}
Node *Insert(List *L,Node *current,Type item)
{
	Node *p=current;
	L->size++;
	p->prev->next=Get_node(item,p->prev,p);
	p->prev=p->prev->next;
	return p->prev;
}
Node *Erase(List *L,Node *current)
{
	Node *p=current;
	Node *re=p->next;
	p->prev->next=p->next;
	p->next->prev=p->prev;
	free(p);
	L->size--;
	return re;
}
Type *Front_pointer(List *L)
{
	Node *current=L->head->next;
	return &(current->date);
}
Type Front_date(List *L)
{
    Node *current=L->head->next;
    return current->date;
}
Type *Back_pointer(List *L)
{
	Node *current=L->tail->prev;
	return &(current->date);
}
Type Back_date(List *L)
{
    Node *current=L->tail->prev;
    return current->date;
}
void Push_front(List *L,Type item)
{
	Insert(L,Begin(L),item);
}
void Push_back(List *L,Type item)
{
	Insert(L,End(L),item);
}
void Pop_front(List *L)
{
	Erase(L,Begin(L));
}
void Pop_back(List *L)
{
	Erase(L,Get_prev(End(L)));
}
int Empty(List *L)
{
	return L->size==0;
}
void Clear(List *L)
{
	while(!Empty(L))
		Pop_front(L);
	L->size=0;
}
void Free(List *L)
{
	Clear(L);
	free(L->head);
	free(L->tail); }

結語

《C語言學習基礎程序》僅爲博主在學習C語言時自己的記錄與積累,加上後期的整理所成。可能對於C語言入門的理解與初步掌握有一定的幫助。
當然,介於當時的水平有限,文章本身可能還存在內容上的紕漏或者錯誤,如果讀者在閱讀中發現錯誤,也請不吝指出,謝謝!

注:《C語言學習基礎程序》會放在附件中,感興趣的小夥伴歡迎下載嗷~
下載鏈接: C語言學習基礎程序——Mr.鵬

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章