2016-12-06 14 views
0

現在、私はargc、argv、tempのピースを渡しますが、コンパイルするとエラーは発生しませんが、後でプログラムで関数を呼び出してchar配列を渡すと。スタックダンプを返します。今まで私が学んだことから、配列は関数から戻すことができず、それがポインタを渡した理由です。ファイルを配列に作成する

int In2File(int argc, char *argv[], char *temp[]){ 

    if (argc == 2) { //open file 
     FILE *user_file; 
     user_file = fopen(argv[1], "r"); 
     if (user_file == NULL) { 
      printf("No data was found.\nEnd(Error 1)"); 
      exit(2); 
     } 
     else { 
      int g = 0;//temp counter to load 
      char c = 0; 
      while ((c = fgetc(user_file)) != EOF && g <= tmplng - 1) { //Used Fgetc instead of fgets because Fgetc allows me to read 
       *temp[g] = c;      //until the end of the file and read each character. Even if there is an \n character. 
       g++;        // The second g < tmplng-1 is used to make sure that the \0 can be placed into the array. 
      } 
      printf("%s\n", temp); 
      fclose(user_file);//Closed the txt file that was loaded by user in args(1)   
      printf("\nFile Loaded.\n"); 
     } 
    } 
    else if (argc > 2) { // Will exit if arguments are greater than 2. 
     printf("Format: %s 'filename'", argv[0]); 
     exit(1); 
    } 
    else { 
     printf("File not provided. Enter information:\n");//If the user doesnt provide a file allow manual input. 
     fgets(*temp, tmplng, stdin); 
    } 
} 

In2File(argc、argv、temp);

誰かが私がこの機能でどこが間違っていたのか考えていますか?私はいくつかの同様の記事を読んだが、C++とPythonのためのものだった。私はまだC++を学んだhaventはとPythonはC.

と呼ばれるこの獣に異なっている

編集:

const int tmplng = 1000; //The only variables needed 
    char temp[tmplng];  // 
    char temp2[tmplng];  // 

    printf("Starting....\n"); //Used for testing debugging. 
+1

不要な 'else'ステートメントをすべて取り除くと、そのコードは簡単に従うことができます。例えば、 'exit(2);の後に' else 'はありません。 –

+1

tmplngと同様に、いくつかのことをはっきりと理解できないので、コードをさらに追加してください。 –

+2

この関数はどのように呼び出され、3番目の引数はどのように宣言されていますか? – dbush

答えて

3

関数の3番目のパラメータは、関数が期待しているものと一致しません。 char [](これはchar *に減衰します)、関数はchar *[](関数のパラメータとしてはchar **に相当)を想定しています。

第3パラメータの定義は、文字配列として使用する方法と一致しません。

パラメータで余分なレベルの間接参照を取り除き、それに従って関数を調整します。

int In2File(int argc, char *argv[], char temp[]){ 
     ... 
     while ((c = fgetc(user_file)) != EOF && g <= tmplng - 1) { 
      temp[g] = c; 
      g++; 
     } 
+0

ええ、私は今それをやります。あなたの時間と援助に感謝します。だから、明確にするために、ポインタのポインタを渡すときにダブルアスタリスク(**)を使用しますか? –

+0

@DamaniAPhilip正解。この場合、ポインタがあります。 – dbush

0

tempのこの宣言:

char temp[tmplng]; 

...この呼び出しに行かない...

In2File(argc,argv,temp); 

...へこの機能...

int In2File(int argc, char *argv[], char *temp[]); 

関数は、3番目の引数がchar *へのポインタへのポインタであることを期待し、しかしそれが受信するcharへのポインタです。次に、文字読み取りを割り当てるしようとすると、...

*temp[g] = c; 

間接参照からchar *としてtempg番目の要素を(それ自体がchar **として解釈)、解釈しようとしますその場所にcを割り当てます。これは、有効なメモリアクセスである可能性は非常に低いです。

あなたが同等である、char *tempchar temp[]のいずれかとしIn2Fileの第三引数を宣言するために、そしてtemp[g] = cとしてそれを書きたいように見えます。ALSO

、余談として、あなたは tempはnull終端であることを保証しませんのでご

printf("%s\n", temp); 

に問題があることに注意してください。最後のバイトまで読み上げることをサポートしている限り、それを終了させる余地はありません。

+0

この非常に詳しい説明をありがとう、私はまたあなたの小切手で印をつけました、そして、今これが私を助けました。もう一度ありがとうございます –

0

多くの人々がコメントに指摘しているように、エラー条件に「早期終了」を採用すると、コードがはるかに理解しやすくなります。

mainはプログラムの引数を扱い、In2Fileはファイルポインタを扱わなければならないという懸念がより明確になります。

int main(int argc, char *argv[]) { 
    FILE *fp; 

    if(argc == 2) { 
     fp = fopen(argv[1], "r"); 
     if (fp == NULL) { 
      fprintf(stderr, "Couldn't open %s: %s", argv[1], strerror(errno)); 
      exit(2); 
     } 
    } 
    else if(argc > 2) { 
     fprintf(stderr, "Usage: %s <optional filename>", argv[0]); 
     exit(1); 
    } 
    else { 
     fp = stdin; 
    } 

    char *lines = In2File(fp); 

    printf("%s\n", lines); 

    free(lines); 
} 

stdinはちょうどあなたがfopenで開かれたもののようなファイルポインタであることに注意してください。また、ファイルが開かれなかった理由を提供するためにstrerrorerrnoを使用しました。

今すぐIn2Fileはファイルポインタをとります。また、事前に割り当てられた配列を渡さずに、コンテンツを返すようにしています。これは、入力から読み込むときにどれくらいの入力を得るのか分からないからです。スペースがなくなる前に読書を止めるか、もっと多くのメモリを割り当てる必要があります。スタックメモリを再割り当てすることはできませんので、In2Fileがメモリを割り当てるように制御することをお勧めします。また、グローバル変数を渡す必要もありません。

これが完了すると、In2Fileははるかに簡単になります。

static char *In2File(FILE *fp){ 
    size_t read_size = 1024; 

    /* Don't forget space for null */ 
    char *content = calloc(read_size + 1, sizeof(char)); 

    fread(content, sizeof(char), read_size, fp); 

    return content; 
} 

ではなく時に文字をステップ実行、私はファイルではありません、私が割り当てられてきた量よりも大きいからブロックを読み取るためにfreadを使用しました。メモリの再割り当ては別の時間の話題です。

+0

ありがとうございます。私はstderr、errno、callocのような新しい関数を研究します。私はまだこれらを学んでいないし、この機能を作ろうとしているうちに私が頭の中に入っているように見える。笑私はもっと本を読んで、本に戻ります。 –

関連する問題