C语言学习(根据浙大翁恺老师课程学习整理)

本篇收纳mooc浙大翁恺老师个人认为比较有意义可提升的课堂代码(相同类型题以难易程度排列在一起):

目录

1.让计算机来想一个数,然后让用户来猜,用户没输入一个数,就告诉它大了还是小了,直到用户猜中为止,最后还要告诉用户它猜了多少次。

2.平均数相关问题【输出输入数字个数、平均数,以及大于平均数的数(数组),超过100个数的处理方式(数组)】

3.整数分解【逆序和正序输出】

4.素数相关问题(素数:只能被1和自己整除,不包括1)【判断是否为素数/输出100以内素数/输出50个素数/函数判断是否为素数/求n个素数(数组)/构造n以内素数表(数组)】

5.求最大公因数(公约数)【枚举法和辗转相除法】

6.输入数量不确定的[0,9]范围内的整数,统计每一种数字出现的次数,输入-1表示结束。

7.搜索硬币数值对应的英文单词【两个数组方发/结构体方法】

8.二分搜索(搜索次数x=logN)

9.选择排序

10.指针基础

11.字符串函数的数组与指针方法实现【strlen函数/strcmp函数/strcpy函数/strcat函数/strchr函数】

12.自主创建一个可变数组(创建、回收、返回数组大小、访问数值、扩展数组大小)

13.自主创建一个链表(添加数据、输出数据、查找数据、删除数据、清除链表)

14.输出一个数的二进制(按位与移位运算)


1.让计算机来想一个数,然后让用户来猜,用户没输入一个数,就告诉它大了还是小了,直到用户猜中为止,最后还要告诉用户它猜了多少次。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
	srand(time(0));
	//rand()生成随机整数 ,%100获取0-99的数
	int num = rand()%100+1;  //随机数 (1-100) 
	int count = 0;  //用户猜的次数 
	int a = 0;  //用户猜的数 
	printf("我已经想好了一个1-100之间的数。\n"); 
	
	do{
		printf("请输入一个1-100之间的数:"); 
		scanf("%d",&a);
		if(num < a)
		{
			printf("猜大了!\n");
		}
		else if(num > a)
		{
			printf("猜小了!\n");
		}
		count++; 
	}while(a != num);
	printf("恭喜!本次猜数用了%d次获得正确答案!\n",count);
    return 0;
}

提问:为什么用户最多7次就能猜出来?

解答:通过二分法可知,每次猜一半,至多7次得到结果。原理是因为2的7次方是128,也就是说,100对半分7次小于1,所以必得到唯一的整数。

2.平均数相关问题【输出输入数字个数、平均数,以及大于平均数的数(数组),超过100个数的处理方式(数组)】

(1)用户输入一系列的正整数,最后输入-1表示输入结束,然后计算出这些数字的平均数,输出输入的数字个数和平均数。

#include <stdio.h>

int main()
{
	int number;
	double sum = 0;
	int count = 0;
	
	scanf("%d",&number);
	while(number != -1)
	{
		sum += number;  //累加输入数字
		count++;  //记录输入数字个数
		scanf("%d",&number);	
	} 

	printf("%f",sum/count);
    return 0;
}

(2)计算用户输入的数字的平均数,并输出所有大于平均数的数。【数组】

#include <stdio.h>

int main()
{
	//定义数组 
	int number[100];
	double sum = 0;
	int count = 0;
	int x;
	
	scanf("%d",&x);
	while(x != -1)
	{
		//对数组中的元素赋值 
		number[count] = x;
		sum += x;
		count++;
		scanf("%d",&x);	
	} 
	
	if(count > 0)
	{
		double average = sum / count;  //平均数 
		int i;
		for(i = 0;i < count;i++)
		{
			if(number[i] > average)  //输出大于平均数的数 
			{
				printf("%d\n",number[i]);
			}
		}
	} 
	return 0;
}

输入超过100个数怎么办?

1)计数,读满100个数即停止输入。

2)利用C99的特性,动态定义数组大小。即让用户输入有多少数字需要计算。

#include <stdio.h>

