项目中需要实现对文件内容进行修改,所以有了以下的测试程序,其中遇到了很多问题,在这一一记录下来。
其实实现原理很简单,首先是要实现定位到所需要的字段的那一行,之后再对指定字段进行修改。在我接触了shell编程后,觉得shell编程会很容易实现(网上说可以用sed命令,还没接触过,有时间再弄弄)。但是由于C语言是面向过程的语言,需要顺序执行的特点,所以,实现中遇到了很多麻烦。
首先,需要修改的文件—data文件的内容如下:
00:00:00:00:00:00-192.168.1.1
00:00:00:00:00:01-192.168.1.2
00:00:00:00:00:02-192.168.1.3
00:00:00:00:00:03-192.168.1.4
ps:1.每行的内容为一组数据,-前面的内容为mac地址, -后面的内容为对应的ip地址。
2.此处每行结束的时候不留多余空格(至于为什么这么处理,下面再做说明)
我想实现的功能是:对我指定的mac地址对应的ip地址进行修改。
比如,我想将00:00:00:00:00:01对应的ip地址修改成192.168.1.5
其实现代码如下:
#include #include #include typedef struct localaddr
{
char mac[18];
char ip[16];
}LOCALADDR;
int main()
{
FILE *fp;
char line_buf[512], buf1[512], buf2[512];
int line_len, len;
LOCALADDR localaddr;
strcpy(localaddr.mac, "00:00:00:00:00:01");
strcpy(localaddr.ip, "192.168.1.5");
if((fp = fopen("data", "r+")) == NULL)
{
perror("fopen");
exit(1);
}
while(fgets(line_buf, 512, fp))
{
line_len = strlen(line_buf);
len += line_len;
sscanf(line_buf, "%[^-]-%[0-9,.]", buf1, buf2); //将-之前的内容(mac地址)赋值给buf1,之后的内容(ip地址)给buf2
if(!strcmp(localaddr.mac, buf1))
{
len -= (strlen(line_buf) + 1); //计算出那一行的行首位置
printf("len = %d\n", len);
if(fseek(fp, len, SEEK_SET) < 0) //定位
{
perror("fseek");
exit(1);
}
strcpy(buf2, localaddr.ip);
strcat(buf1, "-");
strcat(buf1, buf2);
fprintf(fp, "%s", buf1);
fclose(fp);
return ;
}
}
exit(0);
}
编译执行后,data文件的内容变成:
00:00:00:00:00:00-192.168.1.1
00:00:00:00:00:01-192.168.1.5
00:00:00:00:00:02-192.168.1.3
00:00:00:00:00:03-192.168.1.4
测试成功。
Now,come the question:
如果ip地址要求修改成192.168.1.123时,程序编译执行后,data文件内容却变成了:
00:00:00:00:00:00-192.168.1.1
00:00:00:00:00:01-192.168.1.1230:00:00:00:00:02-192.168.1.3
00:00:00:00:00:03-192.168.1.4这是怎么了?
分析:
ip的主机地址字段由原来的“2”变成“5”的时候,长度没有发生变化,所以直接覆盖了原来的“2”,其他无变化。
但是,当“2”变成“123”的时候,长度不一致,需要多占用2个字节,所以除了“123”中的“1”覆盖了原来的“2”之外,“123”中的“2”占用了换行符的空间,导致第三行的内容跑上了第二行,而“123”中的“3”把原来第三行的第一个“0”的空间占据了,所以出现了以上这种意外。
解决方法:
我的解决方法也很简单,就是确保data文件内每行的长度都>=34 即:17(mac地址长度)+15(ip地址最大长度)+1(一个“-”)+1(换行符)
虽然不是通过修改代码来解决问题的,但这也是解决方法的一种,不是吗?