0

对于家庭作业,我用 C 语言编写了一些代码来打印出存储在 achive 文件中的文件的权限和文件名。我的代码可以编译,但由于某种原因,第二个文件的名称在新行中返回。

这是我的输出在终端中的样子:

rw-r--r-- 501/20 1-s.txt        
rw-r--r-- 501/20 
2-s.txt       
(empty blank line here)

这就是我希望输出的样子:

rw-r--r-- 501/20 1-s.txt        
rw-r--r-- 501/20 2-s.txt 
(no empty blank line here)

有人可以看看我的代码并给我一些关于如何修复我的代码的提示吗?我怀疑这与我阅读和选择文件名(使用my_ar.ar_name)的方式有关,但我不知道如何修复它。感谢您的时间。

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/utsname.h>
#include <ctype.h>
#include <string.h>
#include <ar.h>


int main (int argc, char **argv)
{
    FILE *fp;
    size_t readNum;
    long long tot_file_size, cur_file_size;
    struct stat fileStat;
    struct ar_hdr my_ar;


    //open the archive file (e.g., hw.a)
    fp = fopen(argv[1], "r");
    if (fp == NULL)
    {
        perror("Error opening the file\n");
        exit(-1);
    }

    //size of the archive file
     fseek(fp, 0, SEEK_END);
     tot_file_size =ftell(fp);
     rewind(fp);


    //read data into struct
    fseek(fp, strlen(ARMAG), SEEK_SET); 

    file_size_cnt = 0;
    while (ftell(fp) < tot_file_size - 1)
    {
        readNum = fread(&my_ar, sizeof(my_ar), 1, fp);

        if (stat(argv[1], &fileStat) == -1) {
            perror("stat");
            exit(EXIT_FAILURE); 
}


        if ((fileStat.st_mode & S_IFMT) == S_IFREG)
        {

            printf( (fileStat.st_mode & S_IRUSR) ? "r" : "-");
            printf( (fileStat.st_mode & S_IWUSR) ? "w" : "-");
            printf( (fileStat.st_mode & S_IXUSR) ? "x" : "-");
            printf( (fileStat.st_mode & S_IRGRP) ? "r" : "-");
            printf( (fileStat.st_mode & S_IWGRP) ? "w" : "-");
            printf( (fileStat.st_mode & S_IXGRP) ? "x" : "-");
            printf( (fileStat.st_mode & S_IROTH) ? "r" : "-");
            printf( (fileStat.st_mode & S_IWOTH) ? "w" : "-");
            printf( (fileStat.st_mode & S_IXOTH) ? "x" : "-");

            printf("%.*s", 15, my_ar.ar_name);
            printf("\n");

        }

        cur_file_size = atoll(my_ar.ar_size);

        if (fseek(fp, cur_file_size, SEEK_CUR) != 0)
        {
            perror("You have an error.\n");
            exit(-1);
        }

    }

    //printf("\n");
    fclose(fp);

    return 0;
}
4

2 回答 2

0

有很多问题。

  1. OPif (stat(argv[1], &fileStat) == -1) ...好奇地反复查询“文件的文件名”的文件状态,而不是my_ar.ar_name. 因此将出现相同的文件统计信息。

  2. 第一次使用printf("%.*s", 15, my_ar.ar_name)给出了“501/20 1-s.txt”。这看起来像一个不寻常的文件名。该ar_name字段为“如果文件成员名称适合,ar_name 字段直接包含名称,并以斜杠(/)终止并在右侧填充空格。如果成员名称不适合,ar_name 包含斜杠(/ ) 后跟下面描述的存档字符串表中名称偏移量的十进制表示。" 因此,存在/意味着您需要做更多的工作来提取文件名。也可能是字段不是NUL 字节终止的。OP 需要继续阅读struct ar_hdr。试试:http ://www.lehman.cuny.edu/cgi-bin/man-cgi?ar.h+3

  3. 在这段代码中错误地提取的文件名可能包含也可能不包含令人惊讶的字节。我确信这就是为什么您在第二行输出中看到意外的行尾。测试可打印 ASCII 的文件名char是谨慎的。isprint()

于 2013-09-06T18:20:59.317 回答
0

您不想打印新行吗?所以不要打印!

删除这个:

printf("\n");

它位于代码的末尾。

编辑

我猜你不想完全删除它,但你想在除最后一次之外的任何时间打印它。

if (ftell(fp) != tot_file_size - 1) {
    printf("\n");
}

编辑 V1.1

改进后,我在我的 linux mint 13 下运行了你的代码。这是我的输出:

rw-r--r--a.txt/         
rw-r--r--b.txt/ 

这是你想要的格式,不是吗?

于 2013-07-19T16:57:48.760 回答