指针

· · 算法·理论

今天学习了指针的应用,希望自己能够吸收消化。

指针:

    int a=2;
    int *p=&a;//*是间接运算符
    cout<<*p<<" "<<&p<<" "<<&a<<" "<<p; 
    int *pp=NULL;//空指针,但有自己的特殊地址。
    cout<<" "<<*pp<<'\n';
    int *p2=new(int);//开启一个int 大小的空间,随机给指针p2一个4Byte大小的空间,并且明确空间里存储的是一个整数。指针需要初始化,否则电脑系统容易崩溃。

指针变量加减运算:

#include<bits/stdc++.h>
using namespace std;
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int a[100],n;//指向a[1]的地址,即a数组的第二位。
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    int *p=&a[1];
    for(int i=1;i<=n;i++){
        printf("%d ",*p);
        p++;//内存地址右移一位。
    }
    return 0;
}
//int *p=a;与int*p=&a[0]效果一样。
//&a[0]与a,都是a数组的地址。

无类型指针:

#include<bits/stdc++.h>
using namespace std;
int a=10;
double b=2.5;
void *p;
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    p=&a;
//  cout<<*p<<'\n';  强制转化为int *p的指针,并且输出指着的值。
    cout<<*(int *)p<<'\n';
    p=&b;//强制转化为double *p指针。
    cout<<*(double *)p<<'\n';
    return 0;
}

多重指针:

#include<bits/stdc++.h>
using namespace std;
int a=10;
int *p;
int * *pp;//定义双重指针,指向int类型指针的指针。
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    p=&a;
    pp=&p;//pp指针指向一个p指针。
    printf("%d=%d=%d\n",a,*p,**pp); 
    return 0;
}

指针与数组:

#include<bits/stdc++.h>
using namespace std;
int a[100];
int *pa=a; 
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    //pa=&a[0];
    int n;
    cin>>n;
    for(int i=0;i<n;i++){
        scanf("%d",pa+i);//a+i或&a[i],pa+i
        printf("%d",*(pa+i));//pa[i]或a[i]或*(a+i);
    }
    return 0;
}

指针看成数组名:

#include<bits/stdc++.h>
using namespace std;
int n;
int *a;
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    scanf("%d",&n);
    a=new int[n+1];//向系统申请一个连续的n+1个长度的int类型的空间。
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);//或a+i-1
        printf("%d",a[i]);//或*(a+i-1);
    }
    delete []a;//使用完,删除a指针指向的空间,但是原来存的数据还在。
    return 0;
} 

行列转换问题:

#include<bits/stdc++.h>
using namespace std;
const int LP=1e5+5;
int n,m,k;
int x[LP],y[LP],d[LP];
int c[LP];//每列多少个数(记录)
int *a[LP]; //每列一个指针。
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    scanf("%d%d%d",&n,&m,&k);
    for(int l=1;l<=k;l++){
        scanf("%d %d %d",&x[l],&y[l],&d[l]);//第某行:x[i],第某列:y[i],的值:d[i]。
        c[y[l]]++;//统计每一列多少个数。
    }
    for(int i=1;i<=m;i++){
        a[i]=new int(c[i]);//给每一列指针开相应数量的空间。
    }
    for(int i=1;i<=k;i++){
        *a[y[i]]=d[i];
        a[y[i]]++;
    }
    for(int i=1;i<=m;i++){
        a[i]-=c[i];
        for(int j=1;j<=c[i];j++,a[i]++){
            printf("%d ",* a[i]);
        }
    }
    return 0;
}
//*a[i]可写成a[i][j-1]。

指针与字符串:

#include<bits/stdc++.h>
using namespace std;
int main(){
    string str="abcde";
    string *s=&str;
    cout<<*s<<'\n';
    cout<<s<<'\n';
    cout<<&s<<'\n';
//  printf("%s",str);//由于string类型是C++版本的(类类型),而printf是C语言的标准输出,C语言中没有string,只有char a[]代表字符串。所以有编译错误出现。
    printf("%s\n",str.c_str());

    char str1[]="abcdef";
    char *s1=str1;
    cout<<s1<<'\n';//abcdefg
    cout<<*s1<<'\n';//a
    printf("%s\n",s1);//abcdef
    printf("%c\n",s1);//unknown char
    printf("%c\n",*s1);//a the first char
    printf("%s\n",*s1);//no cout

    const char *str2="abcd";//等价于:char *str2;   str2="abcd";
    printf("%s\n",str2);
//  str2[0]='b';//只读,不能修改。只能重新指向新的地址。
    str2="bcdef";
    printf("%s\n",str2);

    char str3[]="12345";
    string s3=str3;
    printf("%s\n",str3);//12345
    printf("%s\n",s3.c_str());//12345
    cout<<str3<<" "<<s3<<'\n';//12345 12345
    return 0;
}

字符串指针做函数:

#include<bits/stdc++.h>
using namespace std;
void swapp(char &a,char &b){
    char t;
    t=a;
    a=b;
    b=t;
}
void work(char *str){
    int len=strlen(str);
    for(int i=0;i<=len/2-1;i++){
        swapp(str[i],str[len-i-1]);
    }
}
int main(){
    char s[100];
    char *str=s;
    gets(s);//读取字符串,包括空格,也可gets(str);
    work(str);
    printf("%s\n",s);
    return 0;
}

