void main(int argc, char* argv[]) {
char* hostname = (char*)malloc(sizeof(char)*1024);
hostname = getClientHostName("122.205.26.34");
printf("%s\n", hostname);
free(hostname);
}
char* getClientHostName(char* client_ip) {
char hostnames[5][2];
hostnames[0][0] = "122.205.26.34";
hostnames[0][1] = "aaaaa";
hostnames[1][0] = "120.205.36.30";
hostnames[1][1] = "bbbbb";
hostnames[2][0] = "120.205.16.36";
hostnames[2][1] = "ccccc";
hostnames[3][0] = "149.205.36.46";
hostnames[3][1] = "dddddd";
hostnames[4][0] = "169.205.36.33";
hostnames[4][1] = "eeeeee";
for(int i = 0; i<5; i++) {
if(!strcmp(hostnames[i][0], client_ip))
return (char*)hostnames[i][1];
}
return NULL;
}
C中的初学者。
我不确定是否有更好的方法来实现我想要实现的内容。代码不言自明。有没有什么方法可以使用一些通用的IP地址来预定义主机名的大小,以避免seg错误?有没有更好的方法,我不需要硬编码大小?
答案 0 :(得分:2)
修复编译器错误和警告后,您将获得:
const char* getClientHostName(const char* client_ip) {
const char * hostnames[5][2];
hostnames[0][0] = "122.205.26.34";
hostnames[0][1] = "aaaaa";
hostnames[1][0] = "120.205.36.30";
hostnames[1][1] = "bbbbb";
hostnames[2][0] = "120.205.16.36";
hostnames[2][1] = "ccccc";
hostnames[3][0] = "149.205.36.46";
hostnames[3][1] = "dddddd";
hostnames[4][0] = "169.205.36.33";
hostnames[4][1] = "eeeeee";
for(int i = 0; i<5; i++) {
if(!strcmp(hostnames[i][0], client_ip))
return hostnames[i][1];
}
return NULL;
}
int main(int argc, char* argv[]) {
const char * hostname = getClientHostName("128.205.36.34");
printf("%s\n", hostname);
}
答案 1 :(得分:2)
有没有更好的方法,我不必硬编码大小?
习惯使用GCC编译所有警告和调试信息:gcc -Wall -Wextra -g
。改进代码以完全不发出警告。
如果您想获得正版IP地址,这是特定于操作系统的(因为标准C11不了解IP地址;请阅读n1570)。在Linux上,您将使用名称服务例程,例如getaddrinfo(3)&amp; getnameinfo(3)或过时的gethostbyname(3)。
如果这只是与TCP / IP套接字没有实际关系的练习(请参阅tcp(7),ip(7),socket(7)),您可以将表存储在某些全局 array:
struct myipentry_st {
const char* myip_hostname;
const char* myip_address;
};
然后定义一个包含它们的global数组,其惯例是通过一些{NULL, NULL}
条目终止它:
const struct myipentry_st mytable[] = {
{"aaaaa", "122.205.26.34"},
{"bbbb", "120.205.36.30"},
/// etc
{NULL, NULL} // end marker
};
你最好有一个全球或static variable(而不是automatic一个坐在call stack上,因为你没有想要在每次致电getClientHostName
时填写。
然后你的查询程序(低效,因为在线性时间内)将是:
const char* getClientHostName(char* client_ip) {
for (const struct myipentry_st* ent = mytable;
ent->myip_hostname != NULL;
ent++)
// the if below is the only statement of the body of `for` loop
if (!strcmp(ent->myip_address, client_ip))
return ent->myip_hostname;
// this happens after the `for` when nothing was found
return NULL;
}
您甚至可以将该表声明为heap allocated指针:
const struct myipentry_st**mytable;
然后使用calloc
分配它并从某个文本文件中读取其数据。
阅读您正在使用的每个standard或外部函数的文档。不要忘记检查是否失败(例如calloc
,如here)。通过适当调用free
来避免memory leaks。使用调试器gdb
和valgrind。小心undefined behavior。
在现实世界中,您可能拥有数千个条目,并且您将多次执行查找(可能数百万次,例如,在Web服务器或客户端中每HTTP个请求一次)。然后选择更好的data structure(hash table或red-black tree或许)。阅读一些Introduction to Algorithms。
答案 2 :(得分:1)
将*
添加到类型定义char * hostnames[5][2]
。这必须是指针数组,而不是简单的char
s。另一个必要的更改是strcpy
,而不是=
中的strcpy( hostname, getClientHostName("122.205.26.34") );
。
PS:总是尝试编译0编译器警告,而不仅仅是0错误!