C语言指针

指针

1.引言

int a;

a = 100;

int b = a;

在C语言里面,同一个变量a,有两层含义

1) 左值:代表该变量的存储单元地址

2) 右值:代表该变量的值

————————————————————————————————————————————————————————————————————————————————————————————————

2.指针概念

地址:分配给每个变量的内存单元都有一个值(编号)

指针: 指针是一个量,对应了一块内存区域,是某个内存单元的地址。

   一个变量的地址称为该变量的指针

————————————————————————————————————————————————————————————————————————————————————————————————

3.定义指针变量

存地址的变量叫做指针变量

指针变量的定义:

类型名 * 变量名

类型必须和他所指向的那个变量的类型相同

 

int a = 10;

int* p = &a;//int *p; p = &a;

int c = a;//int c ;c = a;

* 间接访问运算符

(*地址)  地址对应的变量

*p <-> a

*&a <-> a

 

不能将一个数值赋值给指针变量,而只能给一个变量的地址!!!

int *q;

*q=50;//此种做法是危险的,因为此时你不知道q保存的是谁的地址,

也就不知道修改了哪里的值;

int *q=NULL;//q没有指向任何地方;

*q=50;//错误,没有指向任何地方,也就没有可以修改的值。

上面两种情况可能造成段错误,还有数组越界,尝试修改只读数据也会早成段错误;

注意发生段错误,可以用打印法进行查错。

正确做法:

int a=50;

int *q=&a;

————————————————————————————————————————————————————————————————————————————————————————————————

4.数组与指针

指针与数组元素

int a[10] = {1,2,3,4,5};

int *p = &a[2];

 

数组名代表这个数组的首地址

int *q =  a//int *q = &a[0];

//int *q; q = a;

把100 赋值给a[0],有几种方式

a[0] = 100;

*q = 100;

*&a[0] = 100;

 

把200赋值给a[i]有几种方式

a[i] = 200;

q[i] = 200; //下标法

*(a + i) = *( q + i) = 200;//指针法

 

指针的加减并不是单纯意义上的数学加减,而是加减指向单元的长度(指针的类型)

数组名是指向这个数组第一个元素的常量指针

 

用数组名和指针做参数

1) 形参和实参都用数组名

2) 形参用数组名,实参用指针

3) 实参用数组名,形参用指针

4) 形参和实参都用指针

这四种是等价的,都可以用;

13、写一个函数实现将任意字符串按照ASC值从小到大顺序排列。

 

     函数原型为:

     char *sort(char *s);

写一个函数将任意给定的两个字符串取交集

 

 14、函数原型为:

     char *jiaoji(char *s,char *s1,char *s2);

若s1:  abcddebcdf  ==》去重后的s1  abcdef  

  s2:  bcdfgb

15、写一个函数将任意给定的两个字符串取并集

 函数原型为:

     char *bingji(char *s,char *s1,char *s2);

 

若s1:  abcdde

  s2:  bcdfg

 

则返回的是  abcdefg

 

 

求交集

 

#include<stdio.h>

#include<string.h>

char *sort(char *s)

{

int i,j,n;

char temp;

n=strlen(s);

for(i=0;i<n-1;i++)

{

for(j=0;j<n-1;j++)

{

if(*(s+j)>*(s+j+1))

{

temp=*(s+j);

*(s+j)=*(s+j+1);

*(s+j+1)=temp;

}

}

 

}

return(s);

}

