C言語においてsqliteを使用しています。
以下がソースになります。
・sample.c
// sample.c
// written by mnagaku @ 2006/04/27
// id, worker, change_line_count, commit_date
// の形式のデータをDBに取り込み、
// change_line_countの総計の多いworkerのtop10と
// commit数(データ数)の総計の多いworkerのtop10を調べます
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "sqlite3.h"
#include <time.h>
#define MAX_STR 256
#define MAX_COLUMN 5
// SQL文
#define CREATE_TABLE "CREATE TABLE IF NOT EXISTS bookdata (id INTEGER PRIMARY KEY,
bookmei TEXT NOT NULL, category TEXT NOT NULL, nesesary TEXT NOT NULL,
commit_date TEXT NOT NULL)"
#define INSERT_TABLE "INSERT OR IGNORE INTO bookdata (id, bookmei, category,
nesesary,commit_date) values (%s, '%s', '%s', '%s', '%s')"
#define SELECT_TABLE "SELECT id, bookmei, category,
nesesary,commit_date from bookdata"
/* ログディレクトリ(通常) */
#define LOG_FILE "LOG/log.txt"
// DBの検索結果を大域変数で保持
typedef struct {
char values[MAX_COLUMN][MAX_STR];
} RAW;
RAW *sqlResult;
int rawSize, columnSize;
FILE log_file; / 通常ログ */
void LOG_PRINT(char log_txt[256], char log_data[256]); /* 通常ログ出力関数 */
void LOG_PRINT(char log_txt[256], char log_data[256])
{
time_t timer; struct tm *date; char str[256]; timer = time(NULL); /* 時間取得 */ date = localtime(&timer); strftime(str, sizeof(str), "[%Y/%x %H:%M:%S] ", date); if ((log_file = fopen(LOG_FILE, "a")) == NULL) { exit(EXIT_FAILURE); /* エラーの場合は通常、異常終了する */ } /* 文字列結合 */ strcat(str,log_txt); strcat(str,log_data); fputs(str, log_file); fclose(log_file); return;
}
// 検索結果を1行取得する度に呼ばれるコールバック関数
static int callback(void *option, int columnCount, char **columnValues,
char **columnNames) {
int columnCounter;
if(sqlResult == NULL) { sqlResult = (RAW *)malloc(MAX_COLUMN * MAX_STR * 2); columnSize = columnCount; } else if((sqlResult = (RAW *)realloc(sqlResult, MAX_COLUMN * MAX_STR * (rawSize + 2))) == NULL) return -1; for(columnCounter = 0; columnCounter < MAX_COLUMN && columnCounter < columnCount; columnCounter++) { if(rawSize == 1) strncpy(sqlResult[0].values[columnCounter], columnNames[columnCounter], MAX_STR); strncpy(sqlResult[rawSize + 1].values[columnCounter], columnValues[columnCounter], MAX_STR); } rawSize++; return 0;
}
// SQLの実行
void sqlExec(sqlite3 *db, const char *sql, sqlite3_callback cb) {
char *pStr;
free(sqlResult); sqlResult = NULL; rawSize = 0; if(sqlite3_exec(db, sql, cb, NULL, &pStr) != SQLITE_OK) { fprintf(stderr, "Error %s %d: %s\n%s\n", __FILE__, __LINE__, pStr, sql); sqlite3_close(db); exit(0); }
}
// メイン
void main() {
char str[MAX_STR], data[5][20], *pStr;
int lineCount, dataCount;
FILE *fp;
sqlite3 *db;
// メモリ上にDBを構築
if(sqlite3_open("shoseki.db", &db)) {
fprintf(stderr, "Error %s %d: Can't open database %s\n",
FILE, LINE, sqlite3_errmsg(db));
sqlite3_close(db);
return;
}
// テーブル作成
sqlExec(db, CREATE_TABLE, NULL);
// データファイル読込み
if((fp = fopen("sample.csv", "rt")) == NULL) {
fprintf(stderr, "Error %s %d: Can't open datafile.\n",
FILE, LINE);
sqlite3_close(db);
return;
}
memset(str, '\0', sizeof(str));
fgets(str, MAX_STR, fp); //ヘッダーの読み飛ばし
for(lineCount = 0; fgets(str, MAX_STR, fp) != NULL; lineCount++) { for(pStr = strtok(str, ","), dataCount = 0; dataCount < 4 && strlen(pStr) > 0 && pStr[0] != '\n'; pStr = strtok(NULL, ","), dataCount++) strncpy(data[dataCount], pStr, 20); if(dataCount < 4) { printf("Warnning %s %d: Find illegal data at %d\n", __FILE__, __LINE__, lineCount); break; }
// 読み込んだデータをDBに投入
sprintf(str, INSERT_TABLE, data[0], data[1], data[2], data[3],data[4]);
sqlExec(db, str, NULL);
memset(str, '\0', sizeof(str));
}
fclose(fp);
// DBの検索
sqlExec(db, SELECT_TABLE, callback);
for(int i=0;i<4;i++){
for(int j=0;j<5;j++){
printf("%s\n",sqlResult[i].values[j]);
}
}
sqlite3_close(db);
}
以下がMakefileです。
・Makefile
CC=gcc
CFLAGS=-std=gnu18 -Wall -Wextra -g
all: sample
sample: sample.o
$(CC) $(CFLAGS) -L/usr//local/Cellar/sqlite/3.39.0/lib/ -I/usr//local/Cellar/sqlite/3.39.0/include/ sample.o -lsqlite3 -o sample
sample.o: sample.c
$(CC) $(CFLAGS) -c sample.c
clean:
rm -f *.o sample
コードが増えそうなので、cファイルをもう一つ増やそうと
思います。Makefileにcファイルを増やして、ソースを
結合して、コンパイルしたいです。Makefileの書き方を
お聞きしてもよろしいですか。
0 コメント