項目中需要實現對文件內容進行修改,所以有了以下的測試程序,其中遇到了很多問題,在這一一記錄下來。
其實實現原理很簡單,首先是要實現定位到所需要的字段的那一行,之後再對指定字段進行修改。在我接觸了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.此處每行結束的時候不留多餘空格(至於爲什麼這麼處理,下面再做說明)
比如,我想將00:00:00:00:00:01對應的ip地址修改成192.168.1.5
其實現代碼如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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(換行符)
雖然不是通過修改代碼來解決問題的,但這也是解決方法的一種,不是嗎?