int main()
{
	double sum = 0;
	int count = 0;
	int x;
	
	printf("请输入数字的数量:"); 
	scanf("%d",&count);
	if(count > 0)
	{
		//定义数组 
		int number[count];
		int i;
		// while(x != -1)
		for(i = 0;i < count;i++)
		{
            scanf("%d",&x);
			//对数组中的元素赋值 
			number[i] = x;
			sum += x;
		} 
		
		double average = sum / count;  //平均数 
        int j;
		for(j = 0;j < count;j++)
		{
			if(number[j] > average)  //输出大于平均数的数 
			{
				printf("%d\n",number[j]);
			}
		}
	} 
	return 0;
}

3.整数分解【逆序和正序输出】

(1)逆序输出一个数

#include <stdio.h>

int main()
{
	int num;  //需要逆序的数 
	int digit;  //分解的数 
	int ret;  //逆序的数 
	
	scanf("%d",&num);
	do{
		digit = num % 10;  //输出最后一位	
		ret = ret*10 + digit;  //逆序输出 
		num /= 10;  //消除最后一位 
	}while(num>0);
	
	printf("%d",ret);
    return 0;
}

(2)正序分别空格输出(注意需要保留0)

#include <stdio.h>

int main()
{
	int num;  //需要分解的数 
	int digit;  //分解的数 
	
	scanf("%d",&num);
	int mask = 1;  //记录最高位数 
	int t = num;
	while(t > 9)
	{
		t /= 10;
		mask *= 10;
	} 
	
	do{
		digit = num / mask;  //输出第一位
		printf("%d",digit);
		if(mask > 9)
		{
			printf(" ");
		} 
		num %= mask;  //消除第一位 
		mask /= 10;  //减少mask的位数 
	}while(mask>0);
    return 0;
}

4.素数相关问题(素数:只能被1和自己整除,不包括1)【判断是否为素数/输出100以内素数/输出50个素数/函数判断是否为素数/求n个素数(数组)/构造n以内素数表(数组)】

(1)判断一个数是否是素数

#include <stdio.h>

int main()
{
	int x;  //任意整数 
	
	scanf("%d",&x);
	int isPrime = 1; //x是素数
	int i;  //“for”循环初始声明仅在 C99 模式下允许,故这里需要提前声明 
	for(i = 2;i < x;i++)  //int i = 2 [Error] 'for' loop initial declarations are only allowed in C99 mode 
	{
		if(x % i == 0)
		{
			isPrime = 0;
			break;
		}
	}
	
	if(isPrime == 1)
	{
		printf("%d是素数",x); 
	}
	else
	{
		printf("%d不是素数",x); 
	 } 
	return 0;
}

(2)输出100以内的素数

#include <stdio.h>

int main()
{
	int x; //“for”循环初始声明仅在 C99 模式下允许,故这里需要提前声明 
	for(x = 2;x < 100;x++)//int  x= 2 [Error] 'for' loop initial declarations are only allowed in C99 mode 
	{
		int isPrime = 1;  //是素数 
		int i;
		for(i = 2;i < x;i++)  
		{
			if(x % i == 0)
			{
				isPrime = 0; 
				break;
			}
		}
		if(isPrime == 1)
		{
			printf("%d ",x);
		}
	}
    return 0;
}

(3)输出50个素数

#include <stdio.h>

int main()
{
	int cnt = 0;  //记录素数个数 
	int x = 2; //“for”循环初始声明仅在 C99 模式下允许,故这里需要提前声明 
	//for(x = 2;cnt < 50;x++)//int  x= 2 [Error] 'for' loop initial declarations are only allowed in C99 mode 
	while(cnt < 50) 
	{
		int isPrime = 1;  //是素数 
		int i;
		for(i = 2;i < x;i++)  
		{
			if(x % i == 0)
			{
				isPrime = 0; 
				break;
			}
		}
		if(isPrime == 1)
		{
			printf("%d ",x);
			cnt++; 
		}
		x++;
	}
    return 0;
}

(4)函数方法判断是否是素数(且简化循环次数)

#include <stdio.h>
#include <math.h>

int isPrime(int x) ;

int main(void)
{
	int x;  //任意整数 
	
	scanf("%d",&x);
	if(isPrime(x))
	{
		printf("%d是素数",x); 
	}
	else
	{
		printf("%d不是素数",x); 
	 } 
	return 0;
}

