组态注意事项: 下面说明了关于在C脚本中处理字符串时最重要的问题。必须考虑性能和稳定性因素。在不一致时,内存区可能被覆写,从而使系统锁死 。最坏的情况出现在字符指针。如果指针设计不当,内存区可能被覆写。下面是有关错误和正确组态的四个样例。 没有预留内存区: char *a; a=GetTagChar("Tag name"); strcat(a,"xyz"); //有一个连接到文本的指针“a” //没有预留内存区- 正确: 通过查询有效的指针将字符串正确复制到预定义的缓冲器中(来自描述WinCC信息系统的样例):
- char* pszValue = NULL;
- char szValue[101];
- pszValue = GetTagChar("Varname"); //读标签值并将其缓存到pszValue。/*如果返回一个有效值,将该函数返回值存入局部字符串szValue中。最多保存100个字符。*/
- if(pszValue !=NULL) //!=NULL是必须执行的检查 //以便保证没有NULL指针提交
- {
- strncpy(szValue,pszValue,100); …
- }
- else
- {
- printf("Pointer invalid\r\n"); //使用了无效值
- }
- }
没有预留足够的内存区: 通常,由于预留的内存区太小导致内存被覆写。在这些情况下,通常在C中进行字符串处理时,文本结尾的一个附加字符必须始终被保留。也就是说,必须要比被处理的文本长度多预留出一个字符。- 错误: char a[4]; strcpy(a,"1234"); //总是有4个字符被复制到一个4字符的数组中; // 错误:文本的结尾字符被遗漏
- 正确: char a[5]; //内存区的大小必须 //总是比被复制的文本多一个字符 strcpy(a,"1234");
字符*作为项目函数的返回值无效: 如果在项目函数中返回“char*”,必须用“SysMalloc”预留相应的内存区。如果内存区是通过字符…[x]预留的,像“错误”例子中所描述那样,那么当 退出项目函数时内存区将立刻被释放,因此在进行进一步的动作处理时将传递的是无效的值。- 错误:
- char* new_function_1()
- {
- char myString[100];
- sprintf(myString,"VarName%d", GetTagWord("processvariable"));
- return myString;
- }
- 正确:
- char* new_function_1()
- {
- char* myString;
- myString = SysMalloc(100);
- sprintf(myString,"VarName%d", GetTagWord("processvariable"));
- return myString;
- }
没有Null指针检索的无效字符串拷贝(导致日志文件 - WinCC_Sys_xx.LOG中的“ExecuteError in Action” ) 当动作在执行并且图像被取消选定(目标未发现)时此条目出现在WinCC_Sys.Log中- 错误:
- char sign[5];
- strcpy(sign,GetText(lpszPictureName,lpszObjectName));
- if (0==strcmp(sign,"+"))
- {
- SetText(lpszPictureName,lpszObjectName,"-");
- SetVisible(lpszPictureName,"B5",TRUE);
- }
- else
- {
- SetText(lpszPictureName,lpszObjectName,"+");
- SetVisible(lpszPictureName,"B5",FALSE);
- }
为了避免无意的复制太多的字符到“sign” (例如在后来作改动时) ,并为了避免当取消选定图像时由于“strcpy()”导致的异常,在“strncpy()”复制到Null-指针之前应该使用和检查“strncpy()” 。 - 正确:
- char sign[5], *myPointer;
- myPointer = GetText(lpszPictureName,lpszObjectName);
- if(myPointer != NULL)
- {
- strncpy(sign, myPointer, 4);
- if (0==strcmp(sign,"+"))
- {
- SetText(lpszPictureName,lpszObjectName,"-");
- SetVisible(lpszPictureName,"B5",TRUE);
- }
- else
- {
- SetText(lpszPictureName,lpszObjectName,"+");
- SetVisible(lpszPictureName,"B5",FALSE);
- }
- }
- else
- {
- printf("Error in GetText() !\r\n");
- }
警告: 函数strcpy()将“Source”指针所指向的包含末尾字符'\0’的字符串复制到“Target”指针指向的位置。字符串不能 重叠,并且目标必须足够大 (源字符串长度 + 1,因为有'\0’)。函数strncpy()除了仅复制起始的n个字节外其余与函数strcpy()相同。如果起始的n个字节中没有'\0’,结果将不是以'\0’结束。这将导致未定义的系统状态。
用strcat函数来连接字符串。 假设有四个变量tag1,tag2,tag3,tag4都是8位文本字符变量。把tag1~tag3连接起来显示在tag4中。测试:先建立这四个变量,然后在wincc的画面中建立四个输入输出域,分别连接tag1~tag4,建立一个按钮,在按钮的c动作中: char buffer[256]=""; strcat(buffer,GetTagChar("tag1")); strcat(buffer,GetTagChar("tag2")); strcat(buffer,GetTagChar("tag3")); SetTagChar("tag4",buffer);
|