请教字符串的问题~~

时间:2023-01-07 15:53:22
今天写了一个字符串处理函数
功能是
批字符串中形如"%3C"的字符转换为'<'
即把 '%十六进制' 转为 ascii

代码如下:



#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*将'%十六进制'的数转化为ascii*/
char *url_unencode(char *dest, char *source)
{
int ascii = 0; //转化后的ascii
char *p = source; //p指向source串头
char *q = dest; //q指向dest串头
char buf[9] = {0}; //缓冲区, 用于存储得到的16进制数

/*循环以找到串中的'%'*/
while(*p != '\0') {

if(*p == '%' && *(p+1) != '%' && *(p+2) != '%') {

memcpy(buf, p+1, 2); //将16进制数存储到buf中
ascii = strtol(buf, NULL, 16); //16进制转化为整型ascii
//printf("%s\n", buf);
*q = toascii(ascii); //转换后的ascii存入dest

p = p+3; //p指向未转换的串首
q = q+1;
} else {
*q = *p; //非十六进制数直接copy处理
p++;
q++;
}
}

return dest;
}

int main(void) 
{
char *source = "1312783897324%3C%2Fstring%3E%3Cobject%20name%3D%22attrs%22%3E%3Cstring%20name%3D%22account%22%3E%22%E5%B7%B4%E6%9C%9D%E5%8D%8E%22%26lt%3Bfdrdgg%40126.com%26gt%3B%3C%2Fstring%3E%3Cboolean%20name%3D%22showOneRcpt%22%3E%2Fstring%3E%3Cboolean%20name%3D%22isHtml%22%3Etrue%3C%2Fboolean%3E%3Cstring%20name%3D%22content%22%3E%26lt%3Bdiv%20style%3D'line-height%3A1.7%3Bcolor%3A%23000000%3Bfont-size%3A14px%3Bfont-family%3Aarial'%26gt%3B444444444444444444444%26n%22%3Edeliver%3C%2Fstring%3E%3C%2Fobject%3E";

char *dest = (char *)malloc(1000);
// char *result = NULL;

memset(dest, '\0', 1000);
url_unencode(dest, source);

printf("the dest is:\n%s\n", dest);
free(dest);

return EXIT_SUCCESS;
}



但是运行结果总是不正确,,,开头有问题
希望得到的结果是  1312783897324<\string><object name 等  但运行结果总没有这一段

用gdb调试也没发现问题

坐等高手~~~

本人是在ubuntu 10. 10下做的  gcc 

17 个解决方案

#1


神马情况,没人看 呜~~
顶起~~

#2


单步调试,看一下每次存取的结构是否是楼主想要的

#3


嗯 我试过了  gdb每一次的结果都正确 ,但运行的时候却出错~~

#4


实验室没有GCC不过在VC6.0下面前面的运行结果是对的
就是吧 *q = toascii(ascii);   换成 *q = ascii;     就行了啊

#5


同意,改成

            ascii = strtol(buf, NULL, 16);        //16进制转化为整型ascii
            *q = ascii;                /* 上面已经得到ascii了,为什么还要用toascii()? */

之后是正确的。
引用 4 楼 hnuqinhuan 的回复:
实验室没有GCC不过在VC6.0下面前面的运行结果是对的
就是吧 *q = toascii(ascii);   换成 *q = ascii;     就行了啊

#6


按楼上的方法果然好用了~~~
toascii函数干了什么,,呵呵
看来还是没整明白这个函数哪

#7


    char *dest = (char *)malloc(1000);
    char *result = dest;

    memset(dest, '\0', 1000);
    url_unencode(dest, source);
    
    while (*result != '\0'){
      putchar (*(result++));
      putchar (' ');
    }
    puts("");
    printf("the dest is:\n%s\n", dest);
    free(dest);

首先把main改成这样,你会发现,putchar打印出来的每个char是正确的。我在你的url_unencode用putchar打印,发现第71 72个char(之后也有一些)错误,对照你的string,就可以看到那些%号搜ascii表有问题。
其实再仔细观察,你会发现67 68 69 70虽然可以打印正确,但是打印的分别是e 7 4 f。你可以观察67位,就是string中的%E5变成二进制是11100101,而e在ascii表中真正的是%65即01100101。你可以注意到是只第一位不同,你还可以注意到ascii表第一位都是0。
换言之,错误原因,你的string从第67个char就错了,ascii搜不到正确的字符,有些只能用奇怪的字符代替。所以最后printf打印错误。

具体怎么改正,你要改string的内容咯~

#8


引用 4 楼 hnuqinhuan 的回复:
实验室没有GCC不过在VC6.0下面前面的运行结果是对的
就是吧 *q = toascii(ascii);   换成 *q = ascii;     就行了啊


查了一下  toascii()函数   

toascii(将整型数转换成合法的ASCII 码字符)  
相关函数  isascii,toupper,tolower
 
