你的函數調用getmask()
未定義行爲:
- 複製字符串參數轉換爲本地陣列
x
;
- 你用
strtok()
解析它,它返回一個指針到同一個本地數組x
。
- 您將此指針
mask
返回給調用者。一旦退出此功能,該指針就會失效。
您應該返回一個指向該數組的分配副本的指針,以便在返回到調用方後它仍然有效。
此外,你應該避免使用strtok()
,因爲它不是可重入的:正如你注意到的,你不能用這個函數實現嵌套的解析器。
其他功能都可以解析字符串:
strchr()
座落在一個字符串的字符;
strstr()
查找字符串中的子字符串;
strspn()
匹配字符串開頭的一組字符;
strcspn()
匹配字符串開頭的一組字符的補碼;
- 您還可以手動解析字符串,測試循環中的字符。
下面是一個例子:
#include <stdlib.h>
#include <string.h>
char *getmask(const char *s) {
/* allocate a copy of the mask part
* the mask starts after the first '/'
* and stops at the first space or another '/'
*/
len - 0;
s = strchr(s, '/');
if (s != NULL) {
s++;
len = strcspn(s, "/ \t\r\n");
}
/* allocate space for the mask string */
char *mask = malloc(len + 1);
if (mask != NULL) {
/* copy the mask string */
memcpy(mask, s, len);
mask[len] = '\0';
}
return mask;
}
功能是麻煩的,但非常精確。它的行爲幾乎與strtok()
所預期的相同,唯一的區別是處理多個連續的/
字節,其中strtok()
會跳過,而strchr()
不會。
這裏是sscanf()
替代:
#include <stdlib.h>
#include <string.h>
char *getmask(const char *s) {
char mask[256];
/* skip characters different from /, then skip slashes, then
* copy characters until another/or whitespace
*/
if (sscanf(s, "%*[^/]%*[/]%255[^/ \t\n]", mask) != 1) {
*mask = '\0';
}
return strdup(mask); /* POSIX function to allocate a copy of a string */
}
這是很簡單的,但如果字符串以/
啓動失敗。
strdup()
是一個非常有用的函數來分配一個字符串的副本。它在POSIX兼容系統上可用。這你不用它,它可以能夠很容易地實現:通過getmask()
分配應被釋放
#include <stdlib.h>
#include <string.h>
char *strdup(const char *s) {
char *p = malloc(strlen(s));
if (p != NULL) {
strcpy(p, s);
}
return p;
}
字符串由free()
當不再需要。
在調用getmask()
之前,可以使用類似的方法將輸入字符串解析爲ip/mask地址對。
你也可以提供一個目標緩衝區,以getmask()
以避免內存管理的複雜性:
char *getmask(char *dest, size_t size, const char *s) {
if (dest != NULL && size > 0) {
char mask[256];
/* skip characters different from /, then skip slashes, then
* copy characters until another/or whitespace
* dest cannot be used directly because size cannot be passed
* sscanf easily
*/
*dest = '\0';
if (sscanf(s, "%*[^/]%*[/]%255[^/ \t\n]", mask) != 1) {
strncat(dest, mask, size - 1);
}
}
return dest;
}
解析是棘手,因爲你必須要小心處理所有案件。規範通常不夠精確,所以實施者必須針對特殊情況做出選擇。 C庫提供的用於解析的工具老舊笨重,特別是strtok()
,sscanf()
。使用這些時要小心,即使是有經驗的程序員也會因其副作用和缺點而被咬傷。
你是以'net = strtok(NULL,「」)'開始的嗎?問題描述很混亂。用輸入和輸出顯示最小程序。 –
對不起,第一個strtok是在此之前。我將編輯 – Andrei
'strtok'作爲狀態機運行,所以每個呼叫都有狀態。爲了分割一系列空格分隔的令牌和'/'分隔的令牌的子集,您需要防止狀態發生衝突。這可以通過迭代兩次完成,或者如@Ludonope – Aaron3468