我正在try 将一个字符串插入到我的MariaDB数据库中,该字符串包含一个大于128的Unicode字符,即177,±.

wchar_t wcs = L"INSERT INTO text(drawing, eID, txt) VALUES(9,14063,'\261\065\061\067\071')";

使用wctombs:

int ret;
ret = wctombs(querybuffer, wcs, 60);

ret是-1,这显然意味着有一个宽字符与有效的多字节字符不对应.

我已经按照John Bollinger的建议修改了我的代码(非常感谢):

while(txt[i])
{
  c=cleaveMControl(txt,&i,j);
  if(c){
    if(c<128)
      query[j++]=c;
    else{
      query[j++]=92;
      query[j++]=92;
      sprintf(query+j,"u00%x",c);
      j=strlen(query);
    }
  }
}
query[j++]=39;
query[j++]=41;
query[j++]=59;
query[j]=0;
mysql_query(sqlconnect,query);

这会产生以下结果:

MariaDB [D8]> select * from text where eID=14063;
+---------+-------+------------+
| drawing | eID   | txt        |
+----------+-------+------------+
|       9 | 14063 | \u00b15179 |
+---------+-------+------------+

我预计会看到‘±5179’.

推荐答案

如何确保在C程序中将包含uft8字符的字符串正确写入MySQL?

首先,这是错误的:

wchar_t wcs=L"INSERT INTO text(drawing, eID, txt) VALUES(9,14063,'\261\065\061\067\071')"

您的编译器应该警告您在没有强制转换的情况下将指针赋给整数(以及更窄的整数).它也应该在这里抱怨:

ret=wctombs(querybuffer,wcs,60);

...关于转换另一个方向.如果你没有收到这样的警告,那么要么调高你的编译器的警告级别,要么找一个更好的编译器.

这个wcs的定义更有可能行得通:

const wchar_t *wcs = L"INSERT INTO text(drawing, eID, txt) VALUES(9,14063,'\261\065\061\067\071')";

重要的是,您需要将wcs声明为指针,而不是单个wchar_t.添加const提供了一些保护,防止意外try 修改内容,而您不能这样做.


但如果你能假设至少C11,那么

  • 您可以通过使用UTF-8字符串文字来可移植地定义通过UTF-8在内存中编码的字符串.

  • 在任何字符串文字中,您都可以使用"通用字符名称"通过字符的Unicode代码点值来引用字符.

把这些放在一起,在C11或更高版本中,你只需说:

const char *s = u8"INSERT INTO text(drawing, eID, txt) VALUES(9,14063,'\u00b1" u8"5171')";

以获得您想要的UTF-8编码字节,而不考虑任何源和执行字符集.

顺便说一句,没有必要像我那样将它分成两个字面,但这样做有助于澄清通用字符名称\u00b1不会继续进入字符串的后续数字.(注:也有8位通用字符名称,但它们以\U开头,而不是\u).


如果您不能假设至少为C11,那么您最好跳过宽字符串文字,而不是直接为您需要的单个字符插入UTF-8编码:

const char *s = "INSERT INTO text(drawing, eID, txt) VALUES(9,14063,'\302\261" "5171')";

这确实依赖于执行基本字符集的字符的ASCII(和UTF8)兼容编码,但这是一个相对安全的 Select ,而且比宽字符串变体工作所需的要求要弱.

C++相关问答推荐

segfault在C中使用getline()函数

使用GOTO从多个嵌套循环C继续

为什么C语言允许你使用var =(struct NAME){

如何使fputs功能提示错误输入并要求用户重新输入.程序停止而不是请求新的输入

如何在C客户端应用程序的ClientHello消息中添加自定义扩展?

C中的指针增量和减量(*--*++p)

使用scanf在C中读取和存储文件中的值

如果dim指定数组中的数据量,使用dim-1会不会潜在地导致丢失一个元素?

是什么让numpy.sum比优化的(自动矢量化的)C循环更快?

GCC创建应用于移动项的单独位掩码的目的是什么?

防止规范模式在C++中 echo 特殊字符

为什么我可以在GCC的标签后声明变量,但不能声明Clang?

强制转换变量以在 struct 中蚕食

CS50判断灯泡运动的问题,判断时多出一个灯泡,但不在终端上

Valgrind正在使用一个Fexecve电话报告不可能发生的事情

WSASocket在哪里定义?

令人困惑的返回和 scanf 问题相关

clion.我无法理解 Clion 中发生的 scanf 错误

如何使用 raylib 显示数组中的图像

inline 关键字导致 Clion 中的链接器错误