int isPrime(int x)
{
	int ret = 1; //x是素数
	int i;  //“for”循环初始声明仅在 C99 模式下允许,故这里需要提前声明 
	if(x == 1||x % 2 == 0&&x != 2) ret = 0;  //排除1和2的倍数是素数 
	for(i = 3;i < sqrt(x);i += 2)  //int i = 2 [Error] 'for' loop initial declarations are only allowed in C99 mode 
	{
		if(x % i == 0)
		{
			ret = 0;
			break;
		}
	}
	return ret;
}

(5)数组方法:通过判断是否能被已知的且<x的素数整除,求出number(100)个的素数

#include <stdio.h>

int isPrime(int x,int knownPrimes[],int numberOfKnownPrimes);

int main(void)
{
	const int number = 100;  
    // 只有c99能用number,否则直接写100 
	int prime[number] = {2};  //素数第一个数初始化为2
	int count = 1;  //素数表中已经存在一个2
	int i = 3;
	while(count < number) //循环创造一个素数表 (100个素数) 
	{
		if(isPrime(i,prime,count))  //是素数 
		{
			prime[count++] = i;
		}
		i++;
	 } 
	 for(i = 0;i < number;i++)  //输出 
	 {
	 	printf("%d",prime[i]);
	 	if((i+1)%5) printf("\t");  //每排五个数,否则换行 
	 	else printf("\n");
	  } 
	return 0;
}

//循环仅到当前数最大素数,只判断当前数是否能除尽素数,极大减少了循环次数 
int isPrime(int x,int knownPrimes[],int numberOfKnownPrimes)
{
	int ret = 1; //x是素数
	int i;  //“for”循环初始声明仅在 C99 模式下允许,故这里需要提前声明 

	for(i = 0;i < numberOfKnownPrimes;i++)  //int i = 2 [Error] 'for' loop initial declarations are only allowed in C99 mode 
	{
		if(x % knownPrimes[i] == 0)
		{
			ret = 0;
			break;
		}
	}
	return ret;
}

(6)数组方法:构造n(25)以内的素数表

        1)令x为2

        2)将2x,3x,4x直至ax<n的数标记为非素数

        3)令x为下一个没有被标记为非素数的数,重复2);直至所有数标记完毕

#include <stdio.h>

int main(void)
{
	const int maxNumber = 25;   
	int isPrime[maxNumber];
	int x; 
	int i;
	for(i = 0;i < maxNumber;i++) //初始化,即prime[x]为1表示x是素数 
	{
		isPrime[i] = 1;
	 } 
	for(x = 2;x < maxNumber;x++) //从2开始,构造n以内的素数表 
	{
		if(isPrime[x])  //x是素数 
		{
			for(i = 2;i*x < maxNumber;i++) //则x的倍数不是素数 
			{
				isPrime[i*x] = 0;
			}
		}
	 } 
	for(i = 2;i < maxNumber;i++)  //输出素数 
	 {
	 	if(isPrime[i])
	 	{
	 		printf("%d\t",i);		
		 }
	 } 
	 printf("\n");
	return 0;
}

5.求最大公因数(公约数)【枚举法和辗转相除法】

(1)枚举法

#include <stdio.h>

int main()
{
	int a,b;
	int min;  //比较并记录a和b大小 
	
	scanf("%d %d",&a,&b);
	if(a < b)
	{
		min = a;
	}
	else
	{
		min = b;
	}
	
	int ret = 0;//记录公因数 
	int i; 
    //for(i = min;i > 0;i--)  //方法二:倒着记录公因数,第一次得到的公因数即为最大,即后面还需要用到break;
	for(i = 1;i < min;i++)  //方法一:正序记录公因数,最后一个得到的公因数为最大
    {
		if(a % i == 0)
		{
			if(b % i == 0)
			{
				ret = i;
				//break;  //得到第一个公因数:正序可得到最小公因数,倒序可得到最大公因数
			}
		}
	}
	printf("%d和%d的最大公因数是:%d",a,b,ret); 
    return 0;
}

(2)辗转相除法

两个数a和b。如果b=0,计算结束,a就是最大公因数;否则,计算a%b的余数t,然后让a=b,b=余数t,回到第一步。

#include <stdio.h>

int main()
{
	int x,y;
	int t;  
	
	scanf("%d %d",&x,&y);
	//重新赋值,避免之后运算改变原数 
	int a = x;
	int b = y;
	while(b != 0)
	{
		t = a % b;
		a = b;
		b = t;
	}
	printf("%d和%d的最大公因数是:%d",x,y,a); 
    return 0;
}

