0

在此处检查答案并在我的环境中运行它后,我发现代码仍然遇到与我的代码相同的问题。这个问题是,每当我有一个与此类似的输入文件时......

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

我在目标文件中生成了额外的换行符空格。

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

调试我的代码后,我可以看到 '\n' 被复制到目标文件中两次,我想了解为什么 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 将 line-end 定义为 a 的事实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

并且你必须确保你在调用之前nul-terminate 。您可以通过以下方式实现: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);

(您应该检查返回readwrite验证您正在读取/写入您认为的字节数......)

将更正放在一起(并显示您可以完全消除缓冲区并简单地将 anint用作 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 回答
0
#include <unistd.h>                                                         
#include <fcntl.h>                                                          
#include <sys/types.h>                                                      

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

int main(int argc, char* argv[]){                                           
    if (argc < 3) {                                                         
        printf ("ERROR: not enough arguments\n");                           
        return 1;                                                           
    }                                                                       
    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("%02x\n", *buffer);                                          
        if (*buffer == '\n')                                                
            n--;                                                            
        write(dest_file,buffer,BUFF_SIZE);                                  
    }while (lseek (src_file,n--,SEEK_END) > -1);                            
    printf("\n");                                                           
    return 0;                                                               

}                                                                           

此解决方案是修复输出文件中额外的换行符空格 (\n\n) 的最佳方法。

通过将此部分添加到 do/while 循环中,我可以补偿添加的额外 \n。

if (*buffer == '\n')                                                
                n--;
于 2016-03-23T07:14:05.103 回答