多文件(工程)编译常见问题:
- 隐式声明:没有声明该函数。
解决方式:在工程头文件head.h中,添加该函数的声明。
- gcc链接器未发现函数(未定义函数)(全局变量同理)
解决方式:寻找所有编译的.c文件中是否存在该函数。
- gcc链接器发现多个同名函数(多重定义)(全局变量同理)
解决方式:打开提示的2个文件,删除掉其中的无用函数,或者修改其中一个的函数名。
练习:
- 根据proj2,定义结构体数组(长度50),初始化3个用户的信息。
- 需将usr_login函数移到usr.c中
- 修改usr_login函数,使得可以判断多个用户。
- 要求用户uid和密码可多次输入,当超过3次,提示次数过多,结束程序。
- 登录成功后,显示操作菜单:0: 显示用户信息 usr_show()
1: 修改密码 usr_update()
2: 新增用户 usr_add()
3: 删除用户 usr_del()
先完成修改密码功能,完成后思考一下如何实现用户新增、删除?
(可以添加显示信息功能,查看密码是否修改成功。)
练习:
- 参考proj1文件夹,创建一个自己的工程,放入4个文件:
main.c 放入main主函数
square.c 放入计算平方、立方函数。
sum.c 放入加减乘除的4个函数
head.h 工程头文件
在main函数中都使用子函数,计算一下。
head.h
代码语言:javascript复制#ifndef _HEAD_H
#define _HEAD_H
#include <stdio.h>
/********** square.c函数声明 ***********/
// 计算a的平方
extern int func_square(int a);
// 计算a的立方
extern int func_cube(int a);
/********** sum.c函数声明 ***********/
// 计算两数之和
extern int func_sum(int a, int b);
#endif
main.c
代码语言:javascript复制#include "head.h"
int main()
{
int a=3, b=4;
int a2=func_square(a);
int b2=func_square(b);
int sum = func_sum(a2, b2);
printf("sum: %dn", sum);
int a3=func_cube(a);
printf("a3: %dn", a3);
return 0;
}
square.c
代码语言:javascript复制// 计算a的平方
int func_square(int a)
{
return a*a;
}
// 计算a的立方
int func_cube(int a)
{
return a*a*a;
}
sum.c
代码语言:javascript复制// 计算两数之和
int func_sum(int a, int b)
{
return a b;
}
head.h
代码语言:javascript复制#ifndef _HEAD_H
#define _HEAD_H
// 系统头文件
#include <stdio.h>
#include <string.h>
// 类型声明
typedef unsigned int u32;
// 用户信息结构体声明
struct usr{
u32 uid; // 1.用户ID
char pwd[20]; // 2.用户密码(长度限定20字符)
};
// 子函数外部声明
// 用户登录功能
extern int usr_login(int sum, struct usr *info);
// 显示用户信息
extern void usr_show(int sum, struct usr *info);
// 修改密码
extern void usr_update(int i, struct usr *info);
// 新增用户
extern void usr_add(void);
// 删除用户
extern void usr_del(void);
#endif
main.c
代码语言:javascript复制#include "head.h"
int main()
{
// 定义1个结构体数组
struct usr info[50] = {
{ .uid=1,
.pwd="123456"
},
{ .uid=2,
.pwd="223456"
},
{ .uid=100,
.pwd="323456"
}
};
int sum=3; //当前人数(当前有效数据个数)
// goto pos1; // 直接跳转到44行(调试结束后记得删除!)
// 1.用户登录功能
int cnt=0;
int ret;
while(1)
{
ret = usr_login(sum, info);
// printf("ret: %dn", ret);
if(ret >= 0)
break;
else if(ret == -1)
printf("No Such User!n");
else if(ret == -2)
printf("Password ERROR!n");
cnt ;
printf("ERROR count: %dn", cnt);
if(cnt>3)
{
printf("byebye~n");
return -1; //结束程序
}
}
printf("[%d] Success!n", info[ret].uid);
// pos1:
// 2.用户操作
int cmd;
while(1)
{
printf("=============CMD==============n");
printf("0: 显示用户信息n");
printf("1: 修改密码 n");
printf("2: 新增用户n");
printf("3: 删除用户n");
printf("==============================n");
printf("Pls Input CMD: ");
scanf("%d", &cmd); while(getchar()!='n');
switch(cmd)
{
case 0: //显示用户信息
usr_show(sum, info); break;
case 1: //修改密码
usr_update(ret, info); break;
case 2: //新增用户
usr_add(); break;
case 3: //删除用户
usr_del(); break;
}
}
return 0;
}
usr.c
代码语言:javascript复制#include "head.h"
// 用户登录功能
int usr_login(int sum, struct usr *info)
{
// 1.用户输入uid和密码
struct usr input_info;
printf("Pls Input uid: ");
scanf("%d", &input_info.uid); while(getchar()!='n');
printf("Pls Input pwd: ");
scanf("%s", input_info.pwd); while(getchar()!='n');
// 2.循环判断用户输入
int i;
for(i=0; i<sum; i )
{
if(input_info.uid == info[i].uid) // ID判断
{
// 进一步判断密码
if(strcmp(input_info.pwd, info[i].pwd) == 0)
return i; // ID、密码正确,返回正确用户的下标
else
return -2; // 密码错误
}
}
// 如果for正常循环完毕,说明不存在该ID
if(i==sum)
return -1;
}
// 显示用户信息(用于调试)
void usr_show(int sum, struct usr *info)
{
int i;
printf("============INFO============n");
printf("UIDt PWDn");
for(i=0; i<sum; i )
printf("%dt %sn", info[i].uid, info[i].pwd);
}
// 修改密码
void usr_update(int i, struct usr *info)
{
// 1.用户输入新密码
char input_pwd[20];
printf("Pls Input new pwd: ");
scanf("%s", input_pwd); while(getchar()!='n');
// 2.将新密码替换旧密码
// info[i].pwd = input_pwd; // 字符串不能直接赋值到数组中!需使用字符串拷贝函数
strcpy(info[i].pwd, input_pwd);
}
// 新增用户
void usr_add(void)
{
printf("usr_add 功能待完善...n");
}
// 删除用户
void usr_del(void)
{
printf("usr_del 功能待完善...n");
}
head.h
代码语言:javascript复制#ifndef _HEAD_H
#define _HEAD_H
// 系统头文件
#include <stdio.h>
#include <string.h>
// 类型声明
typedef unsigned int u32;
// 用户信息结构体声明
struct usr{
u32 uid; // 1.用户ID
char pwd[20]; // 2.用户密码(长度限定20字符)
};
// 子函数外部声明
// 用户登录功能
extern int usr_login(int sum, struct usr *info);
// 显示用户信息
extern void usr_show(int sum, struct usr *info);
// 修改密码
extern void usr_update(int i, struct usr *info);
// 新增用户
extern void usr_add(void);
// 删除用户
extern void usr_del(void);
#endif
main.c
代码语言:javascript复制#include "head.h"
int main()
{
// 定义1个结构体数组
struct usr info[50] = {
{ .uid=1,
.pwd="123456"
},
{ .uid=2,
.pwd="223456"
},
{ .uid=100,
.pwd="323456"
}
};
int sum=3; //当前人数(当前有效数据个数)
// goto pos1; // 直接跳转到44行(调试结束后记得删除!)
// 1.用户登录功能
int cnt;
int ret;
for(cnt=2; cnt>=0; cnt--) // 2 1 0
{
ret = usr_login(sum, info);
// printf("ret: %dn", ret);
if(ret >= 0) // 如正确,直接跳出
break;
else if(ret == -1)
printf("ERROR: 无此用户![还剩%d次机会.]n", cnt);
else if(ret == -2)
printf("ERROR: 密码错误![还剩%d次机会.]n", cnt);
}
if(cnt<0)
{
printf("3次错误! 程序结束!n");
return -1;
}
printf("欢迎登陆! 用户ID: [%d]!n", info[ret].uid);
// pos1:
// 2.用户操作
int cmd;
while(1)
{
printf("=============CMD==============n");
printf("0: 显示用户信息n");
printf("1: 修改密码 n");
printf("2: 新增用户n");
printf("3: 删除用户n");
printf("==============================n");
printf("Pls Input CMD: ");
scanf("%d", &cmd); while(getchar()!='n');
switch(cmd)
{
case 0: //显示用户信息
usr_show(sum, info); break;
case 1: //修改密码
usr_update(ret, info); break;
case 2: //新增用户
usr_add(); break;
case 3: //删除用户
usr_del(); break;
}
}
return 0;
}
usr.c
代码语言:javascript复制#include "head.h"
// 用户登录功能
int usr_login(int sum, struct usr *info)
{
// 1.用户输入uid和密码
struct usr input_info;
printf("Pls Input uid: ");
scanf("%d", &input_info.uid); while(getchar()!='n');
printf("Pls Input pwd: ");
scanf("%s", input_info.pwd); while(getchar()!='n');
// 2.循环判断用户输入
int i;
for(i=0; i<sum; i )
{
if(input_info.uid == info[i].uid) // ID判断
{
// 进一步判断密码
if(strcmp(input_info.pwd, info[i].pwd) == 0)
return i; // ID、密码正确,返回正确用户的下标
else
return -2; // 密码错误
}
}
// 如果for正常循环完毕,说明不存在该ID
if(i==sum)
return -1;
}
// 显示用户信息(用于调试)
void usr_show(int sum, struct usr *info)
{
int i;
printf("============INFO============n");
printf("UIDt PWDn");
for(i=0; i<sum; i )
printf("%dt %sn", info[i].uid, info[i].pwd);
}
// 修改密码
void usr_update(int i, struct usr *info)
{
// 1.用户输入新密码
char input_pwd[20];
printf("Pls Input new pwd: ");
scanf("%s", input_pwd); while(getchar()!='n');
// 2.将新密码替换旧密码
// info[i].pwd = input_pwd; // 字符串不能直接赋值到数组中!需使用字符串拷贝函数
strcpy(info[i].pwd, input_pwd);
}
// 新增用户
void usr_add(void)
{
printf("usr_add 功能待完善...n");
}
// 删除用户
void usr_del(void)
{
printf("usr_del 功能待完善...n");
}