You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++操作SQLite3插入俄文数据为空的编码问题求助

解决SQLite3插入俄文姓名为空的编码问题

你遇到的俄文姓名插入为空的问题,核心是控制台输入缓冲区混乱+SQLite文本编码绑定的细节问题,以下是具体解决方案:

1. 修复控制台输入的缓冲区冲突

代码中混用wcin.getline()和cin >> age会导致输入缓冲区残留换行符,下一次getline会直接读取空字符串,最终插入的name就是空值。

解决方法:在cin >> age后添加缓冲区清理代码,记得包含<limits>头文件:

cin >> age;
// 清理输入缓冲区的换行符,避免影响下一次getline
cin.ignore(numeric_limits<streamsize>::max(), '\n');

2. 确保SQLite数据库以UTF-8编码打开

虽然SQLite默认用UTF-8,但显式指定编码可以避免旧数据库的编码兼容问题,将sqlite3_open替换为sqlite3_open_v2:

int open_db = sqlite3_open_v2("test.db", &db, 
    SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, 
    "UTF-8"); // 明确指定UTF-8编码

3. 改用UTF-8字符串绑定(更稳定的方案)

sqlite3_bind_text16依赖系统宽字符编码(Windows是UTF-16LE),换成UTF-8字符串绑定兼容性更好。可以将wstring转换为UTF-8编码的string,再用sqlite3_bind_text绑定:

首先添加转换逻辑:

// 把wstring转换为UTF-8 string
std::wstring_convert<std::codecvt_utf8<wchar_t>> utf8_converter;
std::string utf8_name = utf8_converter.to_bytes(name);

然后修改SetDB函数的绑定代码:

// 替换原有的sqlite3_bind_text16
sqlite3_bind_text(*stmt, 1, utf8_name.c_str(), -1, SQLITE_TRANSIENT);

注意:用SQLITE_TRANSIENT代替SQLITE_STATIC,因为转换后的UTF-8字符串是局部变量,需要SQLite自行复制数据。

修改后的完整代码

#include <iostream>
#include <sqlite3.h>
#include <string>
#include <locale>
#include <codecvt>
#include <Windows.h>
#include <limits> // 新增头文件,用于清理缓冲区

// 定义控制台颜色宏(原代码中缺失,补充)
#define RED "\033[31m"
#define GREEN "\033[32m"
#define RESET "\033[0m"

// 补充原代码中缺失的ERRORsql函数
void ERRORsql(int open_result, sqlite3* db) {
    if (open_result != SQLITE_OK) {
        std::cerr << RED << "Ошибка открытия базы данных: " << sqlite3_errmsg(db) << RESET << std::endl;
        sqlite3_close(db);
        exit(EXIT_FAILURE);
    }
}

using namespace std;

void CreateTable(int open, sqlite3* db, char* ERR)
{
    cout << "Создание таблицы: ";
    const char* SQLTable = "CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT NOT NULL, Age INTEGER);";
    open = sqlite3_exec(db, SQLTable, 0, 0, &ERR);
    if (open)
    {
        cerr << RED << "ПРОВАЛ" << ERR << endl << RESET;
        sqlite3_free(ERR);
    }
    else
        cout << GREEN << "УСПЕХ" << RESET << endl;
}

void SetDB(sqlite3* db, const wstring& name, int age, sqlite3_stmt** stmt)
{
    const char* insertSQL = "INSERT INTO users (Name, Age) VALUES (?, ?)";
    if (sqlite3_prepare_v2(db, insertSQL, -1, stmt, nullptr) == SQLITE_OK)
    {
        // 将wstring转换为UTF-8编码的string
        wstring_convert<codecvt_utf8<wchar_t>> utf8_converter;
        string utf8_name = utf8_converter.to_bytes(name);
        
        // 使用UTF-8字符串绑定
        sqlite3_bind_text(*stmt, 1, utf8_name.c_str(), -1, SQLITE_TRANSIENT);
        sqlite3_bind_int(*stmt, 2, age);
        
        if (sqlite3_step(*stmt) != SQLITE_DONE)
            cerr << "Вставка данных: " << RED << "ПРОВАЛ" << endl << sqlite3_errmsg(db) << RESET;
        else
            cout << "Вставка данных: " << GREEN << "УСПЕХ" << endl << RESET;
    }
    else
    {
        cerr << "Подготовка запроса: " << RED << "ПРОВАЛ" << RESET << endl;
    }
    sqlite3_finalize(*stmt);
}

int main()
{
    SetConsoleCP(CP_UTF8);
    SetConsoleOutputCP(CP_UTF8);
    setlocale(LC_ALL, "ru_RU.UTF-8"); // 明确指定UTF-8区域设置
    
    wstring name;
    int age;
    sqlite3_stmt* stmt = nullptr;
    sqlite3* db;
    char* ErrorMsg = 0;
    
    // 显式指定UTF-8编码打开数据库
    int open_db = sqlite3_open_v2("test.db", &db, 
        SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, 
        "UTF-8");
    ERRORsql(open_db, db);
    
    CreateTable(open_db, db, ErrorMsg);
    
    cout << "Начните ввод для информации в бд" << endl <<
        "Для завершения работы пропишите //exit" << endl;
    
    while (true)
    {
        cout << "Имя: " << endl << "> ";
        getline(wcin, name);
        
        if (name == L"//exit")
            break;
            
        cout << "Возраст (по желанию или же -)" << endl << "> ";
        cin >> age;
        // 清理输入缓冲区的换行符
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
        
        SetDB(db, name, age, &stmt);
    }
    
    cout << "До скорых встреч" << endl;
    sqlite3_close(db);
    
    return 0;
}

关键修改说明

  • 修复了wcin和cin混用导致的输入缓冲区问题,确保能正确读取俄文姓名。
  • 显式指定SQLite数据库使用UTF-8编码,避免编码不匹配。
  • 将宽字符wstring转换为UTF-8字符串后绑定,解决sqlite3_bind_text16的兼容性问题。
  • 补充了原代码中缺失的颜色宏和ERRORsql函数,确保代码可直接编译运行。

内容的提问来源于stack exchange,提问作者Григорий Жидков

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 14:19:51