LR字符串处理

复制代码


Action()
{

strchr和strrchr:
 //strchr:查找指定字符在一个字符串中第一次出现的位置,然后返回指向该位置的指针。
 //char *strchr(const char *string,int c);
 //strrchr:查找指定字符在一个字符串中最后一次出现的位置,然后返回指向该位置的指针。
 //char *strrchr(const char *string,int c);
 /*
    char *string ="I am a young soul in this very strange world.";
    char *first_a,*last_a;
    first_a = (char *)strchr(string,'a');
    lr_output_message("The first occurrence of a:%s",first_a);

 last_a = (char *)strchr(string,'a');
    lr_output_message("The first occurrence of a:%s",first_a);
 */

strcpy和strncpy:

 //strcpy:将一个字符串复制到另一个字符串中。
 //char * strcpy (char *dest,const char * source)
 // dest是目标字符串,source是源字符串。
 //strncpy:将一个字符串中指定长度复制到另一个字符串中。
 //char * strcpy (char *dest,const char * source,size_t n);
 // dest是目标字符串,source是源字符串,n是要复制的长度。
/*
 char test[50];
 char ntest[50];
 strcpy(test,"Copies one string to anther.");
 lr_output_message("%s",test);

 strncpy(ntest,"Copies one string to anther.",10);
 lr_output_message("%s",ntest);
*/

strcmp和stricmp
 //strcmp与stricmp:按照字符表顺序来比较两个字符串的大小,前者区分大小写。
 //int strcmp(const char *string1,const char *string2);
 //int stricmp(const char *string1,const char *string2);
/*
 int result;
 char tmp[20];
 char string1[]="He is a test";
 char string2[]="He is a TEST";
 result = strcmp(string1,string2);
 if(result>0){
  strcpy(tmp,"greater than");
 }else if(result <0){
  strcpy(tmp,"less than");
 }else{
  strcpy(tmp,"equal to");
 }
 lr_output_message("strcmp:String1 is %s string2",tmp);

 result = stricmp(string1,string2);
 if(result>0){
  strcpy(tmp,"greater than");
 }else if(result <0){
  strcpy(tmp,"less than");
 }else{
  strcpy(tmp,"equal to");
 }
 lr_output_message("strcmp:String1 is %s string2",tmp);
*/

strcat和strncat
 //strcat:字符串连接函数。全部内容复制到另一个字符串的后面;
 //char *strcat(char *to_string,const char *from_string);
 //to_string是目标字符串,form_string是源字符串。
 //strncat:字符串连接函数。把字符串的指定长度复制到另一个字符串的后面。
 //char *strncat(char *to_string,const char *from_sring,size_t n);
/*
 char str1[]="This is ";
 char str2[]="a ";
 char str3[]="strcat&strncat ";
 char str4[]=" test!";
 lr_output_message("The str1 is:%s",str1);

 strcat(str1,str2);
 lr_output_message("The str1 is:%s",str1);

 strncat(str1,str3,6);
 lr_output_message("The str1 is:%s",str1);

 strncat(str1,str4,5);
 lr_output_message("The str1 is:%s",str1);
*/
 return 0;
}
复制代码

 

复制代码
Action()
{

sprintf:
 //sprintf:把一个字符串格式化后输入到另一个字符串中,与printf区别是sprintf输出结果到指定的字符串中。
 //int sprintf (char *string,const char *format_string[,args]);
 //string要写入的目标字符串,format_string是格式化的字符串,args是一系列的变量表达式。
/*
 char test[30];
    int a=2,b=8;
    sprintf(test,"Add Test:a=%d,b=%d,a+b=%d.\0",a,b,a+b);
    lr_output_message(test);
*/

strlwr和strupr:
 //strlwr:把字符串全部变成小写。
 //char *strwr(char *string);
 //strupr:把字符串全部变成大写。
 //char *strupr(char *string);
 //注意:源字符串已经变成小写或者大写,发生了内容改变,函数返回的是指向源字符串的指针,不是一个新的字符串。
/* int id;
 char str[]="ThIS is A TeST";
 char *lowerstr,*upperstr;
 lowerstr =(char *)strlwr(str);
 lr_output_message("lowerstr=%s",lowerstr);
 lr_output_message("str=%s",str);

 upperstr =(char *)strupr(str);
 lr_output_message("lowerstr=%s",upperstr);
 lr_output_message("str=%s",str);
*/

atoi和itoa:
 //atoi:把字符串转换为一个整数。
 //char *atoi(const char *string);
/* int j;
 char *s="aaa 111 bbb 222";
 j=atoi(s);
 lr_output_message("Result:%d",j);//对于以非数字开始的字符串,不能转换时,返回0。

 s = "111 bbb 222";
 j=atoi(s);
 lr_output_message("Result:%d",j);//对于前半部分以数字开始,后半部分以非数字字符结束的,能把开始的一部分数字转换为整数。
*/
 //itoa:把整数转换为一个字符串。
 //char *itoa(int value,char *string,int radix);
 //value是要转换的整数,string是用来保存转换结果的字符串,radix是转换的进制。
/* int i=56;
 char str_int[10],str_hex[10];
 itoa(i,str_int,10);
 lr_output_message("New file name %s",str_int);

 itoa(i,str_hex,16);
 lr_output_message("New file name %s",str_hex);
*/
 return 0;
}
复制代码

 

