visual studio 多文件工程【源码目录】
工程打了之后要把代码模块化分的很清楚。一下以visual studio2019示例一个多代码文件组织方法。
在解决方案资源管理器中,有我们的工程代码。
右击工程名,新建一个filter(其实就是一个文件夹)program。
然后在这个文件夹下面再建两个文件夹,一个main一个drive,然后把含有主函数的C文件挪到main文件中。
在drive中一个source文件夹一个include文件夹,分别用来放其他代码的C文件和h文件,我这里放了一个顺序表的sqlist.c和sqlist.h文件。
在sqlist.h文件中,声明sqlist.cpp中的函数,以及其他的宏定义等。
#ifndef _INC_SQLIST
#define _INC_SQLIST
//声明和宏定义
#endif
至于为什么写成_INC_****,因为官方的头文件宏定义声明都是这么声明的(比如下边的stdlib.h),与其保持一致,避免重复定义头文件。
在sqlist.c中包含sqlist.h头文件:#include "sqlist.h" , 注意头文件是根据文件名来的,且应该用双引号。
包含头文件时,<>和" "的区别:
简单的说,正在编译的文件的所在的目录下找该头文件,如果没找到,再去编译器放官方头文件的路径下找。
比如:
include <stdlib.h>
代表编译时直接在软件设置指定的路径(默认是编译器所在文件夹下的include文件夹)中寻找里面是否有stdlib.h的库文件。如果有,直接加载;如果没有,报错(无法找到库文件)。
include "stdlib.h"
代表编译时先寻找你正在编辑的源代码文件(C或CPP文件)所在的文件夹里面有没有stdlib.h的库文件。如果有,优先加载这个文件(上面提到的include文件夹下的stdlib.h文件就被无视了),如果没有,就会在软件设置指定的路径(默认是编译器所在文件夹下的include文件夹)中寻找里面是否有stdlib.h的库文件。如果有,直接加载;如果没有,报错(无法找到库文件)。所以,如果你自己编写了库文件(并且没有将它移动到编译器指定的include文件夹里),要在源代码文件(C或CPP文件)中将这个文件包含进去,就必须使用双引号格式的include语句,而不能使用带<>号的。
然后就可以在sqlist.c文件中编写函数了,编写好的函数如果需要外部文件通过sqlist.h头文件调用,就要在sqlist.h中声明。
最后,在其他文件中包含sqlist.h头文件之后就可以使用这个文件中声明的函数了。
把文件贴上吧
sqlist.h
#ifndef _INC_SQLIST
#define _INC_SQLIST
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define LIST_INIT_SIZE 100 //初始化的时候分配的量
#define LISTINCREMENT 10 //初始化分配的量不够的时候的增量
#define ERROR 0
#define OK 1
typedef int ElemType;
typedef int status;
typedef struct {
ElemType* elem;//存储空间基地址
int length; //当前长度(即元素个数)
int listsize;//当前分配的存储容量
}SqList;
status InitList_Sq(SqList& L);
status ListInsert(SqList& L, int i, ElemType e);
status ListDelet(SqList& L, int i);
int LocateElement(SqList L, ElemType e);
int ListLength(SqList L);//获取表长度
status DislpList(SqList L);//显示表
bool ListEmpty(SqList L);//是否为空
status GetElem(SqList L, int i, ElemType& e);//指定位置元素
#endif
sqlist.cpp
#include "sqlist.h"
status InitList_Sq(SqList& L) //创建一个空表
{
L.elem = (ElemType *)malloc(LIST_INIT_SIZE * sizeof(ElemType));//申请内存
if (!L.elem) exit(ERROR);
L.length = 0;
L.listsize = LIST_INIT_SIZE;
return OK;
}
status ListInsert(SqList& L,int i, ElemType e) //插入 一个 元素
{
int *q,*p;
if (i<1 || i>(L.length+1))return ERROR;//可插入的位置是length+1个
if (L.length >= L.listsize)//内存不够用了就增加LISTINCREMENT个内存
{
L.elem = (ElemType*)realloc(L.elem, (L.listsize + LISTINCREMENT )*sizeof(ElemType));
if (!L.elem)exit(ERROR);
L.listsize += LISTINCREMENT;
}
q = &(L.elem[i-1]);
for (p = &(L.elem[L.length]); p >= q; p--)
{
*(p + 1) = *p;
}
*q = e;
L.length += 1;
return OK;
}
status ListDelet(SqList &L,int i)
{
int *q,*p,e;
if (i<1 || i>L.length)return ERROR;//错误
e = L.elem[i-1]; //保存要删除的元素
q = L.elem + L.length - 1 - 1;//删除后的尾部 L.elem + L.length - 1是删除前最后一个元素的下标,在减一是删除后的最后一个元素下标
for (p = &L.elem[i-1]; p <= q; p++)
{
*p = *(p + 1);
}
L.length -= 1;
return OK;
}
int LocateElement(SqList L, ElemType e)//定位查找元素
{
int i = 1;
while (i <= L.length)
{
if (L.elem[i - 1] == e)return i;
i++;
}
return 0;
}
int ListLength(SqList L)//获取表长度
{
return L.length;
}
status DislpList(SqList L)//显示表
{
int i = 0;
for (i = 0; i < L.length; i++)
{
printf("%d ", L.elem[i]);
}
return OK;
}
bool ListEmpty(SqList L)//是否为空
{
if (L.length == 0)
return true;
else
return false;
}
status GetElem(SqList L,int i, ElemType &e)//指定位置元素
{
e = L.elem[i - 1];
return OK;
}
main.cpp
#include "sqlist.h"
int main()
{
int e;
SqList L;
InitList_Sq(L);
printf("ListEmpty(L): %d\n", ListEmpty(L));
ListInsert(L, 1, 22);
printf("ListInsert(L, 1, 22)\n");
ListInsert(L, 2, 23);
printf("ListInsert(L, 2, 23)\n");
ListInsert(L, 3, 26);
printf("ListInsert(L, 3, 26)\n");
ListInsert(L, 4, 287);
printf("ListInsert(L, 4, 287)\n");
printf("ListEmpty(L): %d\n", ListEmpty(L));
DislpList(L);
printf("\nListLength(L): %d\n", ListLength(L));
printf("LocateElement(L, 23): %d\n", LocateElement(L, 23));
ListDelet(L, 4);
ListDelet(L, 1);
DislpList(L);
printf("\nLocateElement(L, 23): %d\n", LocateElement(L, 23));
GetElem(L, 1, e);
printf("GetElem(L, 1, e): %d\n", e);
return 0;
}