使用缓冲区大小时创建的空行

问题描述 投票:0回答:1

原文为

Make me a sandwich.
What? Make it yourself.
Sudo make me a sandwich.
Okay.

我必须改变它

~~像这样~~

Make me a sosandwich.
Whatot? Make itot yourorsoself.
SoSudo make me a sosandwich.
Okay.

给出了代码,我将 switch 语句添加到主函数

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

#include <string.h>

#define D_BUFSIZE       4096    /* size of buffer for input and output */
                                /* should be a block size, 512, 4096, 8192 */

#define NUM_ARGS_3      3
#define NUM_ARGS_4      4

#define ERROR_ARGS      1
#define ERROR_OPEN_R    2
#define ERROR_OPEN_W    3
#define ERROR_WRITE     4
#define ERROR_CALLOC    5

#define SUCCESS         0
#define ERROR           -1

int BUFSIZE = D_BUFSIZE;

int
main(int argc, char *argv[])
{
    char *input_file,
    *output_file,
    *buffer;
    int input_fd,
     output_fd;
    ssize_t return_num_bytes_write,
     return_num_bytes_read;
    off_t offset = 0;

    if (argc != NUM_ARGS_3 && argc != NUM_ARGS_4) {
        printf("Usage: %s source_file target_file [BUFSIZE]\n", argv[0]);
        return ERROR_ARGS;
    }

    if (argc == NUM_ARGS_4) {
        BUFSIZE = atoi(argv[3]);
    }

    if (argc == NUM_ARGS_3) {
        BUFSIZE = 1;
    }

    input_file = argv[1];
    output_file = argv[2];
    buffer = (char *) calloc(BUFSIZE, sizeof(char));
    if (buffer == NULL) {
        perror("calloc");
        return ERROR_CALLOC;
    }

    input_fd = open(input_file, O_RDONLY);
    if (input_fd == ERROR) {
        perror("open");
        return ERROR_OPEN_R;
    }

    output_fd = open(output_file, O_WRONLY | O_CREAT, 0644);
    if (output_fd == ERROR) {
        perror("open");
        return ERROR_OPEN_W;
    }
    while ((return_num_bytes_read = read(input_fd, buffer, BUFSIZE)) >= 0) {
        if (return_num_bytes_read == 0) {
            break;
        }
        int i;

        for (i = 0; i < sizeof(buffer); i++) {
            switch (buffer[i]) {
            case 'R':
                write(output_fd, "RoR", 3);
                break;
            case 'r':
                write(output_fd, "ror", 3);
                break;
            case 'S':
                write(output_fd, "SoS", 3);
                break;
            case 's':
                write(output_fd, "sos", 3);
                break;
            case 'T':
                write(output_fd, "ToT", 3);
                break;
            case 't':
                write(output_fd, "tot", 3);
                break;
            default:
                write(output_fd, &buffer[i], 1);
            }
        }
        if (return_num_bytes_read == ERROR) {
            perror("read");
            return ERROR;
        }
    }
}

它运行有点正确,但问题是 底部多了一个空行

Make me a sosandwich.
Whatot? Make itot yourorsoself.
SoSudo make me a sosandwich.
Okay.
(blank line created here)

// ------------------

底部不能有空行之类的

Make me a sosandwich.
Whatot? Make itot yourorsoself.
SoSudo make me a sosandwich.
Okay.

所以当我用 diff 命令比较这两个文件时, 然后它说不同,我认为这是因为底部有空行。

我找不到底部的空行造成的问题。

我怎样才能编辑它以获得正确的结果?

c buffer sizeof
1个回答
1
投票

我下载、构建并运行了您的程序。

最后我得到了二进制垃圾。但是,我使用的缓冲区大小为 1000。因此,尾随文本/数据会根据我们使用的缓冲区大小而变化。

您正在定义一个特定大小的缓冲区(一个 VLA 数组)。因此,

sizeof(buffer)
用于 entire 缓冲区,而不是从
read
调用中获得的数量。

