C语言中的unicode字符串比较
我正在学习UNIX系统编程。我正在为UNIX编写一个简单的shell应用程序(我在OS X Yosemite 10.10.5版上,使用Xcode)。我对C有一些经验,但不多 实用程序工作正常,可以打印unicode字符(虽然ls在Xcode控制台中打印“??”而不是它,但这似乎是调试器本身的问题) 我做了一些研究,发现C语言中的unicode字符串比较,c,unix,unicode,C,Unix,Unicode,我正在学习UNIX系统编程。我正在为UNIX编写一个简单的shell应用程序(我在OS X Yosemite 10.10.5版上,使用Xcode)。我对C有一些经验,但不多 实用程序工作正常,可以打印unicode字符(虽然ls在Xcode控制台中打印“??”而不是它,但这似乎是调试器本身的问题) 我做了一些研究,发现strcmp()也可以很好地使用它,因为它只是比较字节,最后寻找一个零字节。读取输入也应该可以,因为您只读取字节 我还读到unicode字符串不应该包含空字节。但是,在执行'str
strcmp()
也可以很好地使用它,因为它只是比较字节,最后寻找一个零字节。读取输入也应该可以,因为您只读取字节
我还读到unicode字符串不应该包含空字节。但是,在执行'strcmp()时,某些输入将导致执行错误访问
代码:
读取用户输入:
char* readCommand(void) {
int buffer_size = LINE_BUFFER_SIZE;
char *buffer = malloc(sizeof(char) * buffer_size);
int position = 0;
int character;
if(!buffer)
{
fprintf(stderr, "readCommand failed: memory allocation error");
exit(ALLOCATION_ERROR);
}
while (1) {
character = getchar();
if(character == EOF || character == '\n')
{
buffer[position] = '\0';
char* cmd = buffer;
free(buffer);
return cmd;
}
else {
buffer[position] = character;
}
if(++position >= sizeof(buffer))
{
buffer_size += LINE_BUFFER_SIZE;
buffer = realloc(buffer, sizeof(char) * buffer_size);
if(!buffer) {
fprintf(stderr, "readCommand failed: memory reallocation error");
free(buffer);
exit(ALLOCATION_ERROR);
}
}
}
return NULL;
}
拆分参数:
int split_string_quotes(char* source, char** argv, size_t arg_count)
{
enum split_states state = DULL;
char* p, *word_start = NULL;
int character;
int argc = 0;
for(p = source; argc < arg_count && *p != '\0'; p++)
{
character = (unsigned char) *p;
switch (state) {
case DULL:
if(isspace(character))
{
continue;
}
if(character == '"')
{
state = IN_STRING;
word_start = p+1;
continue;
}
state = IN_WORD;
word_start = p;
continue;
case IN_WORD:
if(isspace(character))
{
state = DULL;
*p = 0;
argv[argc++] = word_start;
}
continue;
case IN_STRING:
if(character == '"')
{
state = DULL;
*p = 0;
argv[argc++] = word_start;
}
continue;
}
}
if(state != DULL && argc < arg_count)
{
argv[argc++] = word_start;
}
argv[argc] = NULL;
return argc;
}
因此,问题在于,我键入的某些unicode字符串工作正常,不会导致EXC_BAD_访问
,但当我键入фыыПфщщП
时,它会中断。我认为问题在于访问args[0]
,但调试器的输出如下:
Printing description of args:
(char **) args = 0x00007fff5fbff900
*args char * 0x101800a00 0x0000000101800a00
Printing description of *(*(args)):
(char) **args = '\xd1'
所以它认为args[0]
是空的,但它是空的吗?还是被所有的零所迷惑
我真的很困惑,我花了很多时间研究,似乎被困在这里
我也尝试过使用wchar\u t
和wcscmp()
,但它对execvp()
不起作用,也不能解决问题
我还尝试了gcc-Wall-Wextra
,结果如下:
main.c:53:26: warning: comparison of integers of different signs: 'int' and
'size_t' (aka 'unsigned long') [-Wsign-compare]
for(p = source; argc < arg_count && *p != '\0'; p++)
~~~~ ^ ~~~~~~~~~
main.c:92:30: warning: comparison of integers of different signs: 'int' and
'size_t' (aka 'unsigned long') [-Wsign-compare]
if(state != DULL && argc < arg_count)
~~~~ ^ ~~~~~~~~~
main.c:124:23: warning: comparison of integers of different signs: 'int' and
'unsigned long' [-Wsign-compare]
if(++position >= sizeof(buffer))
~~~~~~~~~~ ^ ~~~~~~~~~~~~~~
main.c:180:18: warning: unused parameter 'args' [-Wunused-parameter]
int dHelp(char **args)
^
main.c:203:18: warning: unused parameter 'args' [-Wunused-parameter]
int dExit(char **args)
^
main.c:210:14: warning: unused parameter 'argc' [-Wunused-parameter]
int main(int argc, const char** argv)
^
main.c:210:33: warning: unused parameter 'argv' [-Wunused-parameter]
int main(int argc, const char** argv)
^
7 warnings generated.
main.c:53:26:警告:比较不同符号的整数:“int”和
'size_t'(也称为'unsigned long')[-Wsign compare]
对于(p=source;argc=sizeof(缓冲区))
~~~~~~~~~~ ^ ~~~~~~~~~~~~~~
main.c:180:18:警告:未使用的参数“args”[-Wunused参数]
int dHelp(字符**args)
^
main.c:203:18:警告:未使用的参数“args”[-Wunused参数]
int dExit(字符**args)
^
main.c:210:14:警告:未使用的参数“argc”[-Wunused参数]
int main(int argc,常量字符**argv)
^
main.c:210:33:警告:未使用的参数“argv”[-Wunused参数]
int main(int argc,常量字符**argv)
^
生成了7个警告。
但我认为情况并非如此(如果我错了,请纠正我)。代码中的一个巨大缺陷是读取输入的方式。看看这部分:
if(character == EOF || character == '\n')
{
buffer[position] = '\0';
char* cmd = buffer;
free(buffer);
return cmd;
}
这里您应该使用nil终止缓冲区
。然后指定cmd
指向与buffer
相同的内存,释放缓冲区并返回指向已释放内存的指针。如果在此之后,您使用返回的指针表示任何不允许的内容,并且任何事情都可能发生。内存可以在某个地方重复使用,您可能会遇到访问冲突,或者您附近的火山爆发
将指针赋给另一个变量并不会复制内存,它只会使它们指向同一个位置。在停止使用内容之前,无法释放内存。这很可能是导致您出现问题的原因。显示的代码中存在多个错误
char* cmd = buffer;
free(buffer);
return cmd;
这将返回指向已删除的char
缓冲区的指针。继续使用此指针会导致未定义的行为
if(++position >= sizeof(buffer))
缓冲区
是一个字符*
。这相当于:
if(++position >= sizeof(char *))
这将是4或8字节,取决于您的硬件平台。每次缓冲区增长超过4或8字节时,都会调整缓冲区的大小,这是不必要的
您似乎相信sizeof()
给出了malloc
-ed缓冲区的大小。事实并非如此
总之:这里的总体方法是编写一大堆代码,然后尝试看看它是否正确工作。这是错误的做法。您需要编写一个小函数。例如,将一行读入缓冲区。测试一下。验证它是否有效。既然你知道它是有效的,那就继续写下整个程序的下一个小部分。“我做了一些研究,发现strcmp()也可以用它来工作,只要它只是比较字节,最后寻找零字节。读取输入也应该可以,因为你只读取字节。”-仅当您使用基于
char
的字符串(例如Ansi或UTF-8)读取输入时,才会出现这种情况。它不适用于读取为UTF-16/32的Unicode字符串。您需要wchar\u t
来处理这些。此外,args[0]
的调试器输出不会显示任何空内容args[0]
(即*args
)是数组中的第一个char*
字符串指针,该指针在输出中不为空**args
(即args[0][0]
)是数组中第一个字符串中的第一个char
,并且也不为空。它是0xD1
,是UTF-8中Unicodeф
字符的第一个字节(第二个字节是0x84
)。中的所有字符在UTF-8中各使用2个字节(因此strlen(“фыыыыПфыщщщщщщщщщщщщщщщщщщщщщ109
在标准中定义为1。任何东西乘以1都没有效果。建议将该表达式从参数中删除到malloc()
Ooh我明白了。真的应该是这样,不知道我怎么会错过那一次。我稍后再查,但我肯定那是p
if(++position >= sizeof(buffer))
if(++position >= sizeof(char *))