コードにはいくつかの問題があります。まず第一に、whileループでは、i
がMAX
より大きいかどうかをテストする必要があります。その場合は、バッファオーバーフローを避けるためにループを終了する必要があります。今のように、ファイルが1024文字より長い場合は、配列の外側に書き込もうとしているためクラッシュします。これを回避するには、(i++
後)whileループにこのコードを追加します。
if(i + 1 >= MAX){
break;
}
break;
コマンドは、whileループを終了します。
第2に、文字列はヌル文字で終わる必要があります。
rez[i] = '\0';
buf[i] = '\0';
注意をi
がMAX
よりも大きい場合はテストするときには、私たちはヌル文字のためのスペースを残してif(i + 1 >= MAX)
の代わりif(i >= MAX)
をしたこと:だからあなたは、このようなwhileループの後に、各文字列にnull文字を追加する必要があります。
第3に、free
を使用しないでmalloc
を使用しないでください。そうしないとメモリリークが発生します。あなたはこのようなあなたのプログラムの最後にrez
とbuf
を解放する必要があります。
free(rez);
free(buf);
あなたのケースで動作しますが、常にmalloc
を使用せずにrez
とbuf
など単純な配列を宣言するだろうではない、これに代わる:
char buf[MAX];
char rez[MAX];
MAX
はマクロであり、変数ではありません。
第4に、ポインタを初期化しないでください。その代わり、NULL
にそれを初期化します。
char *buf = NULL;
しかし、あなたの場合には、直接malloc
にそれを初期化する方が良いでしょう:
char *buf = (char*)malloc(sizeof(char) * MAX);
注Cには、それが必要でも推奨されていないことmalloc
の結果をキャストします(ただし、C++では必須です)。したがって、次のコードはより良いでしょう:
char *buf = malloc(sizeof(char) * MAX);
詳細については、thisを参照してください。
第5に、コメントに示唆されているように、メモリ割り当てがmalloc
から失敗したかどうかをチェックする必要があります。その場合は、未定義の動作を避けるためにプログラムを終了する必要があります。メモリ割り当てに失敗した場合、戻り値はmalloc
で、NULL
になります。それはあなたがmalloc
後に配置する必要があることを、このコードを与える:
if(rez == NULL || buf == NULL){
printf("Memory allocation failed.\n");
exit(8);
}
あなたがstandard return valuesをフォローしたい場合は、この場合の戻り値は8になります。もちろん、あなたが標準に従わないことを望むなら、あなたが望む価値を返すことができます。標準に準拠したい場合は、ファイルが見つからなければ戻り値も2でなければなりません(コードのように1ではありません)。マクロERROR_FILE_NOT_FOUND
(2に等しい)とERROR_NOT_ENOUGH_MEMORY
(8に等しい)を使用することもできます。これらのマクロはwindows.h
にあります(Linuxを使用しているのでこのファイルがあるかどうかわかりませんが)。
次のようになり働くあなたのコードのバージョン:
#include <stdio.h>
#include <stdlib.h>
#define MAX 1024
int main(int argc, char **argv){
FILE *f1;
char *buf = malloc(sizeof(char) * MAX);
char *rez = malloc(sizeof(char) * MAX);
if((f1=fopen("fis4.txt", "r")) == NULL){
printf("Error\n");
exit(2);
}
if(rez == NULL || buf == NULL){
printf("Memory allocation failed.\n");
exit(8);
}
int i = 0;
while((buf[i] = fgetc(f1)) != EOF){
rez[i] = buf[i];
i++;
if(i + 1 >= MAX){
break;
}
}
rez[i] = '\0';
buf[i] = '\0';
printf("%s", rez);
free(rez);
free(buf);
fclose(f1);
return 0;
}
文字列は 'char'sのシーケンスです。 NUL文字 ''\ 0' 'で終了する必要があります。 NULは何を読み終えたのですか? – StoryTeller
したがって、rez [i] = '\ 0'のように、whileループの外側で最後の位置に '\ 0'を追加すると動作しますか? (それでも、私は正しく理解していないと思うので) – DanielsQuestions
私のコードに間違いがあります。 rez [i] = buf [0 \、1番目の位置から一度に1つの文字を読み込むので、これはすべきです。今は – DanielsQuestions