尊敬的程序员。请你帮我(再次)如何将以下代码放入我的程序的函数中。 我已经在线阅读并了解功能是如何工作的,但是当我自己这样做时,这一切都变成了梨形/错误(我就是这样的菜鸟)。 请问您如何将下面的代码写入函数中(例如打开输入文件)。
我的初始代码如下:
main (int argc, char **argv)
{
int bytes_read, bytes_written;
struct stat inode;
int input_fd, output_fd;
char buffer[64];
int eof = 0;
int i;
/* Check the command line arguments */
if (argc != 3)
{
printf("syntax is: %s \n", <fromfile> <tofile>\n", argv[0]);
exit (1);
}
/* Check the input file exists and is a file */
if ((stat(argv[1], &inode) == -1) || (!S_ISREG(inode.st_mode)))
{
printf("%s is not a file\n", argv[1]);
exit(2);
}
/* Check that the output file doesnt exist */
if (stat(argv[2], &inode) != -1)
{
printf("Warning: The file %s already exists. Not going to overwrite\n", argv[2]);
exit(2);
}
/* Open the input file for reading */
input_fd = open(argv[1], O_RDONLY, 0);
if (input_fd == -1)
{
printf("%s cannot be opened\n", argv[1]);
exit(3);
}
output_fd = open(argv[2], O_CREAT | O_WRONLY | O_EXCL , S_IRUSR|S_IWUSR);
if (output_fd == -1)
{
printf("%s cannot be opened\n", argv[2]);
exit(3);
}
/* Begin processing the input file here */
while (!eof)
{
bytes_read = read(input_fd, buffer, sizeof(buffer));
if (bytes_read == -1)
{
printf("%s cannot be read\n", argv[1]);
exit(4);
}
if (bytes_read > > 0)
{
bytes_written = write(output_fd, buffer, bytes_read);
if (bytes_written == -1)
{
printf("There was an error writing to the file %s\n",argv[2]);
exit(4);
}
if (bytes_written != bytes_read)
{
printf("Devistating failure! Bytes have either magically appeared and been written or dissapeard and been skipped. Data is inconsistant!\n");
exit(101);
}
}
else
{
eof = 1;
}
}
close(input_fd);
close(output_fd);
}
我尝试打开输出文件:
void outputFile(int argc, char **argv)
{
/* Check that the output file doesnt exist */
if (stat(argv[argc-1], &inode) != -1)
{
printf("Warning: The file %s already exists. Not going to overwrite\n", argv[argc-1]);
return -1;
}
/*Opening ouput files*/
file_desc_out = open(argv[i],O_CREAT | O_WRONLY | O_EXCL , S_IRUSR|S_IWUSR);
if(file_desc_out == -1)
{
printf("Error: %s cannot be opened. \n",argv[i]); //insted of argv[2] have pointer i.
return -1;
}
}
对于我现在如何在我的程序中引用此内容的任何帮助,谢谢。 我试过了: ouputfile(但我无法弄清楚这里发生了什么以及为什么)。
答案 0 :(得分:4)
也许对你来说最有用的功能是:
#include <stdio.h>
#include <stdarg.h>
extern void error_exit(int rc, const char *format, ...); /* In a header */
void error_exit(int rc, const char *format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
exit(rc);
}
然后你可以写:
if (stat(argv[2], &inode) != -1)
error_exit(2, "Warning: The file %s exists. Not going to overwrite\n",
argv[2]);
具有简洁的优点。
您编写执行子任务的函数。决定将代码分解为函数的方法很棘手 - 与科学一样多的艺术。你的代码不是那么大,以至于完全不能保留它 - 一个函数(尽管错误处理可以简化如上)。
如果您想练习写作功能,请考虑将其拆分:
open_input_file()
open_output_file()
checked_read()
checked_write()
checked_close()
这些函数可以将您的主代码写成:
int main(int argc, char **argv)
{
int bytes_read;
int input_fd, output_fd;
char buffer[64];
if (argc != 3)
error_exit(1, "Usage: %s <fromfile> <tofile>\n", argv[0]);
input_fd = open_input_file(argv[1]);
output_fd = open_output_file(argv[2]);
while ((bytes_read = checked_read(input_fd, buffer, sizeof(buffer)) > 0)
check_write(output_fd, buffer, bytes_read);
checked_close(input_fd);
checked_close(output_fd);
return 0;
}
因为你已经将错误处理隐藏起来了,所以现在可以更容易地看到程序的结构。如果您还没有足够的功能,可以将循环隐藏到函数void file_copy(int fd_in, int fd_out)
中。这样可以消除main()
中更多的混乱,并为您提供非常简单的代码。
初次尝试打开输出文件的函数:
void outputFile(int argc, char **argv)
{
/* Check that the output file doesnt exist */
if (stat(argv[argc-1], &inode) != -1)
{
printf("Warning: The file %s already exists. Not going to overwrite\n", argv[argc-1]);
return -1;
}
/*Opening ouput files*/
file_desc_out = open(argv[i],O_CREAT | O_WRONLY | O_EXCL , S_IRUSR|S_IWUSR);
if(file_desc_out == -1)
{
printf("Error: %s cannot be opened. \n",argv[i]); //insted of argv[2] have pointer i.
return -1;
}
}
批判:
int
。stderr
,而不是stdout
。主程序输出(如果有)转到stdout
。argv[i]
或argv[argc-1]
是否为输出文件的名称感到困惑。从某种意义上说,一旦你将文件名传递给函数,这种批评就无关紧要了。但是,一致性是编程的一个主要优点,使用相同的表达式来识别相同的东西通常是一个好主意。if(
和if (
;使用语言创始人K&amp; R使用的规范if (
符号。|
”等运算符周围的空格保持一致。一致性使您的代码更易于阅读,并且您将比编写代码更频繁地阅读代码(至少,一旦完成课程,您将阅读的内容比写作更多。)return -1;
。当您将代码拆分为函数时,您需要复制/移动要提取的代码段落,并留下对新函数的调用。您还需要将相关的局部变量从调用函数复制到新函数中 - 如果在那里不再使用它们,可能会消除调用函数中的变量。你编译时启用了大多数警告,不是吗?您想了解未使用的变量等。
创建新函数时,最重要的部分之一是确定函数的正确签名。它会返回一个值吗?如果是这样,哪个值,它的类型是什么?如果没有,它如何处理错误?在这种情况下,如果遇到错误,您可能希望该函数能够挽救(终止程序)。在较大的系统中,您可能需要始终返回错误指示符(0表示成功,负表示失败,不同的负数表示不同的错误)。使用返回错误指示符的函数时,检查调用代码中的错误指示符几乎总是至关重要的。对于大型程序,代码的大部分都可以用于错误处理。同样,您需要确定将哪些值传递给函数。
我在学习用C语言编程时,忽略了诸如“be const correct”之类的建议,因为你的舞台有些过分。
答案 1 :(得分:1)
有几件事。
函数返回类型不是您想要的。您要么返回文件描述符或错误代码。 IIRC,文件描述符是非负int
,因此您可以使用int
而不是void
的返回类型。您还需要在任一路径上返回一些内容,-1或file_desc_out
。
您可能不希望整体传递命令行参数,而是传递argv[argc - 1]
之类的东西。在这种情况下,参数应该是char * filename
而不是它现在的argc / argv。 (请注意,您在上一个argv[i]
中获得的printf
几乎肯定是错误的。)
这意味着它会被称为
int file_desc_out = outputFile(argv[argc - 1]);
您需要在函数中声明所有变量,特别是inode
和file_desc_out
。
最后,在函数本身的{
和}
内的代码上添加额外的缩进级别。
答案 2 :(得分:1)
你似乎真正理解如何制作一个功能。制作一个功能真的不是那么难。首先,你需要了解一个函数有一个类型。换句话说,argc的类型为int
,argv的类型为char *
,您的函数(当前)的类型为void
。无效意味着它没有价值,这意味着当你返回时,你什么都不返回。
但是,如果您查看代码,则执行return -1
。看起来你想要回复一个整数。所以你应该将顶部从void outputfile(...)
更改为int outputfile(...)
。
接下来,您的函数必须返回。如果存在不会返回的情况(除了无限循环)之外它不会编译。所以在最底层,如果没有错误发生,它将到达终点。因为您不再使用“void”作为返回类型,所以必须在函数结束之前返回一些内容。所以我建议用return 1;
来表明一切都很顺利