C:将以下代码写入函数

时间:2010-12-21 17:13:41

标签: c

尊敬的程序员。请你帮我(再次)如何将以下代码放入我的程序的函数中。 我已经在线阅读并了解功能是如何工作的,但是当我自己这样做时,这一切都变成了梨形/错误(我就是这样的菜鸟)。 请问您如何将下面的代码写入函数中(例如打开输入文件)。


我的初始代码如下:

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(但我无法弄清楚这里发生了什么以及为什么)。

3 个答案:

答案 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]);

您需要在函数中声明所有变量,特别是inodefile_desc_out

最后,在函数本身的{}内的代码上添加额外的缩进级别。

答案 2 :(得分:1)

你似乎真正理解如何制作一个功能。制作一个功能真的不是那么难。首先,你需要了解一个函数有一个类型。换句话说,argc的类型为int,argv的类型为char *,您的函数(当前)的类型为void。无效意味着它没有价值,这意味着当你返回时,你什么都不返回。

但是,如果您查看代码,则执行return -1。看起来你想要回复一个整数。所以你应该将顶部从void outputfile(...)更改为int outputfile(...)

接下来,您的函数必须返回。如果存在不会返回的情况(除了无限循环)之外它不会编译。所以在最底层,如果没有错误发生,它将到达终点。因为您不再使用“void”作为返回类型,所以必须在函数结束之前返回一些内容。所以我建议用return 1;来表明一切都很顺利