6.输入数量不确定的[0,9]范围内的整数,统计每一种数字出现的次数,输入-1表示结束。
#include <stdio.h>

int main()
{
	//记录数组大小 
	const int number = 10;
	int x;
	int i;
    //定义数组
	int count[number];//记录每个数出现次数 
	
	//初始化数组 
	for(i=0;i<number;i++)
	{
		count[i] = 0;
	}
	
	scanf("%d",&x);
	while(x != -1)
	{
		if(x >= 0 && x <= 9)
		{
            //数组参与运算
			count[x]++;  //出现次数+1 
		 } 
		 scanf("%d",&x);
	} 

    //遍历数组输出
	for(i = 0;i < number;i++)
	{
		printf("%d:%d\n",i,count[i]);
	}
	return 0;
}

7.搜索硬币数值对应的英文单词【两个数组方发/结构体方法】

(1)两个数组(不推荐,将关系割裂了)

#include <stdio.h>

int amount[] = {1,5,10,25,50};
char *name[] = {"penny","nickel","dime","quarter","half-dollar"}; 

int search(int key,int a[],int len)
{
	int ret = -1;
	int i;
	for(i = 0;i < len;i++)
	{
		if(key == a[i])  //查到数组内存在该价值硬币,返回数组索引号
		{
			ret = i;
			break;
		}
	}
	return ret;
}

int main(void)
{
	int k = 10;  //查找的数
	int r = search(k,amount,sizeof(amount)/sizeof(amount[0]));
	if(r > -1)
	{
		printf("%s\n",name[r]);  //输出对应数组里存储的英文单词
	 } 
	return 0;
}

(2)结构体

#include <stdio.h>

//int amount[] = {1,5,10,25,50};
//char *name[] = {"penny","nickel","dime","quarter","half-dollar"}; 

struct{
	int amount;
	char *name;
}coins[] = {
	{1,"penny"},
	{5,"nickel"},
	{10,"dime"},
	{25,"quarter"},
	{50,"half-dollar"},
};

int main(void)
{
	int k = 10;  //查找的数
	int len = sizeof(coins)/sizeof(coins[0]);
	int i;
	for(i = 0;i < len;i++)
	{
		if(k == coins[i].amount)
		{
			printf("%s\n",coins[i].name);
			break;
		}
	}
	return 0;
}

8.二分搜索(搜索次数x=logN)
#include <stdio.h>

int search(int key,int a[],int len)
{
	int ret = -1;
	int left = 0;  //数组最左端 
	int right = len-1;  //数组最右端 
	while(right > left)
	{
		int mid = (left+right)/2;  //数组最中间
		if(a[mid] == key)
		{
			ret = mid;  //找到了 
			break;
		 } 
		 else if(a[mid] > key)  //中间数大于key, 即key在左端 
		 {
		 	right = mid - 1; 
		  } 
		  else
		  {
		  	left = mid + 1; 
		  } 
	}
	return ret;
}

int main(void)
{
	int k = 15;
	int a[] = {1,2,5,6,7,7,10,15,18,20};
	int len = sizeof(a)/sizeof(a[0]);
	int r = search(k,a,len); 
	if(r > -1)
	{
		printf("%d",r);
	}
	return 0;
}

9.选择排序
#include <stdio.h>

int max(int a[],int len)  //返回最大数的索引值 
{
	int maxid = 0;
	int i;
	for(i = 1;i < len;i++)
	{
		if(a[i] > a[maxid])
		{
			maxid = i;	
		}	
	}
	return maxid;	
} 

int main(void)
{
	int a[] = {2,45,6,12,14,7,1,10,90,24,86};
	int len = sizeof(a)/sizeof(a[0]);
	int i;
	
	for(i = 0;i < len;i++)  //遍历看初始数组 
	{
		printf("%d ",a[i]);
	 } 
	printf("\n"); 
	
	//选择排序 
	for(i = len-1;i > 0;i--)
	{
		int maxid = max(a,i+1);  //选择出最大的数的索引值 
		//最大数与最末尾的数交换 
		int t = a[maxid] ;  //中间数 
		a[maxid] = a[i];   //最大数索引位置的数与最末尾的数交换 
		a[i] = t;  //最末尾的数为最大数 
	}
	
	for(i = 0;i < len;i++)  //遍历看是否排序成功 
	{
		printf("%d ",a[i]);
	 } 
	return 0;
}

