C 用户输入SQLite3

C++ user input to sqlite3

本文关键字:SQLite3 输入 用户      更新时间:2023-10-16

我有一个课程分配,要求我们编写一个C 程序,该程序跟踪支出,允许修改记录并返回有关单个费用的"满意"数字(即用户感觉如何良好关于花钱(。我们的讲师表示,他希望我们在此程序中使用SQLITE3。他为我们提供了一个示例程序,该程序在SQLite3中构建表,并为列输入预定值。该程序运行良好而没有问题。

我要做的是修改程序以接受用户输入并将其存储在SQLITE3数据库中。这是我迄今为止的代码:

int main()
{
    string salesDesc;
    int price;
    int satisf;
    sqlite3 *db;
    char *szErrMsg = 0;
    cout << "Description of Expense: ";
    cin >> saleDesc;
    cout << endl;
    cout << "Price: ";
    cin >> price;
    cout << endl;
    cout << "Your Satisfaction: ";
    cin >> satisf;
    cout << endl;
    // open database
    int rc = sqlite3_open("spending_track.sqlite", &db);
    if (rc)
    {
        cout << "Cannot open databasen";
    }
    else
    {
        cout << "Database opened successfullyn";
    }
    const char *pSQL[6];
    pSQL[0] = "CREATE TABLE IF NOT EXISTS expenses(id INTEGER PRIMARY KEY "
              "AUTOINCREMENT NOT NULL, logged TIMESTAMP DEFAULT "
              "CURRENT_TIMESTAMP NOT NULL, desc VARCHAR(40), price INT,"
              "satisfaction INT)";
    pSQL[1] = "INSERT INTO expenses('" + string(saleDesc) + "'," price "," satisf ")";
    pSQL[2] = "SELECT * FROM expenses";
    pSQL[3] = "SELECT sum(satisf) FROM expenses";
    // blablabla the rest of the program

当我尝试编译此问题时,我会收到以下错误:

错误:无法转换'std :: _ cxx11 :: basic_string'to'const char*' psql [1] ="插入费用('" string(saledesc( "'," price"," apply"(;

如果我将string(saleDesc)更改为saleDesc,我会遇到相同的错误。

如果将string saleDesc;更改为char* saleDesc;,我会收到以下错误:

错误:类型为" const char [23]''和'char*'to二进制'operator '的操作数无效 psql [1] ="插入费用('" string(saledesc( "'," price"," apply"(;

我不确定还有什么尝试使它起作用。我还听说,允许用户直接输入sqlite3表是个坏主意。做这件事的更"正确"的方法是什么?

,因为这只是一个课程分配,我怀疑您是否需要担心SQL注入攻击,因此我不会费心尝试消毒您的输入。

您的另一个问题是您正在混淆char* S和std::string s。SQLite API要求您将其传递char* S,以便可以从C代码中使用,但这并不意味着您需要使用它们。std::string是Char阵列的包装器,您可以使用c_str()方法获得。我认为您真的不需要将SQL语句放在阵列中。这样的事情怎么样:

std::string  addTable = "CREATE TABLE IF NOT EXISTS expenses(id INTEGER PRIMARY KEY "
                        "AUTOINCREMENT NOT NULL, logged TIMESTAMP DEFAULT "
                        "CURRENT_TIMESTAMP NOT NULL, desc VARCHAR(40), price INT,"
                        "satisfaction INT)";
std::string insertExpense = "INSERT INTO expenses('" + saleDesc + "'," + std::to_string(price) "," + std::to_string(satisf) + ")";
std::string selectAllExpenses = "SELECT * FROM expenses";

然后,当您要将其传递到SQLite API时,可以使用c_str()

sqlite3_exec(db, addTable.c_str(), ...

感谢大家的回答。昨天我和教授一起度过了大约一个半小时,这实际上使他陷入困境。我最终找到了一种用阵列进行这项工作的方法,但是我想强调,我想出的解决方案几乎对这项任务有好处。对于任何有类似问题阅读此书的人,此方法不仅凌乱,而且还允许避免使用SQL注入。

在这里的许多评论中提到的问题是,我试图将字符串插入一个char*数组中。我们想出的解决方法是将变量直接扩展到字符串变量的变量添加SQL命令,例如:

string insertExpense = "INSERT INTO expenses(desc, price, satisf) VALUES ('" + saleDesc + "', "
                        ""+ to_string(price) + ", " + to_string(satisf) + ")";

然后,我们将该变量变为C_str并将其分配给一个char*变量,例如:

const char *line1 = insertExpense.c_str();

然后,我们只是将此char*变量直接分配给数组中的正确位置,例如:

const char *pSQL[6];
pSQL[0] = "CREATE TABLE IF NOT EXISTS expenses(id INTEGER PRIMARY KEY "
          "AUTOINCREMENT NOT NULL, logged TIMESTAMP DEFAULT "
          "CURRENT_TIMESTAMP NOT NULL, desc VARCHAR(40), price REAL,"
          "satisf INT)";
pSQL[1] = line1;
pSQL[2] = "SELECT * FROM expenses";
pSQL[3] = "SELECT sum(satisf) FROM expenses";

此方法正确地制作了SQL表,并使用其各自变量中存储的正确语句填充它。我想再次强调,这种方法既非常混乱又危险,对于任何有类似问题的人来说,使用准备好的陈述可能是一个更好的主意,正如评论中的其他人已经提到的那样。谢谢大家!