質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

UNIX

UNIXとは、AT&Tのベル研究所で開発されたコンピューター用のマルチユーザー・マルチタスクのオペレーションシステム(OS)です。政府や教育機関や研究所で広範囲に採用されています。

Q&A

解決済

3回答

1176閲覧

C言語でUNIX系のhistoryを実現したい

SUNMOON_14

総合スコア20

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

UNIX

UNIXとは、AT&Tのベル研究所で開発されたコンピューター用のマルチユーザー・マルチタスクのオペレーションシステム(OS)です。政府や教育機関や研究所で広範囲に採用されています。

0グッド

0クリップ

投稿2021/07/14 15:07

編集2021/07/15 07:15

仕様

シェルを起動してから実行したコマンドをヒストリとして実行した順番とともに保存しておき、それを古いものから順に表示する。なお、ヒストリとして保存するコマンドの数は32個とし、コマンドとともに保持する順番はシェル起動時を基準とした順番とする。

質問

上記のような仕様を設定した場合に、2次元配列にコマンドを格納することを考えました。
しかし、コマンドが32個を超えた場合、新しいものを加えるために、最も古いものを削除して、全体を一つ前にずらさないといけないと思いますが、これはどのようにして実現できますか?

C

1char *history[32];

などと定義するとして、32個を溢れた場合の処理方法が検討つきません。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

1T2R3M4

2021/07/15 03:32

調べたこと、試したことを追記してください。
guest

回答3

0

ベストアンサー

あれ、前回回答したけど。

ヒストリー番号を32で割った余りを添え字にすればいいです。

#追記

が満たされるイメージがしにくいです。32個を溢れた場合、どのような動作になりますでしょうか?

添え字に書くときに、history[i]と書かずにhistory[i%32]と書くだけですが。

イメージしにくいというのがよく分からないです。
あるいは、「最後まで使ったら先頭に戻って再利用する」という発想が出来てない?
いままで日常生活でそういうことしたことないのでしょうか?

C

1// histN ・・・ 現在のヒストリー番号を保持しているint型変数とする 2 3// ヒストリー保存 4history[histN % 32] = 今の行の入っているバッファのアドレス; 5 6// 直近32個の表示(histNは次の番号になっているとする) 7int i; 8for(i=histN-32; i<histN; i++){ 9 printf("%d %s\n",i,history[i % 32]); 10}

投稿2021/07/14 15:10

編集2021/07/15 08:13
otn

総合スコア84423

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

SUNMOON_14

2021/07/15 05:51

ヒストリー番号を32で割った余りを添え字にした場合に、仕様: シェルを起動してから実行したコマンドをヒストリとして実行した順番とともに保存しておき、それを古いものから順に表示する。なお、ヒストリとして保存するコマンドの数は32個とし、コマンドとともに保持する順番はシェル起動時を基準とした順番とする。 が満たされるイメージがしにくいです。32個を溢れた場合、どのような動作になりますでしょうか?
guest

0

可能であれば、二次元配列、単方向リスト、ついでに双方向リストでも作ってみて、各々どういった利点・欠点があるのかを実感として比較することをお勧めします。
特別厳しい条件があるわけでも無いでしょうし、きちんと動かすことさえ出来ればどれでも構わないレベルだと思います。
むしろ、機能の追加によってもコード全体の見通しを良く(読み易く分かり易く)出来るかの方が難しいと思います。


episteme さんの回答のコードからファイル分割・単方向リストにしてみました。
commandline は簡単にする為固定サイズです。

c

1#include <stdio.h> 2#include "history.h" 3 4int main() { 5 HISTORY* hist = history_initialize(4); // 最新4つ分を保持する 6 7 const char* input[6] = { "alpha", "brabo", "charlie", "delta", "echo", "fox" }; 8 for (int i = 0; i < 6; ++i) { 9 history_push(hist, input[i]); 10 for (int h = history_size(hist); h > 0; --h) { 11 printf("[%s] ", history_at(hist, h-1)); 12 } 13 printf("\n"); 14 } 15 history_terminate(hist); 16 return 0; 17}

history.h

c

1#ifndef HISTORY_H_ 2#define HISTORY_H_ 3 4typedef struct link { 5 struct link *next; 6 char commandline[100]; 7} HIST_LINK; 8 9typedef struct history { 10 HIST_LINK *list; 11 int capacity; 12 int size; 13} HISTORY; 14 15HISTORY* history_initialize(int cap); 16void history_terminate(HISTORY* hist); 17 18int history_size(const HISTORY* hist); 19int history_capacity(const HISTORY* hist); 20const char* history_at(const HISTORY* hist, int n); 21void history_pop_back(HISTORY* hist); 22void history_push(HISTORY* hist, const char* str); 23 24#endif /* HISTORY_H_ */

history.c

c