10.指针基础
#include<stdio.h>

int main(int argc,char const *argv[])
{
	int i = 520;
	int *p = &i;
	int q = *p;
	
	//i 
	printf("i=%d\n",i); 
	printf("&i=%d\n",&i);
	printf("sizeof(i)=%d\n",sizeof(i));
	
	printf("\n"); 
	
	//p左值
	printf("p=%d\n",p); 
	printf("&p=%d\n",&p);
	printf("sizeof(p)=%d\n",sizeof(p));
	
	printf("\n");
	
	//*p左值
	printf("*p=%d\n",*p);
	printf("&(*p)=%d\n",&(*p)); 
	
	printf("\n");
	
	//q
	printf("q=%d\n",q);
	printf("&q=%d\n",&q);
	
	/*输出: 
	i=520
	&i=6487580
	sizeof(i)=4
	
	p=6487580
	&p=6487568
	sizeof(p)=8
	
	*p=520
	&(*p)=6487580
	
	q=520
	&q=6487564
	
	得出结论,值q=*p=i ;地址&(*p)=p=&i ; i数据类型为int ; p数据类型为int* 
	*/ 
	return 0;
}

11.字符串函数的数组与指针方法实现【strlen函数/strcmp函数/strcpy函数/strcat函数/strchr函数】

(1)strlen的实现(返回字符串长度,不包括结尾的\0)

#include <stdio.h>
#include <string.h>

size_t myStrlen(const char *s)
{
    int idx = 0;
    while(s[idx] != '\0')
    {
    	idx++;
	}
	return idx;
}
int main(int argc,char const *argv[])
{
	char line[] = "hello";
	printf("strlen=%lu",myStrlen(line));  //输出:strlen=5 
	return 0;
}
        

(2)strcmp函数的实现(比较两个字符串大小,返回前-后差值)

        1)数组方式

#include <stdio.h>
#include <string.h>

int myStrcmp(const char *s1,const char *s2)  //两个数只读,仅用来比较大小 
{
    int idx = 0;
    while(s1[idx] == s2[idx] &&s1[idx] != '\0')
    {
    	idx++;
	}
	return s1[idx] - s2[idx];
}
int main(int argc,char const *argv[])
{
	char s1[] = "hello";
	char s2[] = "Hello";
	printf("strcmp=%d",myStrcmp(s1,s2));  //输出:strcmp=32
	return 0;
}

        2)指针方式

#include <stdio.h>
#include <string.h>

int myStrcmp(const char *s1,const char *s2)  //两个数只读,仅用来比较大小
{
    int idx = 0;
    while(*s1 == *s2 &&*s1 != '\0')
    {
    	s1++;
    	s2++;
	}
	return *s1 - *s2;
}
int main(int argc,char const *argv[])
{
	char s1[] = "hello";
	char s2[] = "Hello";
	printf("strcmp=%d",myStrcmp(s1,s2));  //输出:strcmp=32
	return 0;
}

(3)strcpy函数的实现(把src的字符串拷贝到dst,第一项是目的变量,第二项是源变量)

        1)数组形式

#include <stdio.h>
#include <string.h>

char* myStrcpy(char *dst,const char *src) //第一项需要写,第二项只读 
{
    int idx = 0;
    while(dst[idx] = src[idx])
    {
    	idx++;
	}
	dst[idx] = '\0';
	return dst;
}
int main(int argc,char const *argv[])
{
	char s1[] = "hello";
	char s2[] = "Hello";
	printf("strcpy=%s",myStrcpy(s1,s2));  //输出:strcpy=Hello
	return 0;
}

        2)指针形式

#include <stdio.h>
#include <string.h>

char* myStrcpy(char *dst,const char *src) //第一项需要写,第二项只读 
{
    char* ret = dst;  //记录最初的地址
	while(*dst++ = *src++) ;  //先比较是否相等,后指向下一单元。循环空语句。
	*dst = '\0'; 
	return ret;  //返回最初的地址 
}
int main(int argc,char const *argv[])
{
	char s1[] = "hello";
	char s2[] = "Hello";
	printf("strcpy=%s",myStrcpy(s1,s2));  //输出:strcpy=Hello
	return 0;
}

