#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
ссылаются на разные места в памяти, вышеуказанное условие никогда не будет выполнено.
Если вы хотите сравнить содержимое, у вас есть три варианта:
- Воспользуйся
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; }
- Используйте оператор
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; }
- Воспользуйся
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. Спасибо вам за ваше решение. Я использую третий.