aimainaを追加

This commit is contained in:
Nebel 2012-08-28 23:07:07 +09:00
parent 8639e2d3f8
commit 019ba69202
14 changed files with 529 additions and 0 deletions

12
cpp/aimaina/Makefile Normal file
View file

@ -0,0 +1,12 @@
OBJS = aimaina.o book.o search.o util.o
aimaina:$(OBJS)
$(CC) -o $@ $^
.c.o:
$(CC) -c $<
aimaina.o: aimaina.c util.h book.h
book.o: book.c util.h search.h book.h
search.o: search.c search.h
util.o: util.c

14
cpp/aimaina/README.md Normal file
View file

@ -0,0 +1,14 @@
蔵書管理プログラム aimaina
=========================
できること
--------
- 書籍情報の追加/検索/削除
- 書籍情報を"booklist.csv"に記録
- プログラミングIIの単位を取る
ライセンス
--------
&copy;2012 [@kou029w](http://twitter.com/kou029w) - [MIT license][MIT]
[MIT]: http://kou029w.appspot.com/mit-license.txt

31
cpp/aimaina/aimaina.c Executable file
View file

@ -0,0 +1,31 @@
/*
aimaina.c
(C)2012 B11T3074C, B11T3011K - MIT License
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "util.h"
#include "book.h"
int main(){
char buff[1024];
openlist("booklist.csv");
for(;;){
printf("追加[a] 検索[s] 終了[q] ");
input_line(buff, 1024);
strtolower(buff);
if(strcmp(buff, "a") == 0){
regist_data();
}else if(strcmp(buff, "s") == 0){
search();
}else if(strcmp(buff, "q") == 0){
savelist("booklist.csv");
exit(0);
}
}
return 0;
}

BIN
cpp/aimaina/aimaina.o Normal file

Binary file not shown.

239
cpp/aimaina/book.c Normal file
View file

@ -0,0 +1,239 @@
/*
book.c
(C)2012 B11T3074C, B11T3011K - MIT License
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "util.h"
#include "search.h"
#include "book.h"
// リストの先頭アドレス
Bookdata *booklist_head = NULL;
// キーボードから本のデータを入力
void input_data(Bookdata *target){
target->title = input_string("タイトル>", target->title);
target->author = input_string("著者>", target->author);
target->publisher = input_string("出版元>", target->publisher);
target->year = input_string("発行年>", target->year);
target->pages = input_string("ページ数>", target->pages);
target->isbn = input_string("ISBN>", target->isbn);
target->note = input_string("備考>", target->note);
}
// 本のデータを表示
void show_data(Bookdata *target){
printf("タイトル:\t%s\n", target->title);
printf("著者:\t\t%s\n", target->author);
printf("出版元:\t\t%s\n", target->publisher);
printf("発行年:\t\t%s\n", target->year);
printf("ページ数:\t%s\n", target->pages);
printf("ISBN:\t\t%s\n", target->isbn);
printf("備考:\t\t%s\n", target->note);
}
// 本のリストからデータを削除
void delete_data(Bookdata *target){
if(target->prev == NULL && target->next == NULL){
// 最後の1冊の場合
booklist_head = NULL;
}else if(target->prev == NULL){
// 先頭の場合
booklist_head = target->next;
(target->next)->prev = NULL;
}else if(target->next == NULL){
// 末尾の場合
(target->prev)->next = NULL;
}else{
(target->next)->prev = target->prev;
(target->prev)->next = target->next;
}
free(target->title); // タイトル
free(target->author); // 著者
free(target->publisher); // 出版元
free(target->year); // 発行年
free(target->pages); // ページ数
free(target->isbn); // ISBN
free(target->note); // 備考
free(target);
}
// リストの末尾にnewdataを追加
void add_data(Bookdata *new_data){
Bookdata *tail;
new_data->next = NULL;
if(booklist_head == NULL) {
// 最初の1冊の場合
booklist_head = new_data;
new_data->prev = NULL;
return;
}
// 末尾を検索
for(tail = booklist_head; tail->next != NULL; tail = tail->next);
// 末尾の後ろにつなぐ
tail->next = new_data;
new_data->prev = tail;
}
// リストをすべて表示
void show_all(){
Bookdata *tail;
puts("---");
for(tail = booklist_head; tail != NULL; tail = tail->next){
show_data(tail);
puts("---");
}
}
// リストをCSVで保存
void savelist(char *filename){
FILE *fp;
Bookdata *tail;
// filenameが""ならば標準出力をオープンする
if(filename[0] == '\0'){
fp = stdout;
}else{
fp = fopen(filename, "w");
}
fputs("title, author, publisher, year, pages, isbn, note\n", fp);
for(tail = booklist_head; tail != NULL; tail = tail->next){
fputs(tail->title, fp); // タイトル
fputs(", ", fp);
fputs(tail->author, fp); // 著者
fputs(", ", fp);
fputs(tail->publisher, fp); // 出版元
fputs(", ", fp);
fputs(tail->year, fp); // 発行年
fputs(", ", fp);
fputs(tail->pages, fp); // ページ数
fputs(", ", fp);
fputs(tail->isbn, fp); // ISBN
fputs(", ", fp);
fputs(tail->note, fp); // 備考
fputs("\n", fp);
}
fclose(fp);
}
// リストCSVファイルを開く
int openlist(char *filename){
char buff[7][1024];
int i, j;
FILE *fp;
// filenameが空なら標準入力をオープンする
if(filename[0] == '\0'){
fp = stdin;
}else{
fp = fopen(filename, "r");
}
if(fp == NULL){
fprintf(stderr, "\"%s\"が開けません\n", filename);
return -1;
}
// 1行目はスルー
fscanf(fp, "%[^\n]\n", buff[6]);
while(EOF != fscanf(fp, "%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^\n]\n",
buff[0], buff[1], buff[2], buff[3], buff[4], buff[5], buff[6])){
Bookdata book;
Bookdata *bp;
for(i=0; i<7; i++){
// ","の後のスペースを削除
if(buff[i][0] == ' ') strcpy(buff[i], &buff[i][1]);
}
book.title = strdup(buff[0]);
book.author = strdup(buff[1]);
book.publisher = strdup(buff[2]);
book.year = strdup(buff[3]);
book.pages = strdup(buff[4]);
book.isbn = strdup(buff[5]);
book.note = strdup(buff[6]);
bp = malloc(sizeof(Bookdata));
*bp = book;
add_data(bp);
}
fclose(fp);
return 0;
}
// bookを初期化
void init_data(Bookdata *book){
book->title = strdup("");
book->author = strdup("");
book->publisher = strdup("");
book->year = strdup("");
book->pages = strdup("");
book->isbn = strdup("");
book->note = strdup("");
}
// 追加する
void regist_data(){
Bookdata tmp;
Bookdata *tail;
init_data(&tmp);
input_data(&tmp);
tail = malloc(sizeof(Bookdata));
*tail = tmp;
add_data(tail);
}
// 検索する
void search(){
char buff[1024];
char pattern[1024];
Bookdata *tail;
Bookdata *matches[1024];
int count;
int i;
printf("/");
input_line(pattern, 1024);
count = 0;
for(tail = booklist_head; tail != NULL; tail = tail->next){
if(smatch(pattern, tail->title)
|smatch(pattern, tail->author)
|smatch(pattern, tail->publisher)
|smatch(pattern, tail->note)){
puts("---");
matches[count++] = tail;
show_data(tail);
}
}
if(count <= 0) return; // 見つからないので、戻る
puts("---");
printf("削除[d] 戻る[x] ");
input_line(buff, 1024);
strtolower(buff);
if(strcmp(buff, "d") == 0){
printf("削除します。よろしいですか? [y/N] ");
if(select_y('N')){
for(i=0; i<count; i++){
delete_data(matches[i]);
}
}
return;
}else if(strcmp(buff, "x") == 0){
return;
}
}

34
cpp/aimaina/book.h Normal file
View file

@ -0,0 +1,34 @@
/*
book.h
(C)2012 B11T3074C, B11T3011K - MIT License
*/
#ifndef BOOK_H
#define BOOK_H
// 1冊あたりの本のデータ
typedef struct Bookdata {
char *title; // タイトル
char *author; // 著者
char *publisher; // 出版元
char *year; // 発行年
char *pages; // ページ数
char *isbn; // ISBN
char *note; // 備考
struct Bookdata *next; // 次の要素
struct Bookdata *prev; // 前の要素
} Bookdata;
void input_data(Bookdata *target);
void show_data(Bookdata *target);
void delete_data(Bookdata *target);
void add_data(Bookdata *new_data);
void show_all(void);
void savelist(char *filename);
int openlist(char *filename);
void init_data(Bookdata *book);
void regist_data(void);
void search(void);
#endif

BIN
cpp/aimaina/book.o Normal file

Binary file not shown.

7
cpp/aimaina/booklist.csv Executable file
View file

@ -0,0 +1,7 @@
title, author, publisher, year, pages, isbn, note
脳と仮想, 茂木健一郎, 新潮社, 2007-2009, 264, ISBN9784101299525,
思考の整理学, 外山滋比古, 筑摩書房, 1986-2011, 223, ISBN4480020470,
恐山, 南直哉, 新潮社, 2012, 207, ISBN9784106104640,
電気回路, 小沢孝夫, 昭晃堂, 1996, 198, ISBN9784785611910,
電気電子工学概論, 酒井善雄, 丸善, 1995, 236, ISBN9784621040935,
アナログ電子回路, 藤井信生, 昭晃堂, 1984-2011, 255, ISBN4785611405,
1 title author publisher year pages isbn note
2 脳と仮想 茂木健一郎 新潮社 2007-2009 264 ISBN9784101299525
3 思考の整理学 外山滋比古 筑摩書房 1986-2011 223 ISBN4480020470
4 恐山 南直哉 新潮社 2012 207 ISBN9784106104640
5 電気回路 小沢孝夫 昭晃堂 1996 198 ISBN9784785611910
6 電気電子工学概論 酒井善雄 丸善 1995 236 ISBN9784621040935
7 アナログ電子回路 藤井信生 昭晃堂 1984-2011 255 ISBN4785611405

90
cpp/aimaina/search.c Normal file
View file

@ -0,0 +1,90 @@
/*
search.c
(C)2012 B11T3074C, B11T3011K - MIT License
*/
#include <stdlib.h>
#include <string.h>
#include "search.h"
// stringにpatternが含まれていれば1、それ以外で0を返す
int match(char *pattern, const char *string){
const char *p;
size_t pat_len = strlen(pattern);
for(p=string; *p; p++){
if(!strncmp(pattern, p, pat_len)){
return 1;
}
}
return 0;
}
// 破壊的AND-match : "pattern1 pattern2" => "pattern1" AND "pattern2"
int andmatch(char *pattern, const char *string){
char *p;
int match_flag = 1;
for(p = strtok(pattern, " "); p != NULL; p = strtok(NULL, " ")){
match_flag &= match(p, string);
}
return match_flag;
}
// 破壊的OR-match : "pattern1|pattern2" => "pattern1" OR "pattern2"
int ormatch(char *pattern, const char *string){
char *p;
int match_flag = 0;
for(p = strtok(pattern, "|"); p != NULL; p = strtok(NULL, "|")){
match_flag |= match(p, string);
}
return match_flag;
}
// 再帰可能なstrtok
char *strtok_r(char *str, const char *delim, char **saveptr){
size_t len;
char *head;
if(str == NULL){
head = *saveptr;
}else{
head = str;
}
len = strcspn(head, delim);
if(len == 0){
head += strspn(head, delim);
len = strcspn(head, delim);
}
if(*head == '\0'){
return NULL;
}
*saveptr = head + len + strspn(head + len, delim);
*(head + len) = '\0';
return head;
}
// Smart-match : 破壊的でない
// "pattern1 pattern2|pattern3" => "pattern1" AND ("pattern2" OR "pattern3")
int smatch(const char *pattern, const char *string){
char *p;
char *nextp;
int match_flag;
char *tmp;
tmp = strdup(pattern);
match_flag = 1;
for(p = strtok_r(tmp, " ", &nextp); p != NULL; p = strtok_r(NULL, " ", &nextp)){
match_flag &= ormatch(p, string);
if(match_flag == 0) break;
}
free(tmp);
return match_flag;
}

16
cpp/aimaina/search.h Normal file
View file

@ -0,0 +1,16 @@
/*
search.h
(C)2012 B11T3074C, B11T3011K - MIT License
*/
#ifndef SEARCH_H
#define SEARCH_H
int match(char *pattern, const char *string);
int andmatch(char *pattern, const char *string);
int ormatch(char *pattern, const char *string);
char *strtok_r(char *str, const char *delim, char **saveptr);
int smatch(const char *pattern, const char *string);
#endif

BIN
cpp/aimaina/search.o Normal file

Binary file not shown.

71
cpp/aimaina/util.c Normal file
View file

@ -0,0 +1,71 @@
/*
util.c
(C)2012 B11T3074C, B11T3011K - MIT License
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// 文字列版tolower()
char *strtolower(char *s){
char *p;
for(p=s; *p != EOF; p++){
*p = tolower(*p);
}
return s;
}
// 1行入力
void input_line(char *buff, size_t size){
char *p;
if(fgets(buff, size, stdin) == NULL){
exit(1);
}
// 改行コードを削除
for(p=buff; *p != '\n'; p++);
*p = '\0';
}
// "y", "n"で選択("n"ならば0を返す)
int select_y(char ch){
char buff[1024];
for (;;){
input_line(buff, 1024);
strtolower(buff);
if (strcmp(buff, "y") == 0){
return 1;
}else if (strcmp(buff, "n") == 0){
return 0;
}else{
switch(ch){
case 'y':
case 'Y':
return 1;
case 'n':
case 'N':
return 0;
}
fputs("yまたはnを入力してください\n", stderr);
}
}
}
// 文字列を入力(defstr:入力がないときデフォルトで返す文字列)
char *input_string(char *prompt, char *defstr){
char buff[1024];
printf("%s", prompt);
input_line(buff, 1024);
if(buff[0] != '\0'){
// 空でない場合
free(defstr);
return strdup(buff);
};
return defstr;
}

15
cpp/aimaina/util.h Normal file
View file

@ -0,0 +1,15 @@
/*
util.h
(C)2012 B11T3074C, B11T3011K - MIT License
*/
#ifndef UTIL_H
#define UTIL_H
char *strtolower(char *s);
void input_line(char *buff, size_t size);
int select_y(char ch);
char *input_string(char *prompt, char *defstr);
#endif

BIN
cpp/aimaina/util.o Normal file

Binary file not shown.