首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C语言 >

C:字符串中包含“\0”怎么才能把它当作有效字符来处理

2012-08-08 
C:字符串中包含“\0”如何才能把它当作有效字符来处理?比如在文件路径中,包含“\0”的话,可以用“\\0”代替,但是

C:字符串中包含“\0”如何才能把它当作有效字符来处理?
比如在文件路径中,包含“\0”的话,可以用“\\0”代替,但是,如果文件路径为动态取得,该怎么办?比如:c:\test\000\abc。
如果说文件路径我们可以在写代码时进行限定不用,但要处理注册表我们就没办法了,我们不能要求所有人都不用“\0”吧!?
而目前我遇到的问题就是,API读注册表,发现有些项读不出来,打开注册表查看,才发现该键键值为注册表路径,其中就包含“\0”,格式如:SORTWARE\Main\000123\{0a4252a0-7e70-11d0-a5d6-28db04c10000},该如何处理?

[解决办法]
在前面再加一个'\'。
这个'\'是个转意字符
[解决办法]
不成问题吧,“\0”只是C语言字面的表示法,内存是0x00,C的字符串函数准确的说是“遇到0x00作为结束符,而不是遇到\0作为结束符”

字符串中的\0是“两个”实际存在的ascii字符“\”和“0”,和C的“\0”根本就是两码事,你肯定是其他地方有问题

一个简单的实验就是,你在一个文本文件中保存“C:\0\XXX”这个字串,再用文件IO读出来存进字符串,字符串里肯定是完整的,不存在所谓的截断问题
[解决办法]
你这与\0无关。
你操作SORTWARE\Main\000123\{0a4252a0-7e70-11d0-a5d6-28db04c10000}
时,把\替换为\\就好了。
SORTWARE\\Main\\000123\\{0a4252a0-7e70-11d0-a5d6-28db04c10000}
[解决办法]
VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)

提醒:
“学习用汇编语言写程序”

“VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)”
不是一回事!

不要迷信书、考题、老师、回帖;
要迷信CPU、编译器、调试器、运行结果。
并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。
任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实!

[解决办法]
不知道LZ有米有用过这个API:GetLogicalDriveStrings
它用于获取本地磁盘的盘符列表
返回的buffer格式为"C:\\\0D:\\\0E:\\\0F:\\\0G:\\\0"
若LZ想用printf或cout输出buffer,可能要让LZ失望了,因为只能输出"C:\\\0"
原因很简单,字符串是以'\0'结束的
所以若想将这个buffer拷贝到另一个内存段buffer2中
就不能把buffer当作字符串,只能做二进制流处理
用memcpy(buffer2, buffer, 20)
[解决办法]
告诉LZ一个简单的调试方法,就是将char array的内容一个一个的打出来(打ascii),或者下个断点,直接查看内存内容。

比如有个路径,它是C:\000\001,如果是直接用api得到的,char array的内容将是
67 58 92 48 48 48 92 48 48 49 0
还是刚才那个路径,如果要用字面量来表示的话,才是"C:\\000\\001"

望LZ先实践下,再来看是否真正理解了转义。

[解决办法]

探讨

呵呵,都成热贴了,还多是说我没有理解转义,我还能说什么。

说我不懂转义的,可以看看问题的核心:
我要从注册表中读取键值,而该键值实际上是注册表的路径,该路径可能是包含“\0”的字符串,格式有如"SORTWARE\Main\000123\{0a4252a0-7e70-11d0-a5d6-28db04c10000}",以下代码在读取键值的时候,没有正确返回键值,不同的计算机返回lResult……

[解决办法]
gcc测试的结果是,如果字符串里面有'\0',则 理解为结束符;

测试程序如下:

C/C++ code
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <unistd.h>int main(){    char *p = "SORTWARE\Main\000123\{0a4252a0-7e70-11d0-a5d6-28db04c10000";    printf("%s\n", p);}[root@bogon temp]# ./t1SORTWAREMain
[解决办法]
to 38楼:
char *p = "SORTWARE\Main\000123\{0a4252a0-7e70-11d0-a5d6-28db04c10000";
这里的应该为
char *p = "SORTWARE\\Main\\000123\\{0a4252a0-7e70-11d0-a5d6-28db04c10000";

Jacky说的"\0"用字符串表示应该是"\\0"。
[解决办法]
我想我可能猜到了

楼主读出的键值本身,应该是“SORTWARE\Main\000123\{0a4252a0-7e70-11d0-a5d6-28db04c10000}”这个正确无误的字符串
但楼主在处理这个字符串的时候,十有八九使用了“format”或者“printf”等具有转义功能的函数
这样,原本字符串中正确无误的“\0”两个字符就在这个函数中被转换成了'\0'一个字符


[解决办法]
定义的字符串应该是酱紫的

C/C++ code
char *p = "SORTWARE\\Main\\000123\\{0a4252a0-7e70-11d0-a5d6-28db04c10000";
[解决办法]
不是常量串的话,如果是从其它地方获取的,是不会存在出现\0的情况, 这个转义字符只适用于在程序代码中输入的串才会有.
[解决办法]
字符串转义只有在直接手写字符串,即char* p = "字符串\0",\0才会转义,
如果"字符串\0"是从已存在的内存取则不会转义,

如果按lz那样,每次内存复制字符串一次都要转义

LZ毕竟图样
[解决办法]
我在二次的时候是会自己补\,没什么好招。

你玩xml的时候,自己没转过吗?呵呵呵
[解决办法]
把\0换成\\0试试吧,我记得原来貌似有遇到过你这样的问题的
[解决办法]
这样的问题还需要想吗?
在写源代码的时候自然要写成'//',因为编译器会将转义字符转义。
但是从机器上读取的时候是这样读取的:'/','0' 转成ASCII码值并不是0
[解决办法]
探讨

引用:
注册表中的各项通常都是相互关联的,必须从某项中读取键值,根据键值才能找到目标键值,进行相关处理。而注册表中上下级关系都是用“\”表示,就好象文件路径一样,因为不能保证路径中没有“\0”字符,目前就卡在这了。


关键的问题是你这个\0到底是怎样获得的,如果是C语言代码中写明的用\\0就解决了,如果使用API从其他地方获取的那根本就不会有问题,因为\和0本来就都会……

[解决办法]
我好想跑题了 
你的问题应该是你不了解"\\"的作用
\\就是代表一个可打印的 "\"
所以 要用的时候用"\\"
代表 C:\dsa\dsa 中的\

要用转移的话 可以表示很多个字符 包括非打印的字符 比如 \n 
就不要用双\ 即"\\"


[解决办法]
探讨

RegQueryValueEx()都读不出包含“\0”的键值,怎么替换成“\\0”??!!

另外:针对下下回复,我在win7和xp环境下测试均得到不同的lResult,所以我也不知道具体是什么值。


[解决办法]
C/C++ code
 lstrcpy(destination, lpRegPath);    lstrcat(destination,start->vpID);    lstrcat(destination,endPath);    //MessageBox(hwnd,destination,"REG_BINARY",MB_OK);    //打开某键    lResult = RegOpenKeyEx(        HKEY_LOCAL_MACHINE,        destination,        0,        KEY_READ,        &hKey    ); 

热点排行