char *jiaoji(char *s,char *s1,char *s2)

 {

 char d[100]={0},e[100]={0};

 char *s3=d,*s4=e;

int i,j=0,n1,n2,n3,n4,k=0;

n1=strlen(s1),n2=strlen(s2);

for(i=0;i<n1;i++)

{

if(i==0)

{

s3[j]=s1[i];

}

if(s3[j]!=s1[i])

{

s3[++j]=s1[i];

 

}

}

puts(s3);

n3=strlen(s3);

j=0;

for(i=0;i<n2;i++)

{

if(i==0)

{

s4[j]=s2[i];

}

if(s4[j]!=s2[i])

{

s4[++j]=s2[i];

 

}

}

puts(s4);

n4=strlen(s4);

for(i=0;i<n3;i++)

{

for(j=0;j<n4;j++)

{

if(s3[i]==s4[j])

{

break;

}

 

}

if(j!=n4)

{

s[k++]=s3[i];

}

}

 

return s;

 }

int main (void)

{

char a[100]={0},b[100]={0},c[100]={0};

scanf("%s%s",a,b);

 

char *s1=sort(a),*s2=sort(b),*s=c;

puts(jiaoji(s,s1,s2));

return 0;

}

求并集

 

#include<stdio.h>

#include<string.h>

char *sort(char *s)

{

int i,j,n;

char temp;

n=strlen(s);

for(i=0;i<n-1;i++)

{

for(j=0;j<n-1;j++)

{

if(*(s+j)>*(s+j+1))

{

temp=*(s+j);

*(s+j)=*(s+j+1);

*(s+j+1)=temp;

}

}

 

}

return(s);

}

char *jiaoji(char *s,char *s1,char *s2)

 {

 char d[100]={0},e[100]={0};

 char *s3=d,*s4=e;

int i,j=0,n1,n2,n3,n4,k=0;

n1=strlen(s1),n2=strlen(s2);

for(i=0;i<n1;i++)

{

if(i==0)

{

s3[j]=s1[i];

}

if(s3[j]!=s1[i])

{

s3[++j]=s1[i];

 

}

}

puts(s3);

n3=strlen(s3);

j=0;

for(i=0;i<n2;i++)

{

if(i==0)

{

s4[j]=s2[i];

}

if(s4[j]!=s2[i])

{

s4[++j]=s2[i];

 

}

}

puts(s4);

n4=strlen(s4);

for(i=0;i<n3;i++)

{

for(j=0;j<n4;j++)

{

if(s3[i]==s4[j])

{

break;

}

 

}

if(j==n4)

{

*(s4+n4+k)=s3[i];

k++;

}

}

s=s4;

return s;

 }

int main (void)

{

char a[100]={0},b[100]={0},c[100]={0},g[100]={0};

scanf("%s%s",a,b);

char *s1=sort(a),*s2=sort(b),*s=c,*s5=g;

s5=sort(jiaoji(s,s1,s2));

puts(s5);

return 0;

}

 

在32位机里面,无论什么什么指针类型(char *,double *,int *, short *)都是4个字节,32bit;

打印验证:printf(%d\n,sizeof(char *));

结果都是4;

————————————————————————————————————————————————————————————————————————————————————————————————

5.多维数组与指针

int a[10];

a a[0]

a &a[0]

int * const(表示&a[0]的类型)

 

int b[3][4];//int[4] b[3];

b b[0]

b &b[0]

int [4] *  const //const int (*)[4](表示&b[0]的类型)

 

b[0] b[0][0]

b[0] &b[0][0]

int *const

 

int a[5];

int b[2][3];

(gdb) p &a

表示&a的类型 = (int (*)[5])   a的地址是0xbffff04c

(gdb) p &a[0]

(表示&a[0]的类型) = (int *)  a[0]的地址是0xbffff04c

(gdb) p &b

(表示&b的类型)= (int (*)[2][3])   0xbffff060

(gdb) p &b[0]

(表示&b[0]的类型)= (int (*)[3]) 0 xbffff060

(gdb) p &b[0][0]

(表示&b[0][0]的类型)= (int *)  0xbffff060

此题&a的类型是int *[4] 即int [4]*

那么&a+1就是加一个指针类型 int [4]*;

&a[0]+1就是就是&a[1];

 

—————————————————————————————————————————————————————————

6.字符串与指针

char string[] = "hello world";

