逐行散列文件

时间:2018-11-06 21:03:02

标签: c

我正在尝试编写一个程序,该程序将读取用户提供的.txt文件,并使其输出哈希列表。到目前为止,这就是我所掌握的,我无法弄清楚如何打开文件并散列单个单词。而是散列文件名。

#include < stdio.h >
#include < string.h >
#include "md5.h"//char *md5(const char *str, int length);
#include < stdlib.h >

int main(int argc, char * argv[]) //argc: # of arguments argv: inputand utput
{
  FILE * fp;
  fp = fopen(argv[1], "r");
  if (!fp) {
    printf("Can't open %s for reading\n", argv[1]);
    exit(1);
  }

  FILE * out;

  if (argc != 3) //(argc < 2 || argc > 3)
  {
    printf("Usage: %s word_to_hash [output_file]\n", argv[0]);
    exit(1);
  }


  out = fopen(argv[2], "w");

  FILE * fpout;
  if (argc == 3) {
    fpout = fopen(argv[2], "w");
    if (!fpout) {
      printf("Can't open %s for writing\n", argv[2]);
      exit(1);
    }
  }


  char line[100];
  while (fgets(line, 100, fp) != NULL) {
    if (argc == 3) fclose(fpout);

    if (argc != 3) //(argc < 2 || argc > 3)
    {
      fprintf("%s", "r");//printf("Usage: %s word_to_hash [output_file]\n", argv[0]);
      exit(1);
    }

    out = fopen(argv[2], "w");
    if (argc == 3) {
      out = fopen(argv[2], "w");
      if (!out) {
        printf("Can't open %s for writing.\n", argv[1]);
        exit(2);
      }
    }
    else
      out = stdout;

    char * hash = md5(argv[1], strlen(argv[1]));
    fprintf(out, "%s\n", hash);

    if (argc == 3)
      fprintf(fpout, "%s", line);
    else
      printf("%s", line);
  }

  // Close file
  fclose(fp);

}

// clang hashpass.c md5.c -o hashp -l crypto

//../ hashp words.txt output.txt

^这些分别是我用来编译和运行程序的内容。 Words.txt是我试图读取我的代码的单独文件。非常感谢能正确打开文件的任何帮助。

1 个答案:

答案 0 :(得分:2)

您的代码的主要问题是-它听起来像是杂乱无章的事情,您认为尝试做一个好主意,所以您添加了它们,编译了它,失败了,更改了一些东西,编译了,它失败了, (然后您重复一遍,直到您如此绝望地迷路了,您需要寻求帮助)–那不是您编程的方式...

编程,每个表达式都有其含义,如果您希望编写能够完成任何任务的程序,则必须准确理解每个表达式的功能。这样做的方法是拿起铅笔和纸,并概述完成任务所需执行的步骤。然后,您研究语言提供的功能以使您完成每个步骤,并通过参考文档了解如何正确使用每个功能(对于您拥有的每个功能,可以是Linux手册页,MSDN页面或C-Standard。决定使用)。

您需要先完成所有 操作,然后拿起键盘并开始查看您的代码。虽然看起来这种方法需要大量的精力和时间-您用“猜测,编译,失败,重复” 方法浪费了多少时间?正确的方法实际上会缩短从头到尾花费的时间。

好的,在这样的背景下,很明显,您需要一点帮助才能指出正确的方向。正如您现在可能已经猜到的那样,在您的代码中对out = fopen(argv[2], "w");进行3次调用是毫无意义的,这真是令人困惑,为什么您会从fp中读取一行然后立即关闭{{1} }(认为它从未使用过),例如

fpout

此外,您已经陷入了写 while (fgets(line, 100, fp) != NULL) { if (argc == 3) fclose(fpout); argv[2]的逻辑中。对于这种大小的代码,这就是简单的外壳 redirection 的用途(在Linux,Windows和Mac上相同)。不必担心打开输出文件,只需写入stdout,如果要输出到文件,则可以在命令行上将输出重定向到文件,例如

stdout读取并写入stdin

stdout

$ yourprogram < somefile 读取并将stdin重定向到文件

stdout

您可以执行同样的操作来读取用$ yourprogram < somefile > output file 打开的文件,只需删除开头的fopen (name, "r")

以这种方式处理输入和输出可简化读写,让您专注于代码的主要目标。

考虑到这一点,您可以删除代码中的大部分内容,只需打开'<'给出的文件以进行读取(或者,如果未提供任何参数,则只需从argv[1]中读取)即可默认)。下面的示例正是这样做的,并且将stdin用于MD5哈希,因为我们无法知道您的<openssl/md5.h>所包含的内容。此外,如果定义了"md5.h"(通过在编译器选项中简单地包含HASHLINE),以下示例将对输入中的每个 line 进行哈希处理,或者对每个 word进行哈希处理默认情况下,如果未定义-DHASHLINE。该示例使用其他代码进行编码,因为完全不清楚是要在描述和变量名中同时使用哈希值来对每个 word line 进行哈希处理。

一个简短的例子是:

HASHLINE

注意:如果您不确定如何编译代码,请让我知道您使用的是哪个编译器,我很乐意提供编译字符串)

示例输入文件

#include <stdio.h>
#include <string.h>
#include <openssl/md5.h>

#define MAXC 1024   /* if you need a constant, #define one - don't skimp */

int main(int argc, char **argv) {

    char word[MAXC] = "";                       /* word/line buffer */
    unsigned char hash[MD5_DIGEST_LENGTH] = ""; /* buffer to hold hash */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin; /* file or stdin */

    if (!fp) {  /* validate file open for reading */
        perror ("file open failed");
        return 1;
    }

#ifndef HASHLINE
    while (fscanf (fp, "%s", word) == 1) {  /* read word at a time */
        const char *fmt = "%-16s : ";       /* printf (fmt, ...) for words */
#else
    while (fgets (word, MAXC, fp)) {        /* read line at a time */
        const char *fmt = "%-32s : ";       /* printf (fmt, ...) for lines */
        word[strcspn (word, "\n")] = 0;     /* remove trailing '\n' */
#endif
        size_t len = strlen (word);         /* get length of word/line */
        int index = 0,                      /* index for output hex char */
            n = MD5_DIGEST_LENGTH;          /* md5 hash length */

        MD5 ((const unsigned char *)word, len, hash);   /* compute hash */
        printf (fmt, word);                 /* output word/line */
        while (n--)
            printf ("%02x", hash[index++]); /* output hash */
        putchar ('\n');                     /* tidy up with newline */
    }

    if (fp != stdin) fclose (fp);   /* close file if not stdin */
}

使用/输出示例

散列每一行,并使用定义的$ cat dat/captnjack.txt This is a tale Of Captain Jack Sparrow A Pirate So Brave On the Seven Seas. 进行编译,例如通过将HASHLINE命令行选项传递给编译器:

-DHASHLINE

哈希每个单词(如果未定义$ ./bin/wordsmd5sslline dat/captnjack.txt This is a tale : 3495386196b8aef7d65ae857a8a5f4dc Of Captain Jack Sparrow : 225057b50358205942eafa11a35e4028 A Pirate So Brave : 3f3498d45e5f3be24ae264768dcbb4c8 On the Seven Seas. : 390ab96392602d0e78ae28b30444481f ,则为默认值):

HASHLINE

仔细检查一下,如果还有其他问题,请告诉我。