I'm writing an IP forwarding program, and I need to splice the following routing table into a char*
array
128.15.0.0 255.255.0.0 177.14.23.1
137.34.0.0 255.255.0.0 206.15.7.2
137.34.128.0 255.255.192.0 138.27.4.3
137.34.0.0 255.255.224.0 139.34.12.4
201.17.34.0 255.255.255.0 192.56.4.5
27.19.54.0 255.255.255.0 137.7.5.6
0.0.0.0 0.0.0.0 142.45.9.7
I have initialized an array of pointers to char*
like so char *routing[128][128];
, then I loop through each line, build a char temp[128]
array which then get's assigned to routing
as shown below.
In other words, each pointer in the routing
array will point to an IP address.
char *routing[128][128];
char line[128], temp[128];
int i = 0, j = 0, token_count = 0, line_count = 0;
while(fgets(line, sizeof(line), routing_table) != NULL){
// printf("%s\n", line);
token_count = 0;
for (i = 0; i < strlen(line); i++){
if (line[i] != ' ' && token_count == 2){
for (j = 0; j < 128; j++){
if (line[i+j] == ' ')
break;
temp[j] = line[i+j];
}
i += j;
routing[line_count][token_count] = temp; //ASSIGNMENT OCCURS HERE
token_count++;
}
else if (line[i] != ' ' && token_count == 1){
for (j = 0; j < 128; j++){
if (line[i+j] == ' ')
break;
temp[j] = line[i+j];
}
i += j;
routing[line_count][token_count] = temp;
token_count++;
}
else if (line[i] != ' ' && token_count == 0){
for (j = 0; j < 128; j++){
if (line[i+j] == ' ')
break;
temp[j] = line[i+j];
}
i += j;
routing[line_count][token_count] = temp;
token_count++;
}
}
line_count++;
}
The problem is that every time an assignment happens, it updates the entire array. So when I print out the array at the end, I get the last element repeated.
142.45.9.7
142.45.9.7
142.45.9.7
...
142.45.9.7
142.45.9.7
I figured I needed to dereference temp
but that threw a warning and didn't even fix it.
What do I have wrong syntactically? Why are all pointers pointing to the same char string?
答案 0 :(得分:2)
接近结尾,就在你增加token_count
的地方之前,你就有这条线:
routing[line_count][token_count] = temp;
这就是你的问题。 temp
是一个包含128个字符的数组 - 我们称之为C中的字符串,如果某处有一个空终结符。您依次将每个IP地址字符串复制到其中,然后对于每个IP地址字符串,将temp
的地址分配给您的一个大二维指针数组中的一个插槽。所有这些指针,但它们都指向相同的实际缓冲区。
因此,在循环结束时,它们都指向您复制到temp
的最后一个字符串。这不是你想要的,如果temp
是函数中的本地,那么你真的遇到了麻烦。
你想要的是一个二维数组的实际char数组(每个16个字符就足以用于点缀四边形和一个空终止符) - 但是我在C上有点生疏并且不会冒险导致你误入歧途关于如何声明 - 或者你需要为现有二维数组中的每个字符串分配新内存。在许多C实现中,你会这样做:
routing[line_count][token_count] = strdup(temp);
strdup()
是一个方便的函数,为你给它的字符串分配足够的内存,将字符串复制到该内存中,并返回指向它的指针。但它不是标准的一部分,所以在所有情况下都不能指望它。如果你正在为一个编译器编写它并且它就在那里,那么你们都已经设置好了(通常就是这种情况)。但是,如果您对可移植性有任何疑虑,here's a portable way to do the same thing。
是否可移植,您现在正在分配内存,当您完成路由表时,您需要通过在您获得的每个指针上调用free(routing[i][j])
来释放分配的内存从strdup()
(或从其他一些更便携的功能)返回。
为此,你应该在分配任何东西之前调用它:
memset(routing, 0, sizeof(char) * 128 * 128);
...其中128和128是数组的两个维度(我将它放在我用于循环和声明的#defined
常量中,如果我真的必须在C中执行此操作,并没有动态分配整个混乱)。如果你首先将整个事物设置为零,那么那里的每个指针都以NULL
开头。然后当你遍历它以释放内存时,你可以循环遍历每个“行”释放每个指针,直到你点击NULL
,然后停止。
答案 1 :(得分:2)
考虑另一种方法,它总是容易出错,解析命令行输出的ip地址,如ifconfig,route,ip等,为什么不用编程方式获取路由表信息呢?例如,在Linux上,RTNETLINK是操纵路由表的标准方法:
http://man7.org/linux/man-pages/man7/rtnetlink.7.html
它为您提供定义良好的结构中的所有信息。
在Windows上,您可以使用Win32 API执行相同的操作:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa365953(v=vs.85).aspx
答案 2 :(得分:0)
routing[line_count][token_count] = temp; //ASSIGNMENT OCCURS HERE
每次迭代时temp
数组的内容可能不同。
temp
数组的地址在整个程序执行过程中保持不变。
因此,您显然为routing
数组中的每个条目分配了相同的值。