WinCC 腳本中需解析形如 "DB10.DBW0,VariableName,DataType,Unit" 的逗號分隔字符串,提取地址、名稱、單元等字段供後續變量操作使用。
void CTxtDemDlg::GetAddressAndUnit(char* str, char* Add, char* Unit, char* Name) {
char* p;
char delim = ',';
p = strtok(str, &delim); // 第一次調用傳入源字符串
strncpy(Add, str, strlen(p)); // 第1段:地址
Add[strlen(p)] = '\0'; // 確保結尾
int i = 0;
while (p != NULL) {
p = strtok(NULL, ","); // 後續調用傳 NULL 續解析
if (!p) break;
i++;
if (i == 1) { // 第2段:名稱
strncpy(Name, p, strlen(p));
Name[strlen(p)] = '\0';
} else if (i == 3) { // 第4段:單元
strncpy(Unit, p, strlen(p));
Unit[strlen(p)] = '\0';
break; // 取完目標段提前退出
}
}
}
| 調用形式 | 行為 | 注意事項 |
|---|---|---|
strtok(str, delim) | 首次調用,從 str 開頭查找分隔符,將分隔符替換為 '\0',返回 token 起始指針 | 會修改原字符串,若需保留原串請先 strcpy 複製 |
strtok(NULL, delim) | 後續調用,從上次 '\0' 後繼續查找 | 線程不安全,內部靜態指針記錄位置;多線程用 strtok_r |
返回 NULL | 無更多 token | 循環終止條件 |
strncpy 不自動加 '\0',必須手動補齊 dest[len]='\0'。char buf[256]; strcpy(buf, src); GetAddressAndUnit(buf, ...);strtok 第二參數是「分隔符字符集合」,"," 與 ",;" 效果不同,後者同時以逗號、分號分割。"A,,B" 中間空段會被跳過,strtok 不返回空 token。若需保留空字段,請手寫分割邏輯。
int split_string(const char* src, const char* delim, char** out, int max_fields) {
int count = 0;
const char* p = src;
while (*p && count < max_fields) {
const char* start = p;
while (*p && !strchr(delim, *p)) p++;
int len = p - start;
out[count] = (char*)malloc(len + 1);
memcpy(out[count], start, len);
out[count][len] = '\0';
count++;
if (*p) p++; // 跳過分隔符
}
return count;
}
WinCC C 腳本中 strtok 便捷高效,但修改原串、線程不安全、跳過空字段三大特性必須心中有數。關鍵業務建議用手寫分割函數替代,獲得完全可控的行為。