指针与函数:

引用和指针: 传入不一样,函数内不一样。只能由指针交换地址下的值。

#include<bits/stdc++.h>
using namespace std;
void swapp(int *x,int *y){
    int t=*x;
    *x=*y;
    *y=t;
}
int main(){
    int a=5,b=3;
    swapp(&a,&b);
    printf("%d %d\n",a,b);
    return 0;
}

函数返回指针:

样子:int *a(int x,int y)

#include<bits/stdc++.h>
using namespace std;
int n,a[100];
bool isprime(int x){//寻找第一个质数。
    for(int j=2;j*j<=x;j++){
        if(x%j==0) return false;
    }
    return true;
}
int *find(){
    for(int i=1;i<=n;i++){
        if(isprime(a[i])){
            return &a[i]; 
        }
    }
    return NULL;
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    int *p=find();
    if(p!=NULL){
        printf("%d\n",*p);
    }
    else {
        printf("can't find it!\n");
    }
    int*(*pp)()=&find;
    cout << reinterpret_cast<void*>(pp) << '\n';//查看函数地址。
    return 0;
}

函数指针:

#include<bits/stdc++.h>
using namespace std;
int t(int a){
    return a;
}
int main(){
    cout<<t<<'\n';//显示函数t的地址。
    int(*p)(int a);//定义函数指针变量。
    p=t;//将函数地址赋给指针p(函数指针)
    cout<<p(5)<<','<<(*p)(10)<<','<<t(15)<<'\n';
    return 0;
}

int *p(int a);//整数指针的p函数
int (*p)(int a);//整数函数的p指针

使用typedef定义函数指针:

#include<bits/stdc++.h>
using namespace std;
int sum(int a,int b){
    return a+b;
}
typedef int(*p)(int,int);//定义一个含两个参数的整形函数指针类型
int main(){
    p pp=sum;
    cout<<pp(2,5);
    return 0;
}
// int (*p)(int a,int b)  生成一个指针p,p指针是一个有含有2个参数的int函数指针,是一个变量

使用指针模拟菜单:

#include<bits/stdc++.h>
using namespace std;
void t1(){cout<<"test1";}
void t2(){cout<<"test2";}
void t3(){cout<<"test3";}
void t4(){cout<<"test4";}
void t5(){cout<<"test5";}
typedef void(*p)();
int main(){
    p a[]={NULL,t1,t2,t3,t4,t5};//a里存的是地址。
    int x;
    cin>>x;
    a[x]();
    return 0;
}

链表结构:

#include<bits/stdc++.h>
using namespace std;
struct Node{
    int data;
    Node *next;
};
Node *head,*p,*r;
int x; 
int main(){
    cin>>x;
    head=new Node;//申请头结点
    r=head;
    while(x!=-1){
        p=new Node;
        p->data=x;
        p->next=NULL;
        r->next=p;
        r=p;
        cin>>x;
    }
    p=head->next;
    while(p!=NULL){
        cout<<p->data<<" ";
        p=p->next;
    }
    return 0;
} 

结构体指针:

#include<bits/stdc++.h>
using namespace std;
struct Node{
    int a;
    string name;
}*p;
int main(){
    p->name="Wu";
    (*p).name="Wu";
    return 0;
}

双向链表:

#include<bits/stdc++.h>
using namespace std;
struct node{
    int data;
    node *pre,*next;
};
node *head1,*p1,*q1,*r1;
void insert(node *head,int i,int x){
    node *s,*p;
    int j=0;
    s=new node;
    p=head;
    while((p!=NULL)&&(j<i)){
        p=p->next;
        j++;
    }
    if(p==NULL){
        cout<<"can't insert"<<'\n';
    }
    else {
        s->data=x;
        s->pre=p->pre;
        p->pre->next=s;
        s->next=p;
        p->pre=s;
    }
}
void delete1(node *head,int i){
    int j=0;
    node *p;
    p=head;
    while((p!=NULL)&&(j<i)){
        p=p->next;
        j++;
    }
    if(p==NULL){
        cout<<"can't "<<'\n';
    } 
    else {
        p->pre->next=p->next;
        p->next->pre=p->pre;
        free(p); //释放p指针当前指向的内存
    }
}
int main(){

}

循环链表,约瑟夫环:

#include<bits/stdc++.h>
using namespace std;
struct node{
    long long data;
    node *next;
};
long long n,m;
node *head,*p,*r;
int main(){
    long long k,l;
    cin>>n>>m;
    head=new node;
    head->data=1;
    head->next=NULL;
    r=head;
    for(int i=2;i<=n;i++){
        p=new node;
        p->data=i;
        p->next=NULL;
        r->next=p;
        r=p;
    }
    r->next=head;
    r=head;

/*  for(int i=1;i<=n;i++){
        cout<<r->data<<" ";
        r=r->next;
    }
    cout<<'\n';*/

//为什么双重循环的j循环从1到m-2:因为r在j循环里被赋值的就是当前数的下一个数,j循环外又输出的是r的下一个,所以数的人数要减去2
    for(int i=1;i<=n;i++){//i列举从第i个人开始数
        for(int j=1;j<=m-2;j++){//j表示从第i个人开始数m个人
            r=r->next;
        }
        cout<<r->next->data<<" ";
        r->next=r->next->next;
        r=r->next;
    }
    return 0;
}

完结撒花