1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4 5#include "history.h" 6 7/* history 実装 */ 8 9HISTORY* history_initialize(int cap) { 10 HISTORY* hist = (HISTORY*)malloc(sizeof(HISTORY)); 11 if(hist != NULL) { 12 hist->list = NULL; 13 hist->capacity = cap; 14 } 15 return hist; 16} 17 18int history_size(const HISTORY* hist) { 19 int size = 0; 20 for(HIST_LINK *link=hist->list; link!=NULL; link=link->next, size++); 21 return size; 22} 23 24int history_capacity(const HISTORY* hist) { 25 return hist->capacity; 26} 27 28const char* history_at(const HISTORY* hist, int n) { 29 if(n < 0) return NULL; 30 HIST_LINK *link = hist->list; 31 for(int i=0; i<n && link!=NULL; i++, link=link->next); 32 return link!=NULL ? link->commandline : NULL; 33} 34 35void history_pop_back(HISTORY* hist) { 36 if(hist->list == NULL) return; 37 HIST_LINK **p = &hist->list; 38 for(; (*p)->next!=NULL; p=&(*p)->next); 39 free(*p); 40 *p = NULL; 41} 42 43void history_push(HISTORY* hist, const char* str) { 44 HIST_LINK *newelement = (HIST_LINK *)malloc(sizeof(HIST_LINK)); 45 newelement->next = NULL; 46 strcpy(newelement->commandline, str); 47 48 while(history_size(hist) >= hist->capacity) history_pop_back(hist); 49 50 newelement->next = hist->list; 51 hist->list = newelement; 52} 53 54void history_terminate(HISTORY* hist) { 55 for(HIST_LINK *link=hist->list, *p; (p=link)!=NULL; ) { 56 link = link->next; 57 free(p); 58 } 59 free(hist); 60}

実行結果:

plain

1[alpha] 2[alpha] [brabo] 3[alpha] [brabo] [charlie] 4[alpha] [brabo] [charlie] [delta] 5[brabo] [charlie] [delta] [echo] 6[charlie] [delta] [echo] [fox]

投稿2021/07/14 20:03

編集2021/07/15 05:46
jimbe

総合スコア12545

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ざっくり書いてみた:

C

1#include <stdio.h> 2 3struct history; 4struct history* history_initialize(int cap); 5void history_terminate(struct history* hist); 6 7int history_size(const struct history* hist); 8int history_capacity(const struct history* hist); 9const char* history_at(const struct history* hist, int n); 10void history_pop_back(struct history* hist); 11void history_push(struct history* hist, const char* str); 12 13int main() { 14 struct history* hist = history_initialize(4); // 最新4つ分を保持する 15 16 const char* input[6] = { "alpha", "brabo", "charlie", "delta", "echo", "fox" }; 17 for (int i = 0; i < 6; ++i) { 18 history_push(hist, input[i]); 19 for (int h = history_size(hist); h > 0; --h) { 20 printf("[%s] ", history_at(hist, h-1)); 21 } 22 printf("\n"); 23 } 24 history_terminate(hist); 25 return 0; 26} 27 28/* history 実装 */ 29 30#include <stdlib.h> 31#include <string.h> 32 33struct history { 34 char** body; 35 int capacity; 36 int size; 37}; 38 39struct history* history_initialize(int cap) { 40 struct history* hist = (struct history*)malloc(sizeof(struct history)); 41 if ( hist != NULL ) { 42 hist->body = (char**)malloc(sizeof(char*)*cap); 43 if ( hist->body == NULL ) { 44 free(hist); 45 hist = NULL; 46 } else { 47 hist->capacity = cap; 48 hist->size = 0; 49 } 50 } 51 return hist; 52} 53 54int history_size(const struct history* hist) { 55 return hist->size; 56} 57 58int history_capacity(const struct history* hist) { 59 return hist->capacity; 60} 61 62const char* history_at(const struct history* hist, int n) { 63 return ( n < hist->size ) ? hist->body[hist->size - n -1] : NULL; 64} 65 66void history_pop_back(struct history* hist) { 67 if ( hist->size != 0 ) { 68 free(hist->body[0]); 69 for ( int i = 0; i < hist->size; ++i ) { 70 hist->body[i] = hist->body[i+1]; 71 } 72 --hist->size; 73 } 74} 75 76void history_push(struct history* hist, const char* str) { 77 char* copy = (char*)malloc(strlen(str) + 1); 78 if ( copy != NULL ) { 79 while ( hist->size >= hist->capacity ) { 80 history_pop_back(hist); 81 } 82 strcpy(copy, str); 83 hist->body[hist->size] = copy; 84 ++hist->size; 85 } 86} 87 88void history_terminate(struct history* hist) { 89 while ( hist->size != 0 ) { 90 history_pop_back(hist); 91 } 92}

投稿2021/07/14 21:40

episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問