如果我们指定 10,000 作为缓冲区长度,并且输入文本(例如)只有 75 个字节,我们将追加 9,925 个额外字节。因为

buffer
在栈上,任何没有被
read
填充的字节将“随机”。

所以,我们想应用修复 [按照 Fe2O3 的建议]。

变化:

for (i = 0; i < sizeof(buffer); i++) {

进入:

for (i = 0; i < return_num_bytes_read; i++) {

此外,如果我们应该将

O_TRUNC
添加到
open
以进行输出。

如果我们不先删除输出文件,然后运行程序两次,一次使用(例如)500 字节的输入文件。

并且,使用 较小 输入文件(例如 200 字节)输出到 same 输出文件的第二次运行,结果将包含第一个输入文件底部的“剩余”字符。


这里是重构代码:

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

#include <string.h>

#define D_BUFSIZE       4096    /* size of buffer for input and output */
                                /* should be a block size, 512, 4096, 8192 */

#define NUM_ARGS_3      3
#define NUM_ARGS_4      4

#define ERROR_ARGS      1
#define ERROR_OPEN_R    2
#define ERROR_OPEN_W    3
#define ERROR_WRITE     4
#define ERROR_CALLOC    5

#define SUCCESS         0
#define ERROR           -1

int BUFSIZE = D_BUFSIZE;

int
main(int argc, char *argv[])
{
    char *input_file,
    *output_file,
    *buffer;
    int input_fd,
     output_fd;
    ssize_t return_num_bytes_write,
     return_num_bytes_read;
    off_t offset = 0;

    if (argc != NUM_ARGS_3 && argc != NUM_ARGS_4) {
        printf("Usage: %s source_file target_file [BUFSIZE]\n", argv[0]);
        return ERROR_ARGS;
    }

    if (argc == NUM_ARGS_4) {
        BUFSIZE = atoi(argv[3]);
    }

    if (argc == NUM_ARGS_3) {
        BUFSIZE = 1;
    }

    input_file = argv[1];
    output_file = argv[2];
    buffer = (char *) calloc(BUFSIZE, sizeof(char));
    if (buffer == NULL) {
        perror("calloc");
        return ERROR_CALLOC;
    }

    input_fd = open(input_file, O_RDONLY);
    if (input_fd == ERROR) {
        perror("open");
        return ERROR_OPEN_R;
    }

#if 0
    output_fd = open(output_file, O_WRONLY | O_CREAT, 0644);
#else
    output_fd = open(output_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
#endif
    if (output_fd == ERROR) {
        perror("open");
        return ERROR_OPEN_W;
    }
    while ((return_num_bytes_read = read(input_fd, buffer, BUFSIZE)) >= 0) {
        if (return_num_bytes_read == 0) {
            break;
        }
        int i;

#if 0
        for (i = 0; i < sizeof(buffer); i++) {
#else
        for (i = 0; i < return_num_bytes_read; i++) {
#endif
            switch (buffer[i]) {
            case 'R':
                write(output_fd, "RoR", 3);
                break;
            case 'r':
                write(output_fd, "ror", 3);
                break;
            case 'S':
                write(output_fd, "SoS", 3);
                break;
            case 's':
                write(output_fd, "sos", 3);
                break;
            case 'T':
                write(output_fd, "ToT", 3);
                break;
            case 't':
                write(output_fd, "tot", 3);
                break;
            default:
                write(output_fd, &buffer[i], 1);
            }
        }
        if (return_num_bytes_read == ERROR) {
            perror("read");
            return ERROR;
        }
    }
}

在上面的代码中,我使用了

cpp
条件来表示旧代码与新代码:

#if 0
// old code
#else
// new code
#endif

#if 1
// new code
#endif

注意:这可以通过运行文件来清理

unifdef -k


这是修复后我得到的输出:

Make me a sosandwich.
Whatot? Make itot yourorsoself.
SoSudo make me a sosandwich.
Okay.
© www.soinside.com 2019 - 2024. All rights reserved.