如何从txt文件正确读取位串以计算汉明距离b / w所有字符串组合

时间:2018-12-24 02:19:07

标签: c fgets

我的目标是能够迭代从文本文件读取的所有位串,以便我可以计算所有字符串组合之间的汉明距离。例如,我有一个txt文件,其中包含500个位串,每个位串的长度为5093。我想从文件中读取字符串s1和s2,然后计算它们之间的汉明距离。本质上,我试图遍历文件中的字符串以计算所有500 * 499/2 = 124,750个组合的HD,以便可以计算均值,std dev并绘制直方图。通过使用readlines()读取字符串并将它们存储在列表中,我能够在python中做到这一点。然后,使用for循环迭代所有(s1)字符串,然后使用嵌套的for循环将它们与从列表中读取的(s2)字符串进行比较。现在,我正在重新解决这个问题以重新使用我的C语言。我当前的方法包括以类似的方式遍历文件,并使用对fgets()的两次调用读取位串,然后剥离回车符。我遇到的问题是,当我尝试调用第二个fgets()以获取s2时,位串的末尾被缩短了约300个字符,并且我计算了汉明距离499次,而不是预期的127450次距离计算。当我使用fgets()一次并注释掉嵌套的while循环时,我能够读取完整的位串。如果您能帮助我理解实施过程中的问题以及实现目标的正确方法,将不胜感激。谢谢!

编辑:初始化变量,并重置i和hd以进行HD计算。提供了包含位串的txt文件的类似示例。在此示例中,有4个长度为16的位串,而不是500个长度为5093的位串。在这种情况下,目标是计算所有6个位串对组合的HD。

样本txt文件

0011010000111010
1001001001110100
1110110010000100
0111011011111001

代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define SIZE 6000
#define CHIPS 500

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

    FILE* fp;

    char buffer[SIZE];
    char s1[SIZE];
    char s2[SIZE];
    int i = 0, j = 0, hd = 0;

    if(argc != 2) {
        fprintf(stderr, "USAGE: ./<executable> <bitstring file>\n");
        return 1;
    }
    else if ((fp = fopen(argv[1], "r")) == NULL) {
        perror("ERROR: File not found.\n");
        return 1;
    }
/*    for(i = 0; i < CHIPS; i++) {
        fgets(s1,sizeof(s1),fp);
        s1[strlen(s1) - 1] = '\0';
        printf("%s\n", s1);
        printf("%d\n", i);
        for(j = 0; j < CHIPS; j++) {
            fgets(s2, sizeof(s2),fp);
            s2[strlen(s2) - 1] = '\0';
            printf("%s\n", s2);
            printf("%d", j);
        }

    }
    fclose(fp);
*/
    while(fgets(s1,sizeof(s1), fp) != NULL) {
        //memcpy(s1,buffer, sizeof(s1));
        s1[strlen(s1) - 1] = '\0';
        printf("%s\n", s1);

        while(fgets(s2, sizeof(s2), fp) != NULL) {
            s2[strlen(s2) - 1] = '\0';

            while(s1[i] != '\0') {
                if(s1[i] != s2[i])
                    hd++;
                i++;
            }
            printf("Hamming Distance: %d\n", hd);
            i = 0;
            hd = 0;
        }

    }
    fclose(fp);

    return 0;
}

示例输出

...
Hamming Distance: 2576

1 个答案:

答案 0 :(得分:0)

OP已经(根据注释)理解了现在初始化变量的错误。

要循环思考N*(N-1)/2次,一种简单的方法可以记住当前s1行末尾的文件偏移量。以后的代码将寻求每个循环。

更强大的代码将全部读入内部存储器-但以下是一种快速编码的选择。

与许多代码开发一样,首先要专注于正确使用功能,然后提高性能。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define SIZE 6000
#define CHIPS 500

int main(void) {
  FILE* fp;
  char s1[SIZE];
  char s2[SIZE];

  fp = fopen("junk.txt", "w");
  if (fp == NULL) {
    perror("ERROR: File.\n");
    return 1;
  }
  fprintf(fp, "%s\n","0011010000111010");
  fprintf(fp, "%s\n","1001001001110100");
  fprintf(fp, "%s\n","1110110010000100");
  fprintf(fp, "%s\n","0111011011111001");
  fclose(fp);

  FILE *fp1 = fopen("junk.txt", "r");
  if (fp1 == NULL) {
    perror("ERROR: File not found.\n");
    return 1;
  }

  long offset = 0;
  for (;;) {
    fseek(fp1, offset, SEEK_SET);
    if (fgets(s1, sizeof(s1), fp1) == NULL) break;
    s1[strcspn(s1, "\n")] = 0;
    offset = ftell(fp1);  // record location
    if (offset == -1) break;

    while (fgets(s2, sizeof(s2), fp1) != NULL) {
      s2[strcspn(s2, "\n")] = 0;
      size_t i = 0;
      size_t hd = 0;
      while (s1[i] >= '0' && s1[i] <= '1') {
        if (s1[i] != s2[i]) {
          hd++;
        }
        i++;
      }
      printf("s1 <%s> " "s2 <%s> " "Hamming Distance: %zu\n", s1 ,s2, hd);
    }

  }
  fclose(fp);
  puts("Done");
  return 0;
}

输出:每个4 * 3/2预期6个汉明码

s1 <0011010000111010> s2 <1001001001110100> Hamming Distance: 8
s1 <0011010000111010> s2 <1110110010000100> Hamming Distance: 10
s1 <0011010000111010> s2 <0111011011111001> Hamming Distance: 6
s1 <1001001001110100> s2 <1110110010000100> Hamming Distance: 10
s1 <1001001001110100> s2 <0111011011111001> Hamming Distance: 8
s1 <1110110010000100> s2 <0111011011111001> Hamming Distance: 10
Done