C语言重点笔记


————— ꧁༺ ♕ ༻꧂ —————


前言


本文是我在大学学习C语言程序设计时学到的一些重点的内容,其中主要包括递归函数、数组、指针、字符串等。我将其重新梳理并且用Markdown排版了出来,除此之外我还附加一些我自己的感想以及对代码的注释,仅是个人愚见若有错误请不吝赐教。如需转载请标明出处。




————— ꧁༺ ♕ ༻꧂ —————




函数




递归函数


准备以后写,先留着



————— ꧁༺ ♕ ༻꧂ —————




数组




一维数组的定义

cint a[10];//注意int
1.数组大小必须是值为正的常量,不能为变量,一旦定义,不能改变大小
2.大小最好用宏定义,以适应未来的变化

#define N 10
int a[N];
一维数组的初始化
  int a[5] = { 12, 34, 56, 78, 9 };
  int a[5] = { 0 };//全是0.
  int a[5] = { 1 };//a[0]=1,其余全是0.
  int a[] = { 11, 22, 33, 44, 55 };

更高效的数组初始化方法

memset(a, 0, sizeof(a));    

sizeof(a)来获得数组a所占的内存字节数
需要包含相应的头文件:
#include <string.h>

一维数组间的相互赋值

1.逐个元素赋值

    b[0]=a[0];
    b[1]=a[1];
    b[2]=a[2];
    b[3]=a[3];

2.通过循环语句赋值

    int i;
    for (i=0;i<4;i++)
    {
        b[i] = a[i];
    }

3.更高效的数组赋值方法
memcpy(b, a, sizeof(a));//把从a开始的内存拷贝到从b开始的地址中去
需要包含相应的头文件:
#include <string.h>

二维数组的定义

二维数组 int b[2][3];

二维数组的初始化
int a[][3]={{1,2,3},{4,5},{6},{0}};
向函数传递一维数组

1.在函数声明时函数里面第一个参数是数组首地址,第二个参数是数组元素的个数。
2.在函数声明的时函数里面第一个参数必须加方括号,但是在函数调用的时函数里面第一个参数一定不要加方括号。
要背过的经典程序
1.计算最高分
注意return只能返回一个值。

int FindMax(int score[],int n)//注意加int[]
{
   int max,i;
   max=score[0];
   for(i=1;i<n;i++)
    {
     if (score[i]>max)
       {
          max=score[i];
       }
    }
	return max;//记得返回最大值。
}
交换法排序

直接背程序
用交换法对成绩降序排序

void DataSort(int score[], int n) /*交换法排序*/
{
	int i, j, temp;
	for (i=0; i<n-1; i++)//口诀:i是0到n-1,j是i+1到n。
	{
		for (j=i+1; j<n; j++) //口诀:i是0到n-1,j是i+1到n。
		{
		    if (score[j] > score[i]) /*从高到低*/
		    {
			 temp = score[j];//口诀:2给空,1给2,空给1
			 score[j] = score[i];
			 score[i] = temp;
		    }
		}
	}
}
选择法排序

直接背程序
用选择法对成绩降序排序

void DataSort(int score[], long num[], int n) /*选择法*/
{
    int i, j, k, temp1;
    long temp2;//单独定义temp2.
    for (i=0; i<n-1; i++)
    {
        k = i;//保存下标
        for (j=i+1; j<n; j++)      
        {
            if (score[j] > score[k]) 
            {
                k = j;    /*记录最大数下标位置*/
            }
        }
        if (k != i)       /*若最大数不在下标位置i*/
        {    
	        temp1 = score[k]; 
            score[k] = score[i]; 
	        score[i] = temp1; 
            temp2 = num[k]; 
            num[k] = num[i]; 
            num[i] = temp2;
        }  
    }
}
顺序查找

查找不到时返回-1.

int  LinSearch(long num[], long x, int n) 
{
    int i;
    for (i=0; i<n; i++)  
    {
        if (num[i] == x)
        {
            return i;
        }
    }
    return -1;
}
折半查找

1.如果有N个数,使用折半查找最多查找log{2}{N}
2.折半查找程序如下,背过。

int  BinSearch(long num[], long x, int n) // x是要查找的数字。
{
	int  low, high, mid;
	low = 0;  
	high = n - 1;              
	while (low <= high)
	{
   	mid = (high + low) / 2; 
		if (x > num[mid])   
   	{
			low = mid + 1; 
   	}
		else  if (x < num[mid])  
		{
			high = mid - 1; 
   	}
		else  
		{
			return mid; 
   	}
	}
	return -1; 
}

值得注意的是:
如果用mid = (high + low) / 2;时
如果数组很大,low和high之和大于有符号整数的极限值(在limits.h中定义)
就会发生数值溢出,使mid成为一个负数
防止溢出的解决方案
修改计算中间值的方法,用减法代替加法
mid = low + (high - low) / 2;



————— ꧁༺ ♕ ༻꧂ —————




指针




变量的内存地址

1.%p表示输出变量的地址值
例如printf("a is %d,&a is %p\n",a,&a);
2.直接寻址:按变量的地址直接访问
例如scanf("%d",&a)//把接收到的地址放入&a中。
3.间接寻址:间接寻址:通过存放变量地址的其他变量访问该变量
4.指针类型:
(1)指针变量:具有指针类型的变量,用于存放地址
(2)变量的指针⇔变量的地址。
例子:

