原文为
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 命令比较这两个文件时, 然后它说不同,我认为这是因为底部有空行。
我找不到底部的空行造成的问题。
我怎样才能编辑它以获得正确的结果?
我下载、构建并运行了您的程序。
最后我得到了二进制垃圾。但是,我使用的缓冲区大小为 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.