(4)strcat函数的实现(将s2拷贝到s1的后面,连接成一个长的字符串)

#include<stdio.h>
#include<string.h>

char* mycat(char *s1, const char *s2)  //第一项可写,第二项只读,c99可加restrict(表示两数不重叠) 
{
	char *p=strchr(s1,'\0');  //指向s1的'\0',即s1=s1+p
	strcpy(p,s2);  //将s2赋值给p,即s1=s1+s2 
	return s1;
 } 

int main(int argc,char const *argv[])
{
	char s1[]="hello";
	char s2[]="Hello";
	mycat(s1,s2);
	printf("%s\n",s1);
	return 0;
}

(5)字符搜索函数strchr(从左寻找单字符)/strsrt(字符串)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc,char const *argv[])
{
	char s[] = "hello";
	char *p = strchr(s,'l');  //指向了s中的‘l’,相当于*p = s[2](个人理解) 
	printf("strchr1=%s\n",p);  //输出:strchr1=llo
	
	//查找第二次
	p = strchr(p+1,'l');  //p[1] = s[3](个人理解) 
	printf("strchr2=%s\n",p);  //输出:strchr2=lo
	
	//只保留前部分
	char c = *p;  //c为'l' 
	printf("c=%c\n",c);  //c=l
	*p = '\0';  //置空:*p[0]='\0'
	printf("p[1]=%c\n",p[1]); //p[1]=0 
	char *t = (char*)malloc(strlen(s)+1);   //动态分配空间 
	strcpy(t,s);  //将s的前部分复制给t,读取到'\0'(p[0])为止,所以读不到p[1] 
	printf("t=%s\n",t);  //输出:t=hel 
	printf("p=%s\n",p);  //输出:p= 
	printf("s=%s\n",s);  //输出:s=hel 
	free(t);  //释放动态分配空间 
	
	//还原s
	*p = c;
	printf("p=%s\n",p);  //输出:p=lo 
	printf("s=%s\n",s);  //输出:s=hello 
	  
	return 0;
}

12.自主创建一个可变数组(创建、回收、返回数组大小、访问数值、扩展数组大小)
#include <stdio.h>
#include <stdlib.h>

const BLOCK_SIZE =  20;  //越界后一次性开辟的数组空间 

typedef struct{   
	int *array;  //数组 
	int size;  //大小 
}Array;  //该结构体另命名为Array
/*不*Array的缺点:
	1)后面虽然不用*了,但是会让人看不出是指针 
	2)本地变量不能使用Array a; 
*/ 

//创建数组 
Array array_create(int init_size){
	Array a;
	a.size = init_size;
	a.array = (int*)malloc(sizeof(int)*a.size);
	return a;
} 

//回收数组 
Array array_free(Array *a){
	free(a->array);
	a->array = NULL;
	a->size = 0;
} 

//返回数组大小(封装)
int array_size(const Array *a){
	return a->size;
}  

//访问数组
int* array_at(Array *a,int index){
	//数组越界,还需考虑小于0的情况 
	if(index >= a->size){
//		开拓内存大小刚好的数组,可以但没必要,越界了还是多给点空间吧~ 
//		array_inflate(a,index - a->size + 1);
		array_inflate(a,(index/BLOCK_SIZE + 1) * BLOCK_SIZE - a->size + 1);  
	} 
	return &(a->array[index]);  //返回一个指针 
} 

int array_get(const Array *a,int index){
	return a->array[index]; 
}

void array_set(Array *a,int index,int value){
	a->array[index] = value;
}

//扩大数组 
void array_inflate(Array *a,int more_size){
	int *p = (int*)malloc(sizeof(int) * (a->size + more_size));
	//复制旧东西,可以换成memcpy 
	memcpy((void*)p,(void*)a->array,a->size * sizeof(int));
//	for(int i = 0;i < a->size;i++) {
//		p[i] = a->array[i];
//	}
	free(a->array);
	a->array = p;
	a->size += more_size;
}

