私は今この問題を一日中苦労しています。同様の例を見ても私はあまりにも遠くになっていないので、助けてくれるといいですね!誰かがコンテキストを知りたいと思えば、私はオペレーティングシステムコンセプトのCH3の最後にあるプログラミング課題1に取り組んでいます。難しい文字のポインタ配列
問題は基本的に、コマンドプロンプトを作成して、ユーザーがコマンドを入力してforkして実行し、そのコマンドを履歴に保存できるようにすることです。ユーザーはコマンド 'history'を入力して、最新の10個のコマンドを表示することができます。本書では、現在のコマンドを引数のcharポインタの配列として格納するように指示しました。現在はexecvp(args[0], args)
を使用して現在のコマンドを実行します。私の教授はこれに他の要件を加えました。だから、このように個々の引数を個別にアクセスできるようにすることは、それらの部分にも役立ちます。
私は、charポインタの配列を使用して同様の方法でコマンドの履歴を保存することに決めました。たとえば、最初のコマンドがls -la
で、2番目のコマンドがcd..
の場合、history[0] = "ls -la"
とhistory[1] = "cd.."
となります。私は本当にこれを動作させるのに苦労しています、そして、私はどこかでポインタをねじっているとかなり確信していますが、私はそれを理解できません。
メインでは、arg_history[0]
を使用して最初のコマンド(ls -la
の場合はls
)に最初の単語を印刷できますが、実際にはすべてを印刷することはできません。しかし、私はそこにデータがあることを知っています。私はそれを(add_history
の機能を介して)追加して確認します。歴史を印刷するために作られたget_history
関数に渡すとさらに悪いことに、ぎこちない言葉が印刷されます。なぜこれをやっているのか理解する助けに感謝します!今のところ私はそれが機能間のポインタを間違って渡すことと関係があるが、私が見ていることに基づいて、私は問題を見つけることができません!
/**
* Simple shell interface program.
*
* Operating System Concepts - Ninth Edition
* Copyright John Wiley & Sons - 2013
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE 80 /* 80 chars per line, per command */
#define HIST_LENGTH 10
void get_input(char *args[], int *num_args, char *history[], int *hist_index);
void get_history(char *history[], int hist_index);
void add_history(char *history[], char *added_command, int *hist_index);
int main(void)
{
char *args[MAX_LINE/2 + 1]; /* command line (of 80) has max of 40 arguments */
char *arg_history[HIST_LENGTH];
int num_args;
int hist_index;
int should_run = 1;
int i;
while (should_run){
printf("osh>");
fflush(stdout);
get_input(args, &num_args, arg_history, &hist_index);
//printf("%s\n", arg_history[0]); //incorrectly prints up to the first space
//printf("%s\n", args[0]) //prints the correct arg from the last command (eg. for 'ls -la' it prints ls for args[0] and -la for args[1])
if (strcmp(args[0], "history") == 0) {
get_history(arg_history, hist_index);
}
}
return 0;
}
void get_input(char *args[], int *num_args, char *history[], int *hist_index) {
char input[MAX_LINE];
char *arg;
fgets(input, MAX_LINE, stdin);
input[strlen(input) - 1] = NULL; // To remove new line character - the compiler doesn't like how I'm doing this
add_history(history, input, hist_index);
arg = strtok(input, " ");
*num_args = 0;
while(arg != NULL) {
args[*num_args] = arg;
*num_args = *num_args + 1;
arg = strtok(NULL, " ");
}
}
void get_history(char *history[], int hist_index) {
int i;
for (i = 0; i < HIST_LENGTH; i++) {
printf("%d %s\n", hist_index, *history);
// prints gibberish
hist_index = hist_index - 1;
if (hist_index < 1) {
break;
}
}
}
void add_history(char *history[], char *added_command, int *hist_index) {
int i;
for (i = HIST_LENGTH-1; i > 0; i--) {
history[i] = history[i-1];
}
history[0] = added_command;
*hist_index = *hist_index + 1;
//printf("%s\n", history[0]); prints correctly
}
アップデート: 私は、関数の外にinput
にポインタを移動する(私がメインでそれを置く)とadd_history
機能のためstrcpy
の使用を含むソリューションの一部によって提案された変更を行いました。私がこの問題を最初に使っていたのは、配列を使って項目を '上に'回転させていたからです。しかし、履歴がすべての要素でいっぱいになる前に、初期化されていない場所にアクセスしていました。私は今、メインからarg_history[0]
を印刷することができましたが、私はまだ何か他のものを印刷することに問題がありました(例えばarg_history [1])。しかしもっと重要なのは、私が実際に解決する必要があった機能であるget_history
から印刷することができなかったことです。より詳細な検査の後、hist_index
は配列にアクセスする前に値が与えられていないことを認識しました。みんな助けてくれてありがとう。もちろん
私はstrtok(input、 "")があなたの入力行を壊したと思います。あなたはstrtok()の前とstrtok()の後にあなたが得たものを見るために入力をプリントアウトしようとするかもしれません。 – Shiping
mainでargs []を出力した場合に 'get_input'を呼び出した後、正しく機能します。問題はarg_historyのデータにアクセスしています –