Я работаю над реализацией истории для оболочки. У меня есть структура, которая хранит команду, и массив этих структур хранит историю.
typedef struct command {
char **arg;
int num;
} cmd;
Код ниже корректно обновляет историю, распечатывая
Cmd # 1 : ls -l
Cmd # 1: pwd
Cmd # 2: ls -l
int main() {
char *arguments[3] = {"ls", "-l", NULL};
cmd *history = startHist();
history = updateHist(arguments, history);
printHistory(history);
char *arg2s[2] = {"pwd", NULL};
history = updateHist(arg2s, history);
printHistory(history);
free(history);
}
cmd* startHist() {
cmd *ret = malloc(20*sizeof(cmd));
for(int i=0;i<20;i++){
ret[i].arg = NULL;
ret[i].num = -1;
}
return ret;
}
cmd* updateHist(char **args, cmd *hist) {
for(int i = 19;i>0;i--) {
hist[i] = hist[i-1];
}
hist[0].arg = args;
if(hist[1].arg!=NULL) {
hist[0].num = hist[1].num+1;
} else {
hist[0].num = 1;
}
return hist;
}
void printHist(cmd *hist) {
int pos = 0;//index for iterating through commands
while(hist[pos].arg!=NULL) {
char* prstr = malloc(INIT_BUFFER*sizeof(char));//the string that will be printed
*prstr = '\0';
int index = 0;//index for iterating through arguments
printf("Cmd #%d: ", pos+1);
while(hist[pos].arg[index] != NULL) {
printf("%s ", hist[pos].arg[index]);
strcat(prstr, hist[pos].arg[index]);//concatenate the argument strings
index++;
}
printf("\n");
pos++;
free(prstr);
}
}
Однако следующий код не работает. Вместо этого строковое значение каждой записи cmd заменяется самой последней командой, хотя значение int работает правильно.
Редактировать: код был изменен по рекомендации. Теперь он должен запустить 3 цикла ввода. Пример вывода:
?: ls
Cmd # 1: ls
?: ls -a
Cmd # 1: ls -a
Cmd # 2: ls -a
?: выход
Cmd # 1: выход
Cmd # 2: выход
Cmd # 3: выход
Обратите внимание, что startHist (), printHist () и updateHist () такие же, как указано выше.
#include "stdio.h"//get from and print to console
#include "stdlib.h"//free and malloc
#include <string.h>//strtok
//Initial input buffer size. Will be expanded in getLine if needed.
const int INIT_BUFFER = 256;
typedef struct command {
char **arg;
int num;
} cmd;
//Function Declarations
char * getLine();//gets the input from the console and returns it
char ** splitLine(char *a);//splits the passed string into argument substrings
cmd* updateHist(char **args, cmd *hist);
void printHist(cmd *hist);
cmd* startHist();
void main() {
//declare primary variables
char *input;
char **args;
int retVal=3;
cmd *history = startHist();
do {//primary execution loop
printf("?: ");//prompt for input
input = getLine();
args = splitLine(input);
history = updateHist(args, history);
printHist(history);
retVal--;
free(input);
free(args);
} while(retVal);
free(history);
}
char ** splitLine(char *input) {
//variables for finding the number and length of the arguments
int numArgs=1;//the number of args in the input(starts at 1, increases per space).
int pos = 0;//the position as the input is iterated through
//loop to find the number and length of the arguments
while(input[pos]!='\0'){//until the end of the input is reached
if(input[pos]==' '){//if the end of the argument is reached
numArgs++;//increment argument counter
}
pos++;//increment the position counter
}
pos=0;//reset pos to reiterate through the input
//create an array of arguments
char* *argArray = malloc((1+numArgs)*sizeof(char*));
char *temp = strtok(input, " \n\r\t");//get the first token from the string
while(temp!=NULL) {
argArray[pos] =temp;
pos++;
temp=strtok(NULL, " \n\r\t");
}
argArray[pos]=NULL;
return argArray;
}
char * getLine() {
int buffspace = INIT_BUFFER;
char *buffer = malloc(sizeof(char)*INIT_BUFFER);
int pos = 0;
int c;//input
if(!buffer) {
fprintf(stderr, "Shell: Allocation Error\n");
exit(EXIT_FAILURE);
}
do {
c=getchar();//get the next character
if(c==EOF || c=='\n'||c=='\r') {
buffer[pos]='\0';
return buffer;
} else {
buffer[pos] = c;
}
pos++;
if(pos>=buffspace) {
buffspace += INIT_BUFFER;
buffer = realloc(buffer, buffspace);
}
} while(c!=EOF);
//the buffer should be returned before this point.
//Print out an error and exit
fprintf(stderr, "Shell: Assignment Error\n");
return buffer;
}
cmd* startHist() {
cmd *ret = malloc(20*sizeof(cmd));
for(int i=0;i<20;i++){
ret[i].arg = NULL;
ret[i].num = -1;
}
return ret;
}
cmd* updateHist(char **args, cmd *hist) {
for(int i = 19;i>0;i--) {
hist[i] = hist[i-1];
}
hist[0].arg = args;
if(hist[1].arg!=NULL) {
hist[0].num = hist[1].num+1;
} else {
hist[0].num = 1;
}
return hist;
}
void printHist(cmd *hist) {
int pos = 0;//index for iterating through commands
while(hist[pos].arg!=NULL) {
char* prstr = malloc(INIT_BUFFER*sizeof(char));//the string that will be printed
*prstr = '\0';
int index = 0;//index for iterating through arguments
printf("Cmd #%d: ", pos+1);
while(hist[pos].arg[index] != NULL) {
printf("%s ", hist[pos].arg[index]);
strcat(prstr, hist[pos].arg[index]);//concatenate the argument strings
index++;
}
printf("\n");
pos++;
free(prstr);
}
}