0

ここで回答を確認し、自分の環境で実行した後、コードがまだ自分のコードと同じ問題を抱えていることがわかりました。この問題は、これに似た入力ファイルがあるときはいつでも...

 FILE A                 
|---------------------| 
| ABCDE               | 
| abcde               | 
|---------------------| 

宛先ファイルに余分な改行空白が生成されます。

 FILE B                 
|---------------------| 
| edcba               | 
|                     | 
| EDCBA               | 
|---------------------| 

コードをデバッグした後、'\n' が宛先ファイルに2 回コピーされていることがわかりました。lseek がこれを行っている理由を理解したいと思います。

添付は私のコードです。問題のクリティカル セクションは do/while ループにあります。私が調べたこの回答のコードはまったく同じ結果を出力するため、私の思考プロセスは健全であると確信しています。

#define CHAR_SIZE 2048 
#define BUFF_SIZE 1    
#define PERMS 0666   


int main(int argc, char* argv[]){                                          
    if (argc < 3) {                                                        
        return 1;                                                          
        printf ("ERROR: not enough arguments\n");                          
    }                                                                      
    int src_file = 0; int dest_file = 0;                                   
    int n = -1;                                                            
    if((src_file=open(argv[1],O_RDONLY)) < -1) return 1;                   
    if((dest_file = creat(argv[2], PERMS)) < -1) return 1;                 
    printf ("The filesize is: %d\n", lseek(src_file, (off_t) 0, SEEK_END));
    char buffer[BUFF_SIZE];                                                
    lseek (src_file,n--,SEEK_END);                                         
    do {                                                                   
        read(src_file,buffer,BUFF_SIZE);                                   
        printf ("%s", buffer);                                             
        write(dest_file,buffer,BUFF_SIZE);                                 
    }while (lseek (src_file,n--,SEEK_END) > -1);                           
    printf("\n");                                                          
    return 0;                                                              

}                       
4

2 に答える 2

1

あなたには多くの問題があります。余分な改行は、POSIX が行末をnewline(すべてのファイルが準拠しているわけではありませんが) として定義しているという事実から来ています。したがって、余分な改行を取り除くには、次のものが必要です。

int n = -2;

それ以外の

int n = -1;

(POSIX の行末を明示的に読み取り、それを出力ファイルに書き込みます)

追加の問題は、戻り値を間違ってチェックしているため、ファイルのオープンが失敗したかどうかがわからないことです。

// if ((src_file = open (argv[1],O_RDONLY)) < -1) return 1;
// if ((dest_file = creat (argv[2], PERMS)) < -1) return 1;

返品は-1失敗時です。したがって、次のものが必要です。

if ((src_file = open (argv[1],O_RDONLY)) == -1) return 1;
if ((dest_file = creat (argv[2], PERMS)) == -1) return 1;

次に、バッファは文字列を保持しません。少なくとも2-char、保持する配列と1-char文字nul-terminatingが必要です。以下は機能しません。

#define BUFF_SIZE 1
...
char buffer[BUFF_SIZE];
...
    printf ("%s", buffer);

終了していない文字を に送信しましたprintf警告を有効にしてコンパイルしている場合(例: -Wall -Wextra) は、コンパイラが警告するのでわかります (コンパイラによっては、適切な警告フラグがなくてもおそらく警告します)。上記の作業を行うには、少なくとも次のものが必要です。

#define BUFF_SIZE 2

を呼び出す前に、ヌル終了 を保証する必要があります。あなたはそれを達成することができます:bufferprintf

char buffer[BUFF_SIZE] = "";
...
    read (src_file, buffer, BUFF_SIZE - 1);
    buffer[1] = 0;
    printf ("%s", buffer);
    write (dest_file, buffer, BUFF_SIZE - 1);

(あなたはあなたが自分であると思うバイト数を読み書きしていることをread確認するために戻り値をチェックする必要があります...)write

修正をまとめると (そして、バッファを完全に削除して、単純intに buf char として使用できることを示します)、次のことができます。

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define CHAR_SIZE 2048
#define BUFF_SIZE 2
#define PERMS 0666

int main(int argc, char **argv) {

    if (argc < 3) {
        return 1;
        printf ("ERROR: not enough arguments\n");
    }

    int src_file = 0;
    int dest_file = 0;
    int n = -2;
    int nl = '\n';  /* explicit newline when writing in reverse */

    // if ((src_file = open (argv[1],O_RDONLY)) < -1) return 1;
    // if ((dest_file = creat (argv[2], PERMS)) < -1) return 1;
    if ((src_file = open (argv[1],O_RDONLY)) == -1) return 1;
    if ((dest_file = creat (argv[2], PERMS)) == -1) return 1;

    printf ("The filesize is: %ld\n", lseek(src_file, (off_t) 0, SEEK_END));

    lseek (src_file, n--, SEEK_END);
#ifdef WBUFCHAR
    int bufchar;
    do {    /* validate both read and write */
        if (read (src_file, &bufchar, BUFF_SIZE - 1) == 0) {
            fprintf (stderr, "error: read failure.\n");
            return 1;
        }
        putchar (bufchar);
        if (write (dest_file, &bufchar, BUFF_SIZE - 1) == 0) {
            fprintf (stderr, "error: write failure.\n");
            return 1;
        }
    } while (lseek (src_file, n--, SEEK_END) > -1);
#else
    char buffer[BUFF_SIZE];
    do {    /* validate both read and write */
        if (read (src_file, buffer, BUFF_SIZE - 1) == 0) {
            fprintf (stderr, "error: read failure.\n");
            return 1;
        }
        buffer[1] = 0;          /* nul-terminate */
        printf ("%s", buffer);
        if (write (dest_file, buffer, BUFF_SIZE - 1) == 0) {
            fprintf (stderr, "error: write failure.\n");
            return 1;
        }
    } while (lseek (src_file, n--, SEEK_END) > -1);
#endif
    /* explicity write the newline you removed earlier */
    if (write (dest_file, &nl, BUFF_SIZE - 1) == 0) {
        fprintf (stderr, "error: write failure.\n");
        return 1;
    }
    putchar ('\n');
    return 0;
}

注:通常どおりコンパイルして、buffer. でコンパイルし-DWBUFCHARてコードを使用しbufcharます。

コンパイルと出力の例

$ cat testabcde.txt
ABCDE
abcde

$ gcc -Wall -Wextra -Ofast -o bin/extranl extranl.c

$ ./bin/extranl testabcde.txt testrev.txt
The filesize is: 12
edcba
EDCBA

$ cat testrev.txt
edcba
EDCBA

$ gcc -Wall -Wextra -Ofast -DWBUFCHAR -o bin/extranlwbc extranl.c

$ ./bin/extranlwbc testabcde.txt testrevwbc.txt
The filesize is: 12
edcba
EDCBA

$ cat testrevwbc.txt
edcba
EDCBA

試してみて、さらに質問がある場合はお知らせください。

于 2016-03-23T05:54:15.780 に答える