复制代码
Action()
{
strlen:
 //strlen:用于返回指定字符串的字符个数。注意:计算长度遇到“\0”就会停止计算。
    //因此Socket脚本中不能使用strlen来计算可能包含"\0"的数据包长度。
    //char *strlen(const char *string);
/*
    char *str = "This is a test!";
    unsigned int len;
    len = strlen(str);
    lr_output_message("The sentence has %d letters",len);

 str ="This is a test!\0abcde";
 len =strlen(str);
 lr_output_message("The sentence has %d letters",len);
*/
memcpy:
 //memcpy:内存缓冲区复制数据,可以复制二进制数据。而strncpy是复制字符串,不能复制中间存在的“\0”的数据。
 //void *memcpy(void *dest,const void *src,size_t n);
/*
 char src[]="AAAAA \0 This is a test.\0";
 char memcpy_str[25];
 char strncpy_str[25];
 memcpy(memcpy_str,src,25);
 strncpy(strncpy_str,src,25);
 lr_output_message("memcpy_str: %s",memcpy_str);
 lr_output_message("strncpy_str: %s",strncpy_str);

 lr_output_message("memcpy_str: %s",memcpy_str+8);
 lr_output_message("strncpy_str: %s",strncpy_str+8);
*/
memset:
 //memset:对数据对象做初始化工作。
 //void *memset(void *buffer,int c,size_t n);
 //把buffer执向的某一块内存中的每个字节的内容全部设置为参数C所指定的ASCII值,块得大小由第三个参数n来指定。
/*
 char buffer[]="This is a test!\n";
 lr_output_message("Buffer before memset:%s",buffer);
 memset(buffer,'a',strlen(buffer) - 1);
 lr_output_message("Buffer after memset:%s",buffer);
*/
sizeof:
 //sizeof:返回指定表达式、变量或指定数据类型在内存中所占有的字节数。
 //size_t sizeof expression
 //size_t sizeof (type)
/*
 char test[10];
 struct str_test{
  char str[10];
  int i;
 };
 struct str_test mystr;
 lr_output_message("\"abcde\"size=%d",sizeof "abcde");
 lr_output_message("\"12345\"size=%d",sizeof (12345));
 lr_output_message("\"test\"size=%d",sizeof test);
 lr_output_message("\"mystr\"size=%d",sizeof (mystr));
*/
 return 0;
}
复制代码

 

 

 LoadRunner中常用的字符串操作函数有:

               strcpy(destination_string, source_string);

               strcat(string_that_gets_appended, string_that_is_appended);

               atoi(string_to_convert_to_int); //returns the integer value

               itoa(integer_to_conver_to_string, destination_string, base); // base is 10

               strcmp(string1, string2); // returns 0 if both strings are equal

对各函数的定义:

             strcpy( ):拷贝一个字符串到另一个字符串中.

             strcat( ):添加一个字符串到另一个字符串的末尾。

            strcmp( ):比较两个字符串,如果相等返回0。

            atoi():转换一个ASCII字符串为一个整型。

            itoa():根据给定的进制,转换一个整型数据为ASCII字符串

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
明确LoadRunner可以输出的结果
 
最近刚刚忙完一个项目的测试,又开始闲了起来,还是琢磨琢磨一些东西,给大家一些参考!
 
PS:本人在51testing和sina blog上的文章全部为原创,转载请注明出处!!
 
  
 
我们都知道软件的功能其实就是输入和输出,有了输入就有输出;例如你做了一个操作,可能返回一个提示,也可能打开一个新的窗口;而测试,其实就是组合输入,确认各种输出的正确性,就像测试一个函数,你组合不同的输入参数值,达到遍历函数的所有路径,并返回对应的值。
 