char *q = string;

char *string = "hello world";//只读数据

string += 2;//string = string + 2;

————————————————————————————————————————————————————————————————————————————————————————————————

7.数组指针与指针数组

数组指针是一个指针,只是因为这个指针指向了一个数组,所以叫数组指针

类型 (*指针名)[常量表达式] 行指针

看优先级,(指针有(),所以为数组指针)(用百分之10)

详见例题8.c  

指针数组是一个数组,只是因为这个数组里面都是指针,所以叫指针数组

类型 * 数组名[常量表达式]

看优先级(数组有(),所以为指针数组) (用百分之90)

注意:

Int a[3][4}={1,2,3,.......,8}

Int (*p)[4]=&a[0]

P=&a[0];

 

Int x[]=等价于int *x;

Void fun(int a[][4],int n)等价于void fun (int (*a)[4],int n])

————————————————————————————————————————————————————————————————————————————————————————————————

8.函数指针与指针函数

函数指针是一个指针,只是因为这个指针指向的是一个函数,所以叫函数指针

返回值类型 (*函数名)(函数参数列表)

指针优先级高,所以为函数指针;(用百分之10)

指针函数是一个函数,只是因为返回的是一个指针,所以叫指针函数

类型 * 函数名(函数参数列表)

函数优先级高,所以为指针函数(用百分之90)

 

函数名代表这个函数的地址!!!

#include<stdio.h>

int sum(int a,int b)

{

return a + b;

}

int sub(int a,int b)

{

return a - b;

}

 

int* func(int a,int *x)

{

 

}

 

void function(int *x,int *y)

{

 

}

int main(int argc,char *argv[])

{

int result;

int a = 3,b = 4;

//result = sum(a,b);

int (*p)(int a,int b);//int (*p)(int ,int);

/*

p = sum;//int (*p)(int ,int ) = sum;

result = p(3,4);

*/

p = ∑

result = (*p)(a,b);

printf("result = %d\n",result);

 

p = sub;

int * (*q)(int ,int *) = func;

 

void (*m)(int *,int *) = function;

m(&a,&b);//function(&a,&b);

return 0;

}

 

————————————————————————————————————————————————————————————————————————————————————————————————

9.二级指针

保存一级指针地址的变量叫做二级指针变量

称为指向指针的指针

类型 ** 指针名

*(*(a+i)+j)=a[i][j]

————————————————————————————————————————————————————————————————————————————————————————————————

10.main函数参数

argc代表参数个数,argv代表每个参数

————————————————————————————————————————————————————————————————————————————————————————————————

11.const与指针两部分结合起来理解 很重要的知识点

详见图示

int const a;

const int a=10;//这两个等价,都是定义一个整形常量a,值不能更改;

int * const b;//一个指向整型数的常指针b,也就是说指向的值可以更改,但是地址(对应指针指向的地方)不能更改;

Const int * b;//一个指向常整型数地址的指针,指向的地址可以更改(对应的指针可以指向其他地方),但是地址上的值不能更改(对应的指针不能改变指向的值);

Const int * const c;一个指向常整形数的常指针,指向的地址和值都不能更改;

诀窍:只要看const在*的哪边,如果是左边,就是指向的值不能更改,如果是右边,就是指向的地址不能更改。

 

————————————————————————————————————————————————————————————————————————————————————————————————

12.void与指针

详见13.c

————————————————————————————————————————————————————————————————————————————————————————————————

13.malloc簇函数

SYNOPSIS

       #include <stdlib.h>

 

       void *malloc(size_t size);

   向内存申请size个字节,并返回这块内存的首地址

       void free(void *ptr);

   将ptr所指向的内存区域回收

       void *calloc(size_t nmemb, size_t size);

    向内存申请nmemb*size个字节,并返回这块内存的首地址

#include<stdio.h>

#include <stdlib.h>

int main(int argc,char *argv[])

