直到昨天中午,我还在因为读错题而疯狂学习新知识。
把整个任务脑补成了一个巨大的任务的错误太可怕了,以后要记住这次的教训,简直是白费了一天多的功夫。
不过这两天也不仅仅做这个任务,还复习了计算机网络,但是考试居然不是今天,是下周的今天。
这种事情怎么老是搞错呢。。。
算了都是好事不在意它。
结课作业中的问题
长久不用C语言,导致语言基础爆炸,很多东西忘记怎么使用,频频报错。
写两篇日志,分别是C语言的语法方面的问题和C语言算法的问题,本篇是语法问题。
指针和数组
这个问题一直是问题,在学C语言的时候草草就过去了,没有细致探讨,这里进行一定的实用性探讨。
- 数组名是数组首元素地址
数组名和指针一样,存储的是地址,特殊在数组名内存储的是数组本身首元素的地址。
一个词叫做解引用,把一个地址对应的数据取出就是解引用。
对于一个数组a[N],我们进行了三步:第一步,取出数组元素首地址;第二步,目标地址=首地址+sizeof(type)*N,得到目标a[N]的地址;第三步,对地址解引用。
对于一个指针p,只有两步,对p的地址解引用,获取到p的值,也就是p指向目标的地址;再对这个目标地址再次解引用,获得目标元素。
数组名!=数组指针,而是等于数组首元素指针。
- 一维数组可以和一维指针混用,二维数组可以喝二维指针混用吗?不可!
首先我们强调,把多维数组当做一维数组看待。
比如char arr[3][3],我们就要把它当做一维数组,内里元素分别为arr[0]arr[1]arr[2],这三个char [3]型的数组。
为什么?
我们先来看二维数组名代表了什么在代码中:
代码1:
char buf[2][2]={{1,2},{3,4}};
char *p = buf;
编译结果:
warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
代码2:
char buf[2][2]={{1,2},{3,4}};
char (*p)[2] = buf;
编译结果:
无警告信息
显然,二位数组的数组名指针类型是char*[2]型,我们应当把二维乃至多维数组看成嵌套型的一维数组,也就是俄罗斯套娃数组,我们可以看到,数组名指针指向的首元素指针既可以是普通变量,也可以是一维或多维数组。
- 那么如何用指针来指向数组呢?
数组中的元素排列是顺序排列的,也就是一横排一横排连续,所以有以下代码可以用指针指向数组并且调用。
#include<stdio.h>
#include<stdlib.h>
#define ROW 2
#define COLUMN 2
int main(void)
{
char buf[ROW][COLUMN]={{1,2},{3,4}};
char *p = (char*)buf;
//访问buf[x][y],即访问p[x*COLUMN+y]
printf("buf = %d,%d,%d,%d\r\n",p[COLUMN*0+0],p[COLUMN*0+1],p[COLUMN*1+0],p[COLUMN*1+1]);
system("pause");
return 0;
}
结果是这样
通过这个试验,我们可以了解到如何用指针来管理数组了。
指针传递、引用传递
函数中有各种参数,普通的直接调用没有什么可说的,仅仅是新建一个值,只存活在函数调用期间,而函数麻烦而又有用的地方就在这指针传递和引用传递。
-
二者有什么共同点?
都是在函数中操作实参地址的,而值传递操作的不是实参地址。 -
有什么不同点?
引用的规则是被引用的同时必须被初始化,同时不能有NULL引用,引用必须与合法的存储单元关联。
一旦引用倍初始化,就不能改变引用的关系。
而指针可以任何时候被初始化,可以是NULL,可以随时改变所指的对象。 -
二者不同的根本原因。
从概念上讲。指针从本质上讲就是存放变量地址的一个变量,在逻辑上是独立的,它可以被改变,包括其所指向的地址的改变和其指向的地址中所存放的数据的改变。而引用是一个别名,它在逻辑上不是独立的,它的存在具有依附性,所以引用必须在一开始就被初始化,而且其引用的对象在其整个生命周期中是不能被改变的(自始至终只能依附于同一个变量)。
用一段这个函数,展示下使用流程。
#include<stdio.h>
#include<stdlib.h>
#define ROW 2
#define COLUMN 2
typedef struct TEST
{
int a;
int b[5];
int *c;
}testOf;
void tt(testOf *t);
void ttt(testOf &t);
int main(void)
{
testOf testa,testb;
testOf *te;
testOf *teb=&testb;
te=&testa;
testa.a=8;
for(int i=0;i<5;i++){
tt(te);
ttt(testa);
ttt(testb);
tt(teb);
}
teb=te;
printf("%d%d\n",testa.a,testa.c);
system("pause");
return 0;
}
void tt(testOf *t)
{
t->a++;
printf("%d\n",t->a);
t->c=&t->a;
}
void ttt(testOf &t)
{
t.a=100;
printf("%d\n",t.a);
}
函数多返回值
很多时候,我们都会碰到一个函数需要多个返回值,但是一个函数的返回值只有一个,如何用一个函数返回多个值呢?
想到指针就对了,我们可以在参数中使用指针参数,传递我们主函数中的参数,通过这个函数来影响实参。
我很喜欢一句话就是“编程的本质不就是改变量吗?”先有量的输入,然后改变成很多量,变型、变数、计算都是改变量。
输入流
输出的方法千篇一律,大多时候就是好看点和不好看的区别。
每次写c的时候,做题没感觉,但是只要是写整个程序就会出现各种难受的问题,最大的问题就是输入的问题。
如何能够方便输入、快速输入经常会成为一个大问题。
如何能够快速输入呢?
我们就想到一个方法,用空格隔开数组中的每一个数,用回车来确定。
这样不仅能清晰看到我们的输入,也比一直敲数字敲回车优雅。
粗略代码如下
#include <stdio.h>
int main(){
int num;
int i=0;
int arr[10];
while(1){
scanf("%d",&num);
char c=getchar();
arr[i++]=num;
if(c=='\n'){
break;
}
}
return 0;
}
getchar();读走了空格和回车并且在下面判定,空格再次循环,回车退出。
因为这次是为了给结课作业中的二维数组邻接表做输入,我就简单再写一个给二维数组邻接表赋值的详细代码。
#include<stdio.h>
#include<stdlib.h>
#define MAX_V_NUM 10
#define MAX_INT 999 //不可能数
//#define MAX_CITY_NUM 10
typedef struct TEST
{
char chengshi[20] ;
int arcsM[MAX_V_NUM][MAX_V_NUM];
int Vnum,Lnum;
int *c;
}testOf;
/*
typedef struct CITY
{
testOf city[MAX_CITY_NUM];
}TheWord
*/
void init(testOf *map);//初始化邻接表,每个点到其他店为不可能值,到自己为0;
void mapIn(testOf &map);//手动输入邻接表,按行输入,空格分开数,回车分开行。
void mapShow(testOf *map);//展示邻接表
int main(void)
{
testOf map,arcs;
testOf *pmap;
testOf *parcs;
pmap=↦
parcs=&arcs;
init(pmap);
mapShow(pmap);
mapIn(map);
mapShow(pmap);
system("pause");
return 0;
}
/*初始化邻接表,*/
void init(testOf *map)
{
int i,j;
map->Vnum=MAX_V_NUM;
for(i=0;i<MAX_V_NUM;i++) //邻接矩阵的初始化
{
for(j=0;j<MAX_V_NUM;j++)
{
if(i==j)
{
map->arcsM[i][j]=0;
}
else
{
map->arcsM[i][j]=MAX_INT;
}
}
}
}
/*手动输入邻接表*/
void mapIn(testOf &map)
{
int num;
int i=0;
int j=0;
int Vtime;
printf("请输入城市中重要站点的数目\n");
scanf("%d",&map.Vnum);
Vtime=map.Vnum;
getchar();
printf("请输入邻接表值,格式为1 2 3 4,将这4个数赋值给邻接矩阵第一排\n");
/*为邻接表手动赋值,0代表不改变*/
for(i=0;i<map.Vnum;i++)
{
printf("现在是第%d行,共有%d行\n",i+1,map.Vnum);
for(j=0;j<map.Vnum;j++)
{
scanf("%d",&num);
char c=getchar();
if(num!=0 && map.arcsM[i][j]!=0)
{
map.arcsM[i][j]=num;
}
/*
if(c==' '){
Vtime--;
if(Vtime==1){
break;
}
}
*/
if(c=='\n'){
break;
}
}
}
}
/*展示邻接表*/
void mapShow(testOf *map)
{
printf("--------此表如下----------\n");
int i,j;
for(i=0;i<map->Vnum;i++)
{
for(j=0;j<map->Vnum;j++)
{
printf("%d ",map->arcsM[i][j]);
}
printf("\n");
}
}
这段代码实现了通过空格隔开数据,分行输入数据到数组中,效果如下
虽然没有鲁棒性,没有错误显示,不过有了一个大的架子,试验中使用还是足够的。
本次实验期间任务繁多,如果在最后较为空闲,会补出等同这段代码,会更加美观更加健壮。
以下是我遇到问题后,上网查资料帮助到我的文章。
————————————————
版权声明:本文为CSDN博主「千淘万漉」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/matrix_google/article/details/76595439
————————————————
版权声明:本文为CSDN博主「魏波-」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weibo1230123/article/details/75541862
网友评论