熟知loadrunner可以输出哪些结果,对我们对整个测试过程把握非常重要,当然也是测试分析中很重要的数据
 
Loadrunner脚本的执行也是一种测试输入,我们通常可以获得那些输出呢?(这些只是我总结的,实际可能不只这些哈!)
 
先说说脚本回放过程:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1、message系列函数
详见:《message函数详细分析》
http://www.51testing.com/?6343/action_viewspace_itemid_13643.html
 
2、写log文件
    写log文件主要是使用c语言的函数来进行,涉及的函数有fopen、fclose、fprintf这三个;     
    写一个例子给大家:
========================================================
Action()
\\先在D盘根目录创建一个文件夹,名为:“lr_log”
{
    char *address="D:\\lr_log\\01.log"; //定义log文件输出的地址和名称
    long filename;//定义存储文件指针的变量
    int i;
    if ((filename=fopen(address,"a+"))==NULL)//打开文件
    {
        lr_error_message("can not open this file,address=%s",address);
        return -1;
    }
    for (i=1;i<11;i++)
    {
        fprintf(filename,"我的第%d条log...\n",i);
    }
    fclose(filename);//关闭文件
    return 0;
}
=======================================================
脚本回放完毕去D盘lr_log文件夹下打开01.log文件,得到结果:
我的第1条log...
我的第2条log...
我的第3条log...
我的第4条log...
我的第5条log...
我的第6条log...
我的第7条log...
我的第8条log...
我的第9条log...
我的第10条log...
 
3、被测试程序的实际输出
   这个就不难理解了,查看是否输出了具体的值或者执行的操作; :)
 
  
 
 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
场景监视过程:
1、vuser的log
   Loadrunner场景监视过程中,是可以查看某个vuser运行的log的;
   具体的操作步骤:
   A、打开vuser信息窗口(双击用户组中运行的vuser即可打开窗口)
   B、选择你要查看的vuser的信息,右键选择Show vuser log
   C、可以查看vuser的log了,这里的log不能显示lr_message、lr_log_message输出的log
   适当的增强脚本的log输出,可以让我们在vuser执行脚本出现问题时,准确的定位问题的位置;
   例如,在使用参数化用户名和密码登录某系统,脚本中使用lr_output_message打印出当前的参数值,如果登录失败,那么用手动去登录试试,这样就能检查出是否是参数的数据有问题了;如果结合返回的错误来进行判断,那就更完美了。举个例子吧:
 
我输入一个网址,网址中包含若干参数(ID、password),网址提交后IE返回登录结果(A\X\Z\D);返回A代表登录成功,返回X代表登录失败,返回Z和D是其他情况;
/*********************************
  * Author:qiguojie
  * object:software login
  * date:2007-5-28
***********************************/
Action()
{
//变量定义区
    typedef long time_t;       //定义一个时间变量
    time_t t;        //定义一个时间变量
    web_reg_save_param("IsRight","LB=Cache-control: private\r\n\r\n","RB=|",LAST);  //保存返回值
    time(&t);        //获取当前时间
    web_url("abclogin.asp",
        "URL=http://192.168.1.9/soft/abclogin.asp?U={user}&P={password}&L=0&H=3HS28QKH",
        "Resource=0",
        "RecContentType=text/html",
        "Referer=",
        "Snapshot=t1.inf",
        "Mode=HTML",
        LAST);
    lr_output_message("%s,随机数是%d,",ctime(&t),n);
    lr_output_message("用户是:%s,密码是:%s,",lr_eval_string("{user}"),lr_eval_string("{password}"));
//判断返回值,输入对应日志
    if (strcmp(lr_eval_string ("{IsRight}"),"A") == 0)//如果返回值是A
    {
        lr_output_message("success:用户登录成功,返回值是:%s",lr_eval_string("{IsRight}"));
    }
    else if (strcmp(lr_eval_string ("{IsRight}"),"X") == 0) //如果返回值是X
    {
        lr_output_message("failed:用户登录失败,返回值是:%s\n",lr_eval_string("{IsRight}"));
    }
    else if (strcmp(lr_eval_string ("{IsRight}"),"Z") == 0)//如果返回值是Z
    {
        lr_output_message("success_others:登录特殊页成功,返回值是:%s\n",lr_eval_string("{IsRight}"));
    }
    else //如果返回值是D
    {
        lr_output_message("success_free:登录免费用户成功,返回值是:%s\n",lr_eval_string("{IsRight}"));
    }
    return 0;
}
 
 
2、事务执行情况
   在controllor里执行场景时,是可以即时监视事务的执行情况的,单击Run选项卡里Passed或Failed Transactions后面的放大镜图标,就可以打开;
   可以监视的参数如下:
   A、不同事务的tps
   B、不同事务的Passed、Failed以及Stopped状态数
   TPS(Transactions per second):每秒事务数,衡量目前场景执行过程中的事务处理速度,越大说明目前事务执行效率越高;当然,你的事务中包含多个函数还是只有web_url一个函数,这个tps肯定是不同的,所以我只拿这个指标做监视用;
 
 