{

//int *p = malloc(10*sizeof(int));

int *p = (int *)calloc(10,sizeof(int));//会将申请的区域全部清0

int i;

for(i = 0;i < 10;i++)

{

//p[i] = 100+i;

printf("p[%d] = %d\t",i,p[i]);

}

printf("\n");

 

free(p);//防止内存泄漏会满

return 0;

}

 

月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不同风味的月饼。现给定所有种类月饼的库存量、总售价、以及市场的最大需

求量,请你计算可以获得的最大收益是多少。



注意:销售时允许取出一部分库存。样例给出的情形是这样的:假如我们有3种月饼,其库存量分别为18、15、10万吨,总售价分别为75、

72、45亿元。如果市场的最大需求量只有20万吨,那么我们最大收益策略应该是卖出全部15万吨第2种月饼、以及5万吨第3种月饼,获得

 72 + 45/2 = 94.5(亿元)。

 

输入描述:

每个输入包含1个测试用例。每个测试用例先给出一个不超过1000的正整数N表示月饼的种类数、以及不超过500(以万吨为单位)的正整数

D表示市场最大需求量。随后一行给出N个正数表示每种月饼的库存量(以万吨为单位);最后一行给出N个正数表示每种月饼的总售价(以亿

元为单位)。数字间以空格分隔。

 

输出描述:

对每组测试用例,在一行中输出最大收益,以亿元为单位并精确到小数点后2位。

 

输入例子:

3 20

18 15 10

75 72 45

 

输出例子:

94.50

#include<stdio.h>

int main ()

{

float a[100]={0.0},b[100]={0.0},c[100]={0.0};

int i,N,D,j,k,flag=0;

float t,t1,t2,s1=0,s2,s3;

scanf("%d%d",&N,&D);

for(i=0;i<N;i++)

{

scanf("%f",&a[i]);

}

for(i=0;i<N;i++)

{

scanf("%f",&b[i]);

}

 

for(i=0;i<N;i++)

{

c[i]=b[i]/a[i];

}

for(i=0;i<N-1;i++)

{

for(j=0;j<N-1-i;j++)

{

if(c[j]<c[j+1])

{

t=c[j];

c[j]=c[j+1];

c[j+1]=t;

t=a[j];

a[j]=a[j+1];

a[j+1]=t;

t=b[j];

b[j]=b[j+1];

b[j+1]=t2;

flag=1;//将月饼单价从大到小顺序排列,其他的库存量,单价利益也跟着 变换。

}

}

if(flag==0)

break;

}

for(i=0;i<N;i++)

{

s1+=a[i];

if(D<s1)

{

k=i;

s2=s1-a[i];

break;

}

}

for(i=0;i<k;i++)

{

s3=0;

s3+=b[i];

}

s3+=(D-s2)*c[k];

printf("最大利益=%.2f\n",s3);

return 0;

}

法二、

#include <stdio.h>

int main()

{

int s,i,j,N;

float tmp,m = 0.0,a[1000],b[1000],c[1000];

scanf("%d%d",&N,&s);

for(i = 0;i < N;i++)

{

scanf("%f",&a[i]);

}

for(i = 0;i < N;i++)

{

scanf("%f",&b[i]);

}

for(i = 0;i < N;i++)

{

c[i] = (b[i]/a[i]);

}

for(j=0;j<N-1;j++)

{

for(i = 0;i < N-j;i++)

{

if(c[i] < c[i+1])

{

tmp = c[i];

c[i] = c[i+1];

c[i+1] = tmp;

tmp = a[i];

a[i] = a[i+1];

a[i+1] = tmp;             

}

}

}

printf("%f %f %f",c[0],c[1],c[2]);

for(i = 0;i <= N-1;i++)

{

if(s <= a[i])

{

m += s * c[i];

printf("max=  %.2f\n",m);

break;

}

else

{

m += (a[i] * c[i]);

s -= a[i];

}

}

return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值