表头文件  #include<ctype.h>
 
定义函数  int toascii(int c)
 
函数说明  toascii()会将参数c转换成7位的unsigned char值,第八位则会被清除,此字符即会被转成ASCII码字符。
 
返回值  将转换成功的ASCII码字符值返回。
 
范例  #include<stdlib.h>
main()
{
int a=217;
char b;
printf(“before toascii () : a value =%d(%c)\n”,a,a);
b=toascii(a);
printf(“after toascii() : a value =%d(%c)\n”,b,b);
}
 
执行  before toascii() : a value =217()
after toascii() : a value =89(Y)



意思不就是 217   1101 1001  转换为了
                  89      0101 0001
 把第八位去掉了变成了unsigned

而我获得的ascii值应该都是小于 128的,,,
用toascii怎么会不行呢

#9


toascii:
Pointer to a 256-byte array that contains the current keyboard state. Each element (byte) in the array contains the state of one key. If the high-order bit of a byte is set, the key is down (pressed). 
The low bit, if set, indicates that the key is toggled on. In this function, only the toggle bit of the caps lock key is relevant. The toggle state of the num lock and scroll lock keys is ignored. 

#10


引用 6 楼 a_sum_of_money 的回复:
按楼上的方法果然好用了~~~
toascii函数干了什么,,呵呵
看来还是没整明白这个函数哪
toascii是搜索ascii表来转换的。如果你不用这个,你还是按楼上说的方法直接改正吧。方便点。

#11


