非常に基本的な作業、つまり配列のサイズを変更することには多くの問題があります。私がこれまでに学んだプログラミングクラスのすべてのイントロは、より大きな配列を作成し、それを充填し、元の配列を新しい(より大きな)配列に向けることによってこれを行うよう教えてくれました。文字ポインタのポインタへのポインタ、またはこの配列を再割り当てできないのはなぜですか?
以下のプログラムは、文字列をプログラム名とそのargv []にトークン化します(最終的に基本的なシェルの実装になります)。一度に8つの引数のためのスペースを割り当てます。もし8以上のものがあれば、それは再帰的に大きな配列を割り当てて、それを埋めます。
args配列からmoreArgs配列を指すことができない点を除いて、すべてうまくいっています(他にも教えてください)。私はgetArgs関数の最後にこれを行うべきですが、単にargs []のアドレスを再割り当てしないという声明があります。私は間違って何をしていますか?
#define debug 1
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
char ** getArgs(char *input, char **args, int ct);
/*Is there a better way than making these global?*/
char ** args;
char **moreArgs;
int main(int argc, char* argv[]) {
char input[]="echo arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9 arg10";
char inputcpy[strlen(input)];
strcpy(inputcpy, input);
char * temp;
temp=strtok(input, " ");
char * prog=temp;
args=(char **) calloc(8, sizeof(char*));
getArgs(inputcpy, args, 1);
if(debug) {
printf("arg address after: %p\n", args);
printf("morearg address after func: %p\n", moreArgs);
}
/*This is basically what the shell will look like. The actual implementation will use stdin
for input. (Unless a pipe or < is present in the input)*/
int q;
int pid=fork();
if (pid!=0) {
execvp(prog, args); //when moreArgs!=null, args should point to moreArgs
return 0;
}
else {
int status=0;
wait(&status);
}
}
/*This function should takes the first argument and inserts int into the second as " " separated tokens. If the second argument is too small -- the function recurses, and resizes the array as needed. The third argument is used to keep
track of the recursion*/
char ** getArgs(char *input, char **args, int ct) {
int adj=(ct-1)*8;//if we recurse, this ensures correct indexes are used
char *inputcpy=malloc(strlen(input));
strcpy(inputcpy, input);
/*Initialize indexes/Prepare for copying*/
int i;
if(ct==1) {
i=1; // this might throw off later adjusts
args[0]=" "; //quick hack to ensure all args are used by exec()
}
else
i=0;
/**Actually do the copying now**/
char *temp=strtok(NULL, " "); //What if later tokens are longer?
args[adj+i++]=temp;
while (temp != NULL && i<8) {
temp=strtok(NULL, " ");
args[adj+i++]=temp;
}
/*If there are more args than we have room for*/
if(i>=8){
//is this allocation right?
moreArgs = (char **) malloc((++ct)*8*sizeof(char *));
/*Fill moreArgs with args*/
int j;
for (j=0; /*j<ct*8 && */args[j]!=NULL; j++) {
moreArgs[j]=args[j];
}
getArgs(inputcpy, moreArgs, (ct)); //could probably move inc to malloc
//free(args)?
if(ct>1)
args=moreArgs;
}
/*Done with too many args problem*/
return NULL;//(char **) args; //we don't want the global args though
}
'realloc()'はあなたの友人です... –
私はコードをスキミングしましたが、 'calloc'はポインタ型を' NULL'ポインタに初期化することは技術的に保証されていません。整数の場合は数値ゼロを意味するオール・ビット・ゼロに初期化し、ヌル・ポインタが数値ゼロのプラットフォームの場合は「NULL」を初期化しますが、C言語レベルでゼロがNULLを保証する場合でもNULLポインターの機械語レベル表現は、「全ビット・ゼロ」であるとは保証されない。あなたのコードが 'calloc'-edポインタが' NULL'であるかどうかは分かりませんが、実際には間違っているとすれば、それは正しくありません。 –
@ChrisLutzうわー、私たちが対処しなければならないこと... –