考场上看到这道题时,自己完全没有勇气去做,原因是以为要实现一个定时器记录时间,那岂不是要多线程???
今天仔细分析了一下,发现其实接收的数据报文中第一个值就是当前的时间,可以以此判断ip地址是否过期。。。
原题入口
#include <stdio.h>
#include <string.h>
#define MAX(x,y) (((x)>(y))?(x):(y))
#define MIN(x,y) (((x)<(y))?(x):(y))
typedef long long ll;
ll N, Tdef, Tmax, Tmin, mes_num;
char H[25];
char send[25], rec[25], type[20];
ll r_time, q_time, ip_address;
struct st {
int state=0; //0 未分配 1 待分配 2 占用 3 过期
ll outtime=0;
char owner[25]="";
}ip[10005];
void brush(){ //只更新状态即可,特定状态对应的属性值其实不用改
ll i; //检索的时候根据状态选定IP后,直接修改其他属性值
//即不用核实状态与属性的一致性
//但是对于未分配且过期的ip,由于检索时会比较占有者名称(33-36),因此也需要刷新
for (i = 1; i <= N; i++)
if (ip[i].outtime <= r_time)
{
if (ip[i].state == 2)
ip[i].state = 3;
if (ip[i].state == 1)
{
ip[i].state = 0;
strcpy(ip[i].owner, "");
}
}
}
ll find_ip() {
ll i;
for (i = 1; i <= N; i++) {
if (strcmp(send, ip[i].owner) == 0) //前提是保证了状态与占用者属性的一致性。。
return i;
}
for (i = 1; i <= N; i++) {
if (ip[i].state == 0)
return i;
}
for (i = 1; i <= N; i++) {
if (ip[i].state == 3)
return i;
}
return 0;
}
int deal() {
if (strcmp(H, rec) != 0 && strcmp("*", rec) != 0) {
if (strcmp(type, "REQ") != 0)
return 0;
}
if (strcmp(type, "REQ") != 0 && strcmp(type, "DIS") != 0)
return 0;
if (strcmp("*", rec) == 0 && strcmp(type, "DIS") != 0 || strcmp(H, rec) == 0 && strcmp(type, "DIS") == 0)
return 0;
if (strcmp(type, "DIS") == 0) {
ll f = find_ip();
if (!f) return 0;//地址池耗尽
ip[f].state = 1;
strcpy(ip[f].owner, send);
if (q_time == 0) {
ip[f].outtime = r_time + Tdef;
}
else {
ll newot = q_time;
newot = MAX(r_time + Tmin, newot);
newot = MIN(r_time + Tmax, newot);
ip[f].outtime = newot;
}
/*else if (q_time >= Tmin + r_time && q_time <= Tmax + r_time) {
ip[f].outtime = q_time;
}
else if (q_time < Tmin + r_time)
ip[f].outtime = r_time + Tmin;
else if (q_time > Tmax + r_time)
ip[f].outtime = r_time + Tmax;*/
printf("%s %s OFR %lld %lld\n", H, send, f, ip[f].outtime);
}
else if (strcmp(type, "REQ")==0) {
ll i;
if (strcmp(rec, H) != 0) {
for (i = 1; i <= N; i++) {
if (strcmp(ip[i].owner, send)==0) {
if (ip[i].state == 1) {
ip[i].state = 0;
strcpy(ip[i].owner, "");
//ip[i].outtime = 0;
}
}
}
return 0;
}
if (ip_address <= N && strcmp(ip[ip_address].owner, send) == 0) {
ip[ip_address].state = 2;
if (q_time == 0) {
ip[ip_address].outtime = r_time + Tdef;
}
else {
ll newot = q_time;
newot = MAX(r_time + Tmin, newot);
newot = MIN(r_time + Tmax, newot);
ip[ip_address].outtime = newot;
}
/*else if (q_time >= Tmin+r_time && q_time <= Tmax+r_time) {
ip[ip_address].outtime = q_time;
}
else if (q_time < Tmin+r_time)
ip[ip_address].outtime = r_time + Tmin;
else if (q_time > Tmax+r_time)
ip[ip_address].outtime = r_time + Tmax;*/
printf("%s %s ACK %lld %lld\n", H, send, ip_address, ip[ip_address].outtime);
}
else {
printf("%s %s NAK %lld 0\n", H, send, ip_address);
return 0;
}
return 1;
}
}
int main() {
scanf("%lld%lld%lld%lld%s", &N, &Tdef, &Tmax, &Tmin, H);
scanf("%lld", &mes_num);
while (mes_num--) {
scanf("%lld%s%s%s%lld%lld", &r_time, send, rec, type, &ip_address, &q_time);
brush();
deal();
}
return 0;
}
思路就是按照实现细节
一步一步处理,一定要仔细分析状态转换的逻辑,该同步的属性值最开始还是不要偷懒省去,很可能导致一些逻辑错误。
第一次做大模拟,大佬勿喷😋