3、ERROR
   在controllor里执行场景时出现错误,是可以即时查看错误信息的,,单击Run选项卡里的Errors后面的放大镜图标,可以打开;另外还可以通过菜单view-show output来打开
   具体的功能大家就自己发掘吧,呵呵
 
当然,结果分析(Analysis)是lr最重要的输出,具体也就不介绍了;论坛和博客里有很多帖。

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
最近在论坛上看到有人提问LoadRunner如何对两个字符串进行比较,其脚本中两个字符串进行比较结果总是不一样的。我把问题整理了一下以便注意这个容易被忽略的错误。
脚本如下:
...
lr_save_string( "Hello World!","string1" );
lr_save_string( "Hello World!","string2" );
result = strcmp("string1","string2");
if ( result == 0 )
{
   lr_output_message("the result is 0.");
}
else
{
   lr_output_message("the result is not 0.");
}
大家可以看出脚本那里错了吗?
问题错在result = strcmp("string1","string2");这个上,这样变成了对字符串"string1""string2"的比较,而不是对变量的值进行比较,因此比较结果肯定是不一样的。
 
正确的写法有两种:
result = strcmp(&string1,&string2);
result = strcmp(lr_eval_string("{string1}"),lr_eval_string("{string2}")); 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
strcmp() 用来比较字符串(区分大小写),其原型为:
    int strcmp(const char *s1, const char *s2);<br><br>【参数】s1, s2 为需要比较的两个字符串。
 
 字符串大小的比较是以ASCII 码表上的顺序来决定,此顺序亦为字符的值。strcmp()首先将s1 第一个字符值减去s2 第一个字符值,若差值为0 则再继续比较下个字符,若差值不为0 则将差值返回。例如字符串"Ac""ba"比较则会返回字符"A"(65)和'b'(98)的差值(-33)。
 
 【返回值】若参数s1 和s2 字符串相同则返回0。s1 若大于s2 则返回大于0 的值。s1 若小于s2 则返回小于0 的值。
 
 注意:strcmp() 以二进制的方式进行比较,不会考虑多字节或宽字节字符;如果考虑到本地化的需求,请使用 strcoll() 函数。
 
 【实例】对 4 组字符串进行比较。
 
 
 
 
 
 
#include <string.h>
main()<br>{
    char *a = "aBcDeF";
    char *b = "AbCdEf";
    char *c = "aacdef";
    char *d = "aBcDeF";
    printf("strcmp(a, b) : %d\n", strcmp(a, b));
    printf("strcmp(a, c) : %d\n", strcmp(a, c));
    printf("strcmp(a, d) : %d\n", strcmp(a, d));
}
 
 
输出结果:
strcmp(a, b) : 32
 strcmp(a, c) :-31
 strcmp(a, d) : 0

strcmp

C/C++函数,比较两个字符串
设这两个字符串为str1,str2,
若str1==str2,则返回零;
若str1>str2,则返回正数;
若str1<str2,则返回负数。
 
当s1<s2时,返回为负数
当s1=s2时,返回值= 0
当s1>s2时,返回正数
即:两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇'\0'为止。如:
"A"<"B" "a">"A" "computer">"compare"
特别注意:strcmp(const char *s1,const char * s2)这里面只能比较字符串,即可用于比较两个字符串常量,或比较数组和字符串常量,不能比较数字等其他形式的参数。
ANSI标准规定,返回值为正数,负数,0 。而确切数值是依赖不同的C实现的。

 

posted @   Agoly  阅读(1160)  评论(0编辑  收藏  举报
编辑推荐:
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
阅读排行:
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 趁着过年的时候手搓了一个低代码框架
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!
点击右上角即可分享
微信分享提示