引用 7 楼 baby313 的回复:
C/C++ code
    char *dest = (char *)malloc(1000);
    char *result = dest;

    memset(dest, '\0', 1000);
    url_unencode(dest, source);
    
    while (*result != '\0'){
      putchar (*(result++)……



哥们 观察的真是仔细啊~~~

字符串中有如%E5 这样的字符,用toascii()转换后从1110 0101   变成了  0110 0101所以有错~~~

还让我纠结的是 source中的"1312783897324"这此字符和toascii没有关系 怎么也打印不出来 呢

#12


呵呵,理论上,能替换了倒也没错,关键是替换不了的,弄一下奇怪的字符串,就很麻烦了。
引用 11 楼 a_sum_of_money 的回复:
引用 7 楼 baby313 的回复:

C/C++ code
char *dest = (char *)malloc(1000);
char *result = dest;

memset(dest, '\0', 1000);
url_unencode(dest, source);

while (*result != '\0'){
putchar (*(result++)……

#13


你把%8D去掉试试
引用 11 楼 a_sum_of_money 的回复:
引用 7 楼 baby313 的回复:

C/C++ code
char *dest = (char *)malloc(1000);
char *result = dest;

memset(dest, '\0', 1000);
url_unencode(dest, source);

while (*result != '\0'){
putchar (*(result++)………

#14


引用 13 楼 shi3590 的回复:
你把%8D去掉试试
引用 11 楼 a_sum_of_money 的回复:
引用 7 楼 baby313 的回复:

C/C++ code
char *dest = (char *)malloc(1000);
char *result = dest;

memset(dest, '\0', 1000);
url_unencode(dest, source);

while ……


嗯这样能打出来了,,求解释

#15


顶起啊~~让高手们看到

#16


因为8D进行toascii()转换后是回车,相当于0D。
指针遇到回车重新指向回车后的地址,所以回车前的数据全部丢失。

#17


引用 16 楼 shi3590 的回复:
因为8D进行toascii()转换后是回车,相当于0D。
指针遇到回车重新指向回车后的地址,所以回车前的数据全部丢失。


指针指向回车的情况还真的没遇到过。。。我得好好思考下
多谢啦~

#1


神马情况,没人看 呜~~
顶起~~

#2


单步调试,看一下每次存取的结构是否是楼主想要的

#3


嗯 我试过了  gdb每一次的结果都正确 ,但运行的时候却出错~~

#4


实验室没有GCC不过在VC6.0下面前面的运行结果是对的
就是吧 *q = toascii(ascii);   换成 *q = ascii;     就行了啊

#5


同意,改成

            ascii = strtol(buf, NULL, 16);        //16进制转化为整型ascii
            *q = ascii;                /* 上面已经得到ascii了,为什么还要用toascii()? */

之后是正确的。
引用 4 楼 hnuqinhuan 的回复:
实验室没有GCC不过在VC6.0下面前面的运行结果是对的
就是吧 *q = toascii(ascii);   换成 *q = ascii;     就行了啊

#6


按楼上的方法果然好用了~~~
toascii函数干了什么,,呵呵
看来还是没整明白这个函数哪

#7


    char *dest = (char *)malloc(1000);
    char *result = dest;

    memset(dest, '\0', 1000);
    url_unencode(dest, source);
    
    while (*result != '\0'){
      putchar (*(result++));
      putchar (' ');
    }
    puts("");
    printf("the dest is:\n%s\n", dest);
    free(dest);

首先把main改成这样,你会发现,putchar打印出来的每个char是正确的。我在你的url_unencode用putchar打印,发现第71 72个char(之后也有一些)错误,对照你的string,就可以看到那些%号搜ascii表有问题。
其实再仔细观察,你会发现67 68 69 70虽然可以打印正确,但是打印的分别是e 7 4 f。你可以观察67位,就是string中的%E5变成二进制是11100101,而e在ascii表中真正的是%65即01100101。你可以注意到是只第一位不同,你还可以注意到ascii表第一位都是0。
换言之,错误原因,你的string从第67个char就错了,ascii搜不到正确的字符,有些只能用奇怪的字符代替。所以最后printf打印错误。

具体怎么改正,你要改string的内容咯~

#8


引用 4 楼 hnuqinhuan 的回复:
实验室没有GCC不过在VC6.0下面前面的运行结果是对的
就是吧 *q = toascii(ascii);   换成 *q = ascii;     就行了啊


查了一下  toascii()函数   

toascii(将整型数转换成合法的ASCII 码字符)  
相关函数  isascii,toupper,tolower
 
表头文件  #include<ctype.h>
 
定义函数  int toascii(int c)
 
函数说明  toascii()会将参数c转换成7位的unsigned char值,第八位则会被清除,此字符即会被转成ASCII码字符。
 
返回值  将转换成功的ASCII码字符值返回。
 
范例  #include<stdlib.h>
main()
{
int a=217;
char b;
printf(“before toascii () : a value =%d(%c)\n”,a,a);
b=toascii(a);
printf(“after toascii() : a value =%d(%c)\n”,b,b);
}
 
执行  before toascii() : a value =217()
after toascii() : a value =89(Y)



意思不就是 217   1101 1001  转换为了
                  89      0101 0001
 把第八位去掉了变成了unsigned

而我获得的ascii值应该都是小于 128的,,,
用toascii怎么会不行呢

#9


toascii:
Pointer to a 256-byte array that contains the current keyboard state. Each element (byte) in the array contains the state of one key. If the high-order bit of a byte is set, the key is down (pressed). 
The low bit, if set, indicates that the key is toggled on. In this function, only the toggle bit of the caps lock key is relevant. The toggle state of the num lock and scroll lock keys is ignored. 

#10


引用 6 楼 a_sum_of_money 的回复:
按楼上的方法果然好用了~~~
toascii函数干了什么,,呵呵
看来还是没整明白这个函数哪
toascii是搜索ascii表来转换的。如果你不用这个,你还是按楼上说的方法直接改正吧。方便点。

#11


引用 7 楼 baby313 的回复:
C/C++ code
    char *dest = (char *)malloc(1000);
    char *result = dest;

    memset(dest, '\0', 1000);
    url_unencode(dest, source);
    
    while (*result != '\0'){
      putchar (*(result++)……



哥们 观察的真是仔细啊~~~

字符串中有如%E5 这样的字符,用toascii()转换后从1110 0101   变成了  0110 0101所以有错~~~

还让我纠结的是 source中的"1312783897324"这此字符和toascii没有关系 怎么也打印不出来 呢

#12


呵呵,理论上,能替换了倒也没错,关键是替换不了的,弄一下奇怪的字符串,就很麻烦了。
引用 11 楼 a_sum_of_money 的回复:
引用 7 楼 baby313 的回复:

C/C++ code
char *dest = (char *)malloc(1000);
char *result = dest;

memset(dest, '\0', 1000);
url_unencode(dest, source);

while (*result != '\0'){
putchar (*(result++)……

#13


你把%8D去掉试试
引用 11 楼 a_sum_of_money 的回复:
引用 7 楼 baby313 的回复:

C/C++ code
char *dest = (char *)malloc(1000);
char *result = dest;

memset(dest, '\0', 1000);
url_unencode(dest, source);

while (*result != '\0'){
putchar (*(result++)………

#14


引用 13 楼 shi3590 的回复:
你把%8D去掉试试
引用 11 楼 a_sum_of_money 的回复:
引用 7 楼 baby313 的回复:

C/C++ code
char *dest = (char *)malloc(1000);
char *result = dest;

memset(dest, '\0', 1000);
url_unencode(dest, source);

while ……


嗯这样能打出来了,,求解释

#15


顶起啊~~让高手们看到

#16


因为8D进行toascii()转换后是回车,相当于0D。
指针遇到回车重新指向回车后的地址,所以回车前的数据全部丢失。

#17


引用 16 楼 shi3590 的回复:
因为8D进行toascii()转换后是回车,相当于0D。
指针遇到回车重新指向回车后的地址,所以回车前的数据全部丢失。


指针指向回车的情况还真的没遇到过。。。我得好好思考下
多谢啦~