Не могу вставить в базу данных используя sqlite3_bind_text - PullRequest
1 голос
/ 18 марта 2019

Здравствуйте, у меня проблема с этой функцией recup().Цель recup() - вставить все слова, найденные в строке chaine, слово за словом, в базу данных.Слова приходят из цепочки, которая задается пользователем с помощью fgets.Проблема, с которой я сталкиваюсь, состоит в том, что она вставляет только слова, длина которых равна первому слову chaine.Например, если я напишу «Я хочу кота», будут вставлены только «я» и «а».

int recup(char *chaine){

    char tab[30] ={0};
    char delim[] = " ";
    char *ptr = strtok(chaine,delim);

    int rc =0;
    char *sql ="INSERT INTO newTable SELECT * FROM dbTable where lemme =?";

    sqlite3_stmt *stmt = 0;

    rc = sqlite3_prepare_v2(db,sql,-1,&stmt,0); 

    do {
        // Expected word is printed here
        printf("%s\n",ptr);
        strcpy(tab,ptr);

        // For some reason, only words that match the length
        // of the first word are being inserted
        rc = sqlite3_bind_text(stmt,1,tab,-1,SQLITE_STATIC);  
        rc = sqlite3_step(stmt);
        ptr = strtok(NULL,delim);
    } while(ptr != NULL);
    rc = sqlite3_finalize(stmt); 
    return 0;
}


#include <ansi_c.h>
#include <sqlite3.h>
#include "fdata.h"
sqlite3 *db;   

int main(int argc, char* argv[]) { 
      int rc = 0;
      char chaine[100] = {0};
      rc = sqlite3_open("lexique.db",&db);
      check(rc);
      createNewT();
      question(&chaine);
      recup(&chaine);
      sqlite3_close(db); 
      return 0;
}

Ответы [ 3 ]

1 голос
/ 18 марта 2019

Функция strtok () изменяет строку, переданную в нее.Итак, необходимо создать копию входной строки.См. Отличный ответ @David Cullen, который создает mcve.

См. Комментарии в исправленном коде, объясняющие, что происходит.

#include <stdio.h>
#include <string.h>

int recup(char *chaine){


  char tab[30] ={0};
  char delim[] = " ";
  ///// strtok will modify its inut string argument, so create a copy of the input
  strcpy(tab, chaine);
  // ptr will contain the current last token that was parsed
  char *ptr = strtok(tab,delim); // pass the copy to strtok, ptr points to first word

  int rc =0;
  char *sql ="INSERT INTO newTable SELECT * FROM dbTable where lemme =?";

  sqlite3_stmt *stmt = 0;

  rc = sqlite3_prepare_v2(db,sql,-1,&stmt,0);


  while (ptr) {
    printf("%s\n",ptr);  // print the word that was just tokenized

    rc = sqlite3_bind_text(stmt,1,ptr,-1,SQLITE_STATIC);
    rc = sqlite3_step(stmt);
    ptr = strtok(NULL,delim);
  }
  rc = sqlite3_finalize(stmt);
  return 0;
}
1 голос
/ 18 марта 2019

API C SQLite не очень терпим и требует строгой семантики.Здесь ваша проблема заключается в том, что вы пытаетесь повторно использовать оператор SQL в цикле (что правильно), не сбрасывая его (что неправильно).Текущий поток:

sqlite3_open
sqlite3_prepare_v2
sqlite3_bind
sqlite3_step
sqlite3_bind => ERROR SQLITE_MISUSE

В то время как документация для sqlite3_step гласит (выделите мое):

SQLITE_DONE означает, что оператор завершил выполнение успешно. sqlite3_step () не должен вызываться снова на этой виртуальной машине без предварительного вызова sqlite3_reset () для сброса виртуальной машины обратно в ее начальное состояние.

Я предполагаю, что следующее sqlite3_step вызывает сброс оператора, что позволяет обрабатывать 3-е слово, но вы теряете каждое второе слово.

Цикл должен быть:

do {
    printf("%s\n",ptr);
    strcpy(tab,ptr);


    rc = sqlite3_bind_text(stmt,1,tab,-1,SQLITE_STATIC);
    if (rc) {
        // process error
    }
    rc = sqlite3_step(stmt);
    if (rc != SQLITE_DONE) {
        // process error
    }
    sqlite3_reset(stmt);
    ptr = strtok(NULL,delim);
} while(ptr);
1 голос
/ 18 марта 2019

Это mcve , показывающий, как использовать strtok для токенизации строки примера:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
    char *test = "I want a cat";
    char chaime[strlen(test) + 1];
    char *delim = " ";
    char *ptr = NULL;

    strcpy(chaime, test);
    ptr = strtok(chaime, delim);
    while (ptr) {
        printf("%s\n", ptr);
        ptr = strtok(NULL, delim);
    }
    return 0;
}

выход

[user@machine]: ./program
I
want
a
cat

Примечание

Если вы можете дать нам что-то подобное, демонстрирующее вашу проблему, вам будет легче помочь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...