int *pa,*pb;
char *pc;

注意:int,char等为指针变量指向的数据类型,称为基类型。

例子:

#include <stdio.h>
int main()
{
  int a=0;
  int *pa=&a;//在定义指针变量pa的同时对其初始化。
  printf("a is %d,&a is %p,pa is %p,&pa is %p\n",a,&a,pa,&pa);
}

5.间接寻址运算符:*

如果定义 int *pa=&a,那么就有*pa⇔a.
6.如果以指针作为函数的形参,则可以通过指针变量的间接引用去改变函数外实参的值。
阅读以下代码,感受通过指针变量的间接引用去改变函数外实参的值的方法。

#include <stdio.h>
void Fun(int* par);
int main()
{
	int arg = 1;
	printf("arg=%d\n", arg);
	Fun(&arg);
	printf("arg=%d\n", arg);
	return 0;
}
void Fun(int* par)//注:定义了一个指针变量。
{
	printf("par=%d\n", *par);
	*par = 2;//将arg赋值为2.
}
指针的初始化
int *x=NULL//初始化为空指针。
指针指向变量的方式
int a=0;
int*pa;
pa=&a;
int a=0;
int*pa=&a;
编写函数实现两数的互换
int main()
{
  int a, b;
  a = 5;
  b = 9;
  Swap( &a, &b );
  printf("a=%d,b=%d",a,b);
  return 0;
} 
void Swap( int *x, int *y )//这里定义两个指针。
{ 
    int temp;
    temp = *x;
    *x = *y;
    *y = temp;
}
int main()
{
  int a[2] = {5, 9};

  Swap(a);//函数调用数组时不要加方括号。

  printf("%d,%d", a[0], a[1]);
  return 0;
}
void Swap(int p[])
{
    int temp;
    temp = p[0];
    p[0] = p[1];
    p[1] = temp;
}

3.Swap函数中也可以用指针来定义,这两种方式是等价的,具体程序如下

int main()
{
  int a[2] = {5, 9};

  Swap(a);//函数调用数组时不要加方括号。

  printf("%d,%d", a[0], a[1]);
  return 0;
}
void Swap(int *p)
{
    int temp;
    temp = *(p+0);
    p[0] = *(p+1);
    *(p+1) = temp;
}

下面看几个错误例子
1.

void Swap(int *x, int *y)
{  
    int *pTemp; 
   
    *pTemp = *x;
    *x = *y;
    *y = *pTemp;
} 

错误原因:指针pTemp未初始化,指针pTemp指向哪里未知,对未知单元写操作是危险的,不能借助一个未初始化的,指针变量进行两数互换。

void Swap(int *x, int *y)
{  
    int *pTemp; 
   
    pTemp = x;
    x = y;
    y = pTemp;
} 

错误语言因:借助指针pTemp,交换的是地址值,不是指针指向的内容。

函数指针

1.函数指针(Function Pointer)就是指向函数的指针变量
数据类型 (*指针变量名)(形参列表);

int  (*f)(int a, int b);

函数指针f指向的函数原型为:
int 函数名(int a, int b);

2.函数指针的作用:
保存地址,保存程序入口的地址,最重要的是函数指针可以指向不同函数从而表现出不同的功能

fun max;
fun=&max

举个例子

int Max(int x, int y);
int Min(int x, int y);
int Add(int x, int y);
int Max(int x, int y)
{   printf("max=");
    return  x>y? x : y;
}
int Min(int x, int y)
{   printf("min=");
    return  x<y? x : y;
}
int Add(int x, int y)
{   printf("sum=");  
    return  x+y;
}
void Fun(int x, int y, int (*f)(int, int));
int main()
{   int a, b;
    scanf("%d,%d", &a, &b);
    Fun(a, b, Max);//通过指向不同的函数来实现求最大,求最小,求和的功能
    Fun(a, b, Min);
    Fun(a, b, Add);
    return 0;
}
void Fun(int x, int y, int (*f)(int, int))
{   int result;
    result = (*f)(x, y) ;
    printf("%d\n", result);
}

3.功能
一般函数指针的使用
作为参数使用
举例子
1.求定积分。
求F1定积分

float F1(float x)
{
  return 1 + x * x;
}
float IntegralF1(float a, float b)
{
	float s, h;
	int n = 100, i;
	s = (F1(a) + F1(b)) / 2;
	h = (b - a) / n;
	for (i=1; i<n; i++)
	{
	   s += F1(a + i * h);
	}
	return s * h;
}

求F2的定积分。

float F2(float x)
{
  return x /(1 + x * x);
}
float IntegralF2(float a, float b)
{
	float s, h;
	int n = 100, i;
	s = (F2(a) + F2(b)) / 2;
	h = (b - a) / n;
	for (i=1; i<n; i++)
	{
	   s += F2(a + i * h);
	}
	return s * h;
}

用函数指针来求定积分时函数的表达式可以改变,所以就不用一个一个求了,更加方便。

float Integral(float (*f)(float), float a, float b)
{
   float s, h;
   int n = 100, i;
   s = ((*f)(a) + (*f)(b)) / 2;  //这里直接引用函数表达式,注意函数指针引用的形式。
   h = (b - a) / n;
   for (i=1; i<n; i++)
   {
   	s += (*f)(a + i * h);
   }
   return s * h;
}




————— ꧁༺ ♕ ༻꧂ —————




字符串




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值