Lab2:数据组织基础方法及创新应用(创新)
1.数组指针
(1)定义 int (*)[ ]数组指向二维 int 数组
(2)定义 int 指针指向二维数组的第一个元素
指针的写法较多,从我个人的尝试中选择几种写法分析。
代码1:
#include<bits/stdc++.h>
using namespace std;
int* p[12]; //数组的每一个元素都是指针
int a[12][12];
void init()
{
for(int i=1;i<=10;i++)
for(int j=1;j<=10;j++) a[i][j]=i+j;
}
int main()
{
for(int i=1;i<=10;i++) p[i]=a[i]; //每个指针指向数组的a[i][0]元素
init();
//int b[12];
//int (*q)=b; *q=&b[0];
//int (*q)[12]=a+1; //q[i][j]=xxx;
for(int i=1;i<=10;i++)
{
for(int j=1;j<=10;j++)
printf("%d ",p[i][j]); //直接调用指针的值
puts("");
}
return 0;
}
输出结果正常。
代码2
输出的最后一行居然为 0 ,这是为什么呢?
因为 \(q\) 指针初始指向了 \(a+1\) 的位置,相当于比 \(a\) 走的快了一步,导致最后一行没有成功赋值。(我原本以为 \(a\) 下标从 1 开始,那么 \(q\) 也应该从 \(a+1\) 开始,但是事实证明这么写是不对的)
正确代码:
#include<bits/stdc++.h>
using namespace std;
int a[12][12];
void init()
{
for(int i=1;i<=10;i++)
for(int j=1;j<=10;j++) a[i][j]=i+j;
}
int main()
{
init();
int (*q)[12]=a; //q[i][j]=xxx;
//int (*r)[12]=&a[1];
//(*q[i]+j)
for(int i=1;i<=10;i++)
{
for(int j=1;j<=10;j++)
printf("%d ",q[i][j]); //直接调用指针的值
puts("");
}
return 0;
}
代码3 (2)
#include<bits/stdc++.h>
using namespace std;
int a[6][6]; //要注意数组大小和初始化范围一致,因为单个指针遍历数组只能挨着遍历
void init()
{
for(int i=0;i<=5;i++)
for(int j=0;j<=5;j++) a[i][j]=i+j;
}
int main()
{
init();
int *q=&a[0][0];
for(int i=0;i<=35;i++)
{
printf("%d ",*(q+i)); //直接调用指针的值
puts("");
}
return 0;
}
要注意数组大小和初始化范围一致,因为单个指针遍历数组只能挨着遍历(肯定是因为我在这里错了才知道)
输出如下:(符合预期)
2.指针数组
定义并初始化 \(int*\) 数组,并用数组形式和数组指针形式两种方法输出
这个一开始真没搞懂,初始化和输出都搞错了,主要就在加不加 * 的问题上纠结。
注意几点:
int *r=&b
时,实际上等效于int* r; r=&b;
(这里一直理解错误了!!)- 输出参考普通指针的 \(*\) 写法,对应增加即可,自己想真的很容易错!
代码
#include<bits/stdc++.h>
using namespace std;
int a[6];
void init(){ for(int i=0;i<6;i++) a[i]=i;}
int main()
{
init();
int *q[6];
for(int i=0;i<6;i++) q[i]=&a[i];
//int* r=&b; cout<<*r;
//这里我们参考普通指针的写法,从而推出指针数组该怎么输出(仍然要多加*)
for(int i=0;i<=5;i++) printf("%d ",*q[i]);
puts("");
for(int i=0;i<=5;i++) printf("%d ",*(*(q+i)));
return 0;
}
输出如下:
3.字符串
对于任务一,指针写法和前面大同小异。无论有无串尾终止符 '\0'
,输出的时候都不会输出'\0'
,这是因为就算不手动加上这个终止符,编译器内部也会自动把它补上,而这个符号是不输出的。
代码
#include<bits/stdc++.h>
using namespace std;
char c[10];
int main()
{
scanf("%s",c);
int len=strlen(c);
char* p=c;
for(int i=0;i<len;i++) cout<<*(p+i);
puts("");
c[len]='\0';
for(int i=0;i<=len;i++) cout<<*(p+i);
return 0;
}
输出如下
任务二感觉比较简单
代码
#include<bits/stdc++.h>
using namespace std;
char c[30]="ATS\n012\123\x15\\";
int main()
{
char* p=c;
int len=strlen(c);
for(int i=0;i<len;i++) cout<<*(p+i);//指针形式
puts("");
for(int i=0;i<len;i++) cout<<p[i];//数组形式
return 0;
}
输出如下
4.typedef与自定义类型
这里用新类型数组和指针结合的时候我一开始不懂:*p到底是指针数组还是数组指针?后来根据调试我最终确定应该是数组指针,即 *p指向一整个数组。可能 typedef 之后再定义指针和我想象中的有点差别吧。
代码
#include<iostream>
using namespace std;
typedef int T[5];
T a={ 9,8,7,6,5 };
int main()
{
T *p=&a;
// T (*p)=&a; 这种写法和上面的写法是等效的,这也意味着 *p 是数组指针
for (int i = 0;i < 5;i++)
cout << a[i] << " ";
cout << endl;
for (int j = 0;j < 5;j++)
cout <<(*p)[j]<< " ";
return 0;
}
输出
5.针对下列数据结构简单输入输出
这里做其中的(e)(f),其余的前面做过了
(e)
#include<bits/stdc++.h>
using namespace std;
struct node
{
int a[5];
}x;
int main()
{
for(int i=0;i<=4;i++) x.a[i]=i;
for(int i=0;i<=4;i++) cout<<x.a[i]<<' ';
return 0;
}
输出:0 1 2 3 4
(f)
构建了指针 *r->*q->*p
#include<bits/stdc++.h>
using namespace std;
int* p,*q,*r;
int main()
{
int a=5;
p=&a;
q=p;
r=q;
cout<<*r;
return 0;
}
输出:5
6.自由设计复杂数据结构
这里就介绍一种用于建边和存储的结构吧---链式前向星
通过结构体数组和链表式的存储方式,可以遍历一个点的所有出边。
代码如下:
struct edge
{
int nxt,to,w;
}a[N];
inline void add_edge(int x,int y,int w)
{
a[++ecnt]=(edge){head[x],y,w};
head[x]=ecnt;
}