C ++用户输入到sqlite3

时间:2018-04-04 22:28:43

标签: c++ sql sqlite

我有一个课程作业,要求我们编写一个跟踪开支的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 database\n";
    }
    else
    {
        cout << "Database opened successfully\n";
    }

    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'转换为'const char *'   pSQL [1] =“INSERT INTO expenses('”+ string(saleDesc)+“',”price“,”satisf“)”;

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

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

  

错误:类型'const char [23]'和'char *'到二进制'operator +'的操作数无效   pSQL [1] =“INSERT INTO expenses('”+ string(saleDesc)+“',”price“,”satisf“)”;

我不确定还有什么方法可以让它发挥作用。我也听说允许用户直接输入sqlite3表是个坏主意。什么是更“适当”的方式来做到这一点?

2 个答案:

答案 0 :(得分:1)

由于这只是一个类赋值,我怀疑你将不得不担心SQL注入攻击,所以我不打算尝试清理你的输入。

您的另一个问题是,您感到困惑char*std::string。 sqlite API要求您传递它char*,以便可以从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(), ...

答案 1 :(得分:0)

感谢大家的回复。昨天我和我的教授花了大约一个半小时的时间来讨论这件事,这实际上让他很难过。我最终找到了一种方法来使这个工作与数组,但我想强调,我想出的解决方案几乎只对这个任务有好处。对于任何阅读此类问题的人来说,这个方法不仅麻烦,而且还允许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表,并使用存储在各自变量中的正确语句填充它。我想再次强调这种方法非常混乱和危险,对于任何有类似问题的人来说,使用预准备语句可能是一个更好的主意,正如评论中的其他人已经提到的那样。谢谢大家!