いくつかの値を保持する「input.txt」というファイルがあります。そのファイルで最小値を見つけ、その最小値をコマンドライン引数として指定された数値に置き換えるプログラムを書いています-そのコマンドライン引数が最小値よりも大きい場合。これらの値は室温を表すため、事実を使用して最小値を見つけることができます。さらに、ファイルのその部分 (新しい番号が最小値に置き換わる場所) をロックする必要があります。
例:
$ ./prog 23
ファイル: 21 25 19 22 24
ファイル: 21 25 23 22 24
$ ./prog 29
ファイル: 21 25 23 22 24
ファイル: 29 25 23 22 24
コード:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdint.h>
/* Function that handles errors */
void fatal_error(const char *message){
perror(message);
exit(EXIT_FAILURE);
}
int main(int argc, char **argv){
if(argc != 2)
fatal_error("Bad arguments.\n");
/* Fetching command line argument */
int temp = atoi(argv[1]);
/* Opening file and checking for errors */
FILE *file = fopen("input.txt", "r+");
if(!file)
fatal_error("Unable to open file.\n");
/* Finding minimum in the file */
int min = 200;
int value;
while(fscanf(file, "%d", &value) != EOF)
if(value < min)
min = value;
/* Exiting if nothing needs to change */
if(temp <= min)
return 0;
/* Creating file descriptor from stream and checking for errors */
int fdOpen = fileno(file);
if(fdOpen == -1)
fatal_error("Unable to open file descriptor.\n");
/* Moving offset to the beginning of the file */
off_t of = lseek(fdOpen,0,SEEK_SET);
printf("Ofset pre petlje: %jd\n", (intmax_t)of);
while(1){
/* I'm reading file all over again */
if(fscanf(file, "%d", &value) == EOF)
fatal_error("Reached end of file.\n");
/* If I reached minimum */
if(value == min){
/* I lock that part of the file - temperatures are two digit numbers*/
struct flock lock;
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_CUR;
lock.l_start = -2;
lock.l_len = 2;
/* I create lock */
if(fcntl(fdOpen,F_SETLK, &lock) == -1){
if(errno == EACCES || errno == EAGAIN)
fatal_error("File is locked.\n");
}
/* Moving two positions back from current position */
off_t offset;
if((offset = lseek(fdOpen, -2, SEEK_CUR)) == -1)
fatal_error("lseek error.\n");
/* Inserting read command line value into file */
fprintf(file, "%d", temp);
/* Unlocking */
lock.l_type = F_UNLCK;
if(fcntl(fdOpen, F_SETLK, &lock) == -1)
fatal_error("Unable to destroy lock.\n");
/* Closing file descriptor, and breaking loop */
close(fdOpen);
break;
}
}
return 0;
}
ただし、これは機能しません。ファイルは変更されません。問題は、これが正しい方法であることを知っていることです。私は基本的に、単語"aa"の出現ごとに"bb"に変更する同じプログラムを作成しました。基本的に同じコンセプトです。
私はもう試した:
- ループの前後にオフセットをフェッチしようとしまし
fscanf()
た 。while()
最初のfscanf
オフセットが 0 に設定される前 - ファイルの先頭。最初のfscanf
オフセットがファイルの最後に設定された後、各反復の後、オフセットはファイルの最後に残ります。 ftell()
これらと同じものを使用しprintf()
てみましたが、ftell()
正しいオフセットが得られます。ただしftell()
、 while ループではまだファイルの終わりが返されます。私もfseek()
代わりに 使用してみました(実装での使用lseek()
を知っていても)。それでも同じ結果。fseek()
lseek()
char*
値の代わりにバッファを使用してみました。基本的にはfscanf(file,"%s",buffer)
、その値を変換して読み取り値が最小かどうかを確認し、その後、それfprintf(file,"%s",buffer)
を記述するのに使用しました。でも同じ結果。- ファイル全体をロックしようとしましたが(おそらく問題があると思いました)、同じ結果になりました。
コード:
これは、同じ概念を使用する、私が言及した2番目のプログラムです。このコードは機能しますが、ここでもオフセットを印刷しようとしましたが、オフセットもファイルの最後にあります。
int main(int argc, char **argv){
if(argc != 4)
fatal_error("You must enter exactly 4 arguments.\n");
FILE *f = fopen(argv[1], "r+");
if(!f)
fatal_error("Unable to open file for reading and writing.\n");
int fd = fileno(f);
if(fd == -1)
fatal_error("Unable to fetch file descriptor for file.\n");
char word[MAX_LEN + 1];
int word_len = strlen(argv[2]);
while(fscanf(f,"%s",word) != EOF){
printf("%jd\n", lseek(fd,0,SEEK_CUR));
if(!strcmp(argv[2],word)){
struct flock lock;
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_CUR;
lock.l_start = -word_len;
lock.l_len = word_len;
if(fcntl(fd, F_SETLKW, &lock) == -1)
fatal_error("File locking failed.\n");
if(lseek(fd, -word_len, SEEK_CUR) == -1)
fatal_error("Lseek error.\n");
fprintf(f, "%s", argv[3]);
lock.l_type = F_UNLCK;
if(fcntl(fd, F_SETLK, &lock) == -1)
fatal_error("Failed to release lock.\n");
}
}
}
ご覧のとおり、まったく同じ概念です。2 番目のプログラムは機能しますが、最初のプログラムは機能しません。
私は今とても混乱しています。ファイルストリームからファイル記述子を作成lseek()
し、そのファイル記述子を使用してオフセットを変更すると、ストリームのオフセットも変更されますか? fscanf()
また、ストリームから何かを読み取るために使用する場合offset_t
、ファイルから読み取るのと同じくらい変更しますか? fscanf()
フォーマット指定子%d
とを使用する場合、オフセットの変更に違いはあり%s
ますか?