int main(int argc,char const *argv[])
{
	Array a = array_create(100);  //创建大小为100的数组 
	//(不返回指针的优点:本地变量a用的是array_create()中制作的结构初始化,且*会很复杂 
	printf("%d\n",array_size(&a));  //输出数组大小
	
	printf("%d\n",*array_at(&a,0));
	*array_at(&a,0) = 10;  //直接改变0位置的数组值
	printf("%d\n",*array_at(&a,0));  //访问索引为0位置的数组值 
	
	int number = 0;
	int cnt = 0;
	while(1){
		scanf("%d",&number);
		if(number != -1){
			*array_at(&a,cnt++) = number;
		}
//		scanf("%d",array_at(&a,cnt++));   //不断访问数组并赋值 
	}
	
	array_free(&a);  //回收数组 
	  
	return 0;
}

可变数组的缺陷:

1)拷贝需要时间

2)内存受限:在已申请的内存(a)后方再申请,新内存(a+block)前面的内存已回收但无法使用

13.自主创建一个链表(添加数据、输出数据、查找数据、删除数据、清除链表)

比起可变数组的优点:

1)避免拷贝,节约时间

2)旧内存(已申请内存a)直接链向新内存(扩展内存block),充分利用空间

#include <stdio.h>
#include <stdlib.h>
#ifndef _NODE_H_
#define _NODE_H_

typedef struct _node{   
	int value;
	struct _node *next;  //指针,指向下一个;别名还没定义所以还不能使用 
}Node;

typedef struct _list{
	Node *head;
//	Node *tail;
}List;

#endif

//void add(Node *head,int number); 
//Node *add(Node** pHead,int number);
void add(List *pList,int number);
void print(List *pList);
void removed(List *pList);
void clear(List *pList);

int main(int argc,char const *argv[])
{
//	Node *head = NULL;
	List list;   
	list.head = NULL;
//	list.tail = NULL;

	//遍历链表的值 
	print(&list);
	
	int number;
	do{
		scanf("%d",&number);
		if(number != -1){
			/*list.head = */add(&list,number);
		}
	}while(number != -1);
	  
	//遍历链表的值 
	print(&list); 
	
	//找到数值
	scanf("%d",&number); 
	Node *p;
	int isFound = 0;
	for(p = list.head;p;p = p->next){
		if(p->value == number){
			printf("找到啦\n");
			isFound = 1;
			break;
		}
	}
	if(!isFound){
		printf("没找到\n");
	}
	
	//删除数值(单向链表: p前面数值找到后面数值,然后free(p) 
	//可分别根据指针、数值删除 
	removed(&list);
	print(&list);
	
	//清除链表
 	clear(&list);
 	print(&list);
	
	return 0;
}

void add(List *pList,int number){
		//add to linked-list
		//初始化 
		Node *p = (Node*)malloc(sizeof(Node));
		p->value = number;
		p->next = NULL;	//新的数据的指针指向下一个为NULL 
		//find the last
		Node *last = pList->head;
		if(last){
			while(last->next){
				last = last->next;
			} 
			//attach链接上 
			last->next = p;
		}else{
			pList->head = p;  //head指向的是NULL	
		}
}

void print(List *pList){
	Node *p;
	for(p = pList->head;p;p = p->next){
		printf("%d\t",p->value);
	}
	printf("\n");
}

void removed(List *pList){
	int number;
	scanf("%d",&number); 
	Node *p;
	Node *q;
	for(q= NULL,p = pList->head;p;q=p,p = p->next){
		if(p->value == number){  //指针p出现在左边,必须判断是否NULL 
			if(q){
				q->next = p->next;	
			}else{
				pList->head = p->next;
			}
			free(p);
			break;
		}
	}
}

void clear(List *pList){
	Node *p;
	Node *q; 
	//方法1:根本没清除!不知道哪里错了 
//	for(p = pList->head;p;p = q){
//		q = p->next;
//		free(p);
//	}
 
	//方法2 
	if(pList->head->next){
		clear(pList->head->next);
	}
	free(pList->head);
}

14.输出一个数的二进制(按位与移位运算)
#include <stdio.h>

int main(int argc,char const *argv[])
{
	int number;
	scanf("%d",&number);
	unsigned mask = 1u<<31;  //左移作为最大的一个32位的int(10000...000) 
	for(;mask;mask>>=1){  //每次循环右移一位 
//		printf("%d:",number & mask);  两数相比:输出与mask为1位所对应的整数 
		//由于同1输出1,用不同位的1逐一与number对比,>0即输出1,最后可得出number的二进制数 
		printf("%d\n",number & mask ? 1:0);  
	}
	return 0;
}
  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值