3

我使用 strcpy 和 sprintf 将一些值(例如长十进制)转换为 ar_hdr 结构的属性。当我打开存档时,它看起来像:

0000000    2   -   s   .   t   x   t  \0  \0  \0  \0  \0  \0  \0  \0  \0
0000020    1   3   7   4   0   8   7   6   3   2  \0  \0   5   0   1  \0
0000040   \0  \0   2   0  \0  \0  \0  \0   1   0   0   6   4   4  \0  \0
0000060    8   2  \0  \0  \0  \0  \0  \0  \0  \0   `  \n   2   2   2   2
0000100    2   2   2   2   2   2   2   2   2   2   2   2   2   2   2   2
*
0000140    2   2   2   2  \n   2   2   2   2   2   2   2   2   2   2   2
0000160    2   2   2   2   2   2   2   2   2   2   2   2   2   2   2   2
0000200    2   2   2   2   2   2   2   2   2   2   2   2   2  \n        
0000216

我想在“”(只是一个空格)时替换所有的“\0”。有人可以给我一个关于如何解决这个问题的提示吗?谢谢。下面是我写的一些代码。

int main (int argc, char **argv)
{
    char *archive = argv[1];
    char *read_file = argv[2];

    int in_fd;
    int out_fd;

    //char title[] = ARMAG;   //constant define in ar.h
    char buf[BLOCKSIZE];
    char tmpBuf[BLOCKSIZE];

    int num_read;
    int num_written;

    struct stat stat_file;
    struct ar_hdr my_ar;

    FILE *fp;

    //open read_file (i.e., text file)
    if (stat(read_file, &stat_file) == -1){
        perror("Error in Stat");
        exit(-1);
    }


    //open read file
    in_fd = open(read_file, O_RDONLY);
    if (in_fd == -1) {
        perror("Canot open/create output file");
        exit(-1);
    }

    //assign file info to struct dhr (my_ar)
    //all my_ar attributes = char []
    strcpy(my_ar.ar_name, read_file);
    sprintf(my_ar.ar_date, "%ld", stat_file.st_mtimespec.tv_sec);
    sprintf(my_ar.ar_uid, "%ld", (long)stat_file.st_uid);
    sprintf(my_ar.ar_gid, "%ld", (long)stat_file.st_gid);
    sprintf(my_ar.ar_mode, "%o", stat_file.st_mode);
    sprintf(my_ar.ar_size, "%lld", stat_file.st_size);
    strcpy(my_ar.ar_fmag, ARFMAG);




    //0666 - open archive
    out_fd = open(archive, O_CREAT | O_WRONLY | O_APPEND, 0666);
    if (out_fd == -1) {
        perror("Canot open/create output file");
        exit(-1);
    }


    //write my_ar struct to archive
    //num_written = write(out_fd, title, sizeof(title));
    off_t curpos = lseek(out_fd, SEEK_CUR, 0);  //get current position
    if(curpos == 0) {                           //if it is at beginning, it must be a new file
        num_written = write(out_fd, ARMAG, SARMAG);
        num_written = write(out_fd, &my_ar, sizeof(my_ar));
    }
    else
    {
        num_written = write(out_fd, &my_ar, sizeof(my_ar));
    }


    //add the file content to archive
    off_t in_fd_pos = lseek(in_fd, 0, SEEK_CUR);
    while ((num_read = read(in_fd, buf, BLOCKSIZE)) >0) {
        num_written = write(out_fd, buf, BLOCKSIZE);

        if (num_written != num_read) {
            perror("Error writing file");
            exit(-1);
        }
    }

    return 0;
}
4

2 回答 2

1

根据手册页sprintf()

成功返回后,这些函数返回打印的字符数(不包括null用于结束输出到字符串的字节)。

因此,为每个成员字段'\0'添加一个。sprintf()每个成员字段的其余'\0's 可能是由于 的初始化值my_ar。您可以通过 init 运行一个值expt来查看是否是这种情况。my_arnon-null

sprintf()返回写入了多少个字符的值。因此,您可以使用该字段替换'\0'为空格。

于 2013-07-22T16:07:04.107 回答
1

您的代码似乎将一些文本写入结构内的一些固定长度的字符串,但您没有为 提供定义struct ar_hdr,所以我不能确定。

然后,您将整个结构转储到一个文件中,但是因为每个字符串都是以 nul 结尾的,并且由于字符串之间存在未初始化的值(碰巧也包含 nul 字符),所以您的文件中会出现不需要的垃圾输出。

我建议您不要只是将内存转储到文件中。正确地完成这项工作要好得多。如何将数据写入文件,如下所示:

FILE *out_file = fdopen(out_fd);  /* or use fopen in the first place */
fprintf("%s %s %s %s %s %s", my_ar.ar_name, my_ar.ar_date, my_ar.ar_uid,
        my_ar.ar_gid, my_ar.ar_mode, my_ar.ar_size);

如果仍然需要固定长度的字符串,则在 printf 文档中查找字段宽度修饰符。

更好的是,根本不将数据存储为字符串,而只是直接从原始数据的(副本)中打印出来。

于 2013-07-22T16:42:28.573 回答