Символ без знака * создает странные символы, из-за которых его всегда не удается сравнить

#c #sqlite #unsigned

Вопрос:

У меня всегда есть эта проблема, unsigned char* особенно когда это тип, возвращаемый из какой-либо функции. Ибо моя проблема в том, что у меня есть база данных, и я хочу выбрать один из столбцов из таблицы. Затем получите значение с sqlite3_column_text() помощью .

Это и есть код:

 void check_username(std::string username)
{
    sqlite3_stmt* stmt;
    std::string query = "SELECT username FROM bank_account WHERE username = '"  username  "';";
   
    int rc = sqlite3_prepare_v2(DB, query.c_str(), -1, amp;stmt, NULL);
    if (rc != SQLITE_OK) 
    {
        std::cerr << "Error: " << sqlite3_errmsg(DB) << std::endl;
        return -1;
    }
    
    // Move to result of query's row
    rc = sqlite3_step(stmt);

    // Get the column value
    const unsigned char* result = sqlite3_column_text(stmt, 0);
    // Convert std::string username to unsigned char* for comparison with text in result
    const unsigned char* new_username = reinterpret_cast<const unsigned char*>(username.c_str());


    sqlite3_finalize(stmt);
    
    
    // THIS WILL FAILED TO COMPARE //
    if (new_username == result)
        std::cout << "It's match! << std::endl;
    else
        std::cout << "It's not match! << std::endl;
}
 

В нем говорится, что sqlite3_column_text() возвращается unsigned char* , поэтому я храню его в переменной того же типа:

const unsigned char* result = sqlite3_column_text(stmt, 0);

А затем, как вы можете видеть, моя функция принимает std::string в качестве параметров. Поэтому, чтобы сравнить его с результатом из базы данных, я преобразую его в символ без знака:

const unsigned char* new_username = reinterpret_cast<const unsigned char*>(username.c_str());

Вот в чем проблема: в конце кода ему всегда не удавалось сравнить, он всегда получал значение false, даже если имя совпадает. Затем я попытался выполнить отладку с std::cout << result << std::endl;
std::cout << new_username << std::endl; помощью , вот результат:

 �S�U
Harrypotter
 

Так что тот, который получается из sqlite3_column_text() -за этих странных персонажей. Итак, я думаю, что именно поэтому они всегда не совпадают, когда я пытаюсь сравнить.

Поэтому мой вопрос в том, как это происходит? и каково решение, чтобы я мог его сравнить?

Комментарии:

1. Вы сравниваете указатели. Попробуйте сделать это наоборот, создайте строку std::из результата, а затем сравните переменные std::string.

2. @PepijnKramer Я не думаю, что в этом нет никакой проблемы. До тех пор, пока они оба содержат строки. Я уже пробовал это.

Ответ №1:

Подобный этому:

 void check_username(const std::stringamp; username) // added constamp;
{
....
    // Get the column value, create string from char*
    std::string new_username{ static_cast<const char*>(sqlite3_column_text(stmt, 0)) }; // <========

    sqlite3_finalize(stmt);
    
    // now compare the std::string variables instead of pointers
    if (new_username == username)
        std::cout << "It's match! << std::endl;
    else
        std::cout << "It's not match! << std::endl;
}
 

Комментарии:

1. Это не удалось. Это sqlite3_column_text() не может так храниться std::string .

2. Ошибка гласит: no instance of constructor "std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string [with _CharT=char, _Traits=std::char_traits<char>, _Alloc=std::allocator<char>]" matches the argument list -- argument types are: (const unsigned char *)

3. И я не мог скомпилировать все данные sql.. о, метод sql возвращает постоянный символ без знака* Я этого не заметил, для std::string требуется символ со знаком*. Ehm попробуйте std::string new_username{ static_cast<const char*>(sqlite3_column_text(stmt, 0)) }; (Обычно мы просим пример компилируемого кода, но я вижу, что это сложно с sql lite в цикле)

Ответ №2:

В этой строке:

if (new_username == result)

Вы не можете сравнивать два отдельных указателя подобным образом. Указатели, по сути, являются просто адресами памяти, и, учитывая это result , и new_username ссылаются на разные места в памяти, вышеуказанное условие никогда не будет выполнено.

Если вы хотите сравнить содержимое, у вас есть три варианта:

  1. Воспользуйся std::equal() :
     #include <cstring>
    #include <algorithm>
    
    // Do prefer using `const std::stringamp;` over just `std::string` in the parameter to avoid temporary copies
    void check_username(std::string constamp; username) {
        // ...
    
        const unsigned char* result = sqlite3_column_text(stmt, 0);
    
        // ...
    
        if (std::equal(username.begin(), username.end(),
                       result, result   std::strlen(reinterpret_cast<const char*>(result))))
            std::cout << "It's match!" << std::endl;
        else
            std::cout << "It's not match!" << std::endl;
    }
     
  2. Используйте оператор operator==() сравнения для строк:
     #include <cstring>
    
    // ...
    
    void check_username(std::string constamp; username) {
        // ...
    
        const unsigned char* result = sqlite3_column_text(stmt, 0);
    
        // ...
    
        if (username == std::string(result, result   std::strlen(reinterpret_cast<const char*>(result))))
            std::cout << "It's match!" << std::endl;
        else
            std::cout << "It's not match!" << std::endl;
    }
     
  3. Воспользуйся std::strcmp() :
     #include <cstring>
    
    // ...
    
    void check_username(std::string constamp; username) {
        // ...
    
        const unsigned char* result = sqlite3_column_text(stmt, 0);
    
        // ...
    
        if (std::strcmp(amp;username[0], reinterpret_cast<const char*>(result)) == 0)
            std::cout << "It's match!" << std::endl;
        else
            std::cout << "It's not match!" << std::endl;
    }
     

Комментарии:

1. Это не удалось. Все это. Как я уже сказал, на нем всегда написано «Это не совпадение!». Хотя я знаю, что это одно и то же имя.

2. @Kevinkun Вы пытались проверить значения username и result использовать отладчик или std::cout и посмотреть, совпадают ли они?

3. Да, это совпадение.

4. Я только что нашел проблему! Он включен sqlite3_finalize(stmt) . Он изменяет значение result , когда он выполняется, прежде чем я сделаю сравнение. Так вот почему это всегда не совпадало.

5. Спасибо вам за ваше решение. Я использую третий.