极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 18549|回复: 9

arduino对TXT文件的二分查找

[复制链接]
发表于 2014-8-15 18:47:43 | 显示全部楼层 |阅读模式
身份菜鸟,最近一直在再用arduino做Rfid的门禁控制,过程中我做了一个卡号验证,我把卡号存放到SD卡中的一个CHECK.TXT文件中,当刷卡时,遍历这个文件查找卡号,但是由于这个文件中存放数据过多的话,会造成板子反应很长时间,所以就想对txt的查找进行优化,所以才有了下面的代码。txt中的数据是已经排好序有一定格式的。我把读卡的部分摘了出来,遇到的问题是这样的。

上图中,遍历的时候明明已经遍历到了,而且符合判断,为什么就没有执行下面代码呢

if( index == 0)
      {
        Serial.printf("Seccess low = ld, high = %ld\n", curLocation-12, curLocation );
        return true;
      }

[pre lang="arduino" line="1" file="BtSearch"]
#include<SD.h>
const int chip = 4;
long SIZE = 0;

File myfile;

void setup()
{
  Serial.begin(9600);
  if(!SD.begin(chip))
  {
    Serial.println("SD init failed");
    return;
  }
  Serial.println("SD done");
  
}

void loop()
{
  long mm = 0;
  long pos = 0;
  char kk = '\0';
  String ss = "";
  while(Serial.available()>0)
  {
    ss += char(Serial.read());
  }
  if(ss.length() > 0)
  {
    myfile = SD.open("CHECK4.TXT");
    if(myfile)
    {
      SIZE = myfile.size();
      Serial.printf("size = %ld\n", SIZE);
    }
    else
    {
      Serial.println("SD error");
      return;
    }
    String strCard ="JCDJ000001";
    if(cmpCard(0,SIZE,strCard))
    {
      Serial.println("Seccess!!");
      myfile.close();
    }
    else
    {
      Serial.println("failed!!");
    }
    ss = "";
  }
  
  
  
}

String GetCard(long pLocation, long& NewLocation)
{
  String str = "";
  char ch = '\0';
  myfile.seek(pLocation);
  while(myfile.available())
  {
    ch = myfile.read();
    if(ch == '\n')
    {
      str.trim();
      if(str[0] != 'J' || str[1] != 'C' || str[2] != 'D' )
      {
        str = "";
      }
  //    Serial.printf("str[0] = %c, str[1] = %c, str[2] = %c\n",str[0],str[1],str[2]);
      if(!str.equals(""))
      {
        NewLocation = myfile.position();
        str.trim();
        Serial.println(str);
        return str;
      }
    }
    else
    {
      if(ch != ' ' || ch != '  ')
      {
        str += ch;
      }
    }
  }
}

bool cmpCard(long low, long high, String strCard)
{
  long mid = 0;
  long curLocation = 0;
  int index = 0;
  String strGet = "";
  if(low < high)
  {
    if(high-low < 40)
    {
      strGet = GetCard(low, curLocation);
/*     index = strGet.compareTo(strCard);
      if( index == 0)
      {
        Serial.printf("Seccess low = ld, high = %ld\n", curLocation-12, curLocation );
        return true;
      }
      else
      {
        return cmpCard(curLocation, high, strCard);
      }
    */
    }
    else
    {
      mid = (low+high)/2;
      strGet = GetCard(mid, curLocation);
    }
    delay(20);
    index = (int)strGet.compareTo(strCard);
//   index = compare(strGet, strCard);             ------------------------------换成这个判断的话又会出现如下图错误
    Serial.print(strGet);
    Serial.print("-----");
    Serial.print(strCard);
    Serial.print("-----");
    Serial.println(index);
   
    if( 0 == index)
    {
      Serial.printf("Seccess low = ld, high = %ld\n", curLocation-12, curLocation );
      return true;
    }
    else if(index < 0)
    {
      Serial.printf("small low = %ld, high = %ld\n", curLocation, high );
      return cmpCard(curLocation, high, strCard);
    }
    else if(index > 0)
    {
      
      Serial.printf("big low = %ld, high = %ld\n",low, curLocation);
      return cmpCard(low, curLocation, strCard);
    }
  }
  return false;
}

int compare(String str1, String str2)
{
  int length = 10;
  for(int j=0; j<length; j++)
  {
    if(str1[j] > str2[j]) return 1;
    if(str1[j] < str2[j]) return -1;
  }
  return 0;
}
[/code]

我开始以为是判断的问题,所以在别处自己写了一个简单的判断,去比较字符串的大小但是会出现如下问题:

//   index = compare(strGet, strCard);             ------------------------------换成这个判断的话又会出现如下图错误

代码跟SD卡里的txt都在附件里



这个算法写的还有问题,一些卡号遍历的时候会遍历不到,但是好像不会影响到我问的这些问题。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

发表于 2014-8-15 19:23:17 | 显示全部楼层
会不会是因为内存占用太多导致的啊?

另外,还有一个思路是:校验卡号,就是你按照一定算法生成卡号

然后收到卡号之后只要简单的运算就能判断卡号是否合法而不必到txt中去查找,当然这样的方法

缺陷是:灵活度差,不能废除某些卡
回复 支持 反对

使用道具 举报

发表于 2014-8-15 19:59:51 | 显示全部楼层
Serial.printf("Seccess low = ld, high = %ld\n", curLocation-12, curLocation );
这句难道没有语法错误? 但至少应该偏离你的本意了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-8-16 10:09:32 | 显示全部楼层
Lance 发表于 2014-8-15 19:59
Serial.printf("Seccess low = ld, high = %ld\n", curLocation-12, curLocation );
这句难道没有语法错误 ...

没有错误啊,他只是一个输出格式,而后面的变量是我的每个字符串是10
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-8-16 10:12:33 | 显示全部楼层
Lance 发表于 2014-8-15 19:59
Serial.printf("Seccess low = ld, high = %ld\n", curLocation-12, curLocation );
这句难道没有语法错误 ...

想过,这个原因,但是没有相应的判断使用资源的ide,我也无法肯定
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-8-16 10:13:52 | 显示全部楼层
zoologist 发表于 2014-8-15 19:23
会不会是因为内存占用太多导致的啊?

另外,还有一个思路是:校验卡号,就是你按照一定算法生成卡号

想过,但不敢肯定啊而且这个工具没法调试啊
回复 支持 反对

使用道具 举报

发表于 2014-8-17 12:28:59 | 显示全部楼层
hytrao 发表于 2014-8-16 10:13
想过,但不敢肯定啊而且这个工具没法调试啊

这个应该没问题,哪怕计算checksum也是一种校验了

另外,你的问题搞定了么?

回复 支持 反对

使用道具 举报

发表于 2014-8-17 13:03:57 | 显示全部楼层
hytrao 发表于 2014-8-16 10:09
没有错误啊,他只是一个输出格式,而后面的变量是我的每个字符串是10


我意思是少了个%.
Seccess low = ld -> Seccess low = %ld
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-8-17 21:46:11 | 显示全部楼层
Lance 发表于 2014-8-17 13:03
我意思是少了个%.
Seccess low = ld -> Seccess low = %ld

这个程序中肯定改了,关键问题不是这个啊,看主要问题。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-8-17 21:46:28 | 显示全部楼层
zoologist 发表于 2014-8-17 12:28
这个应该没问题,哪怕计算checksum也是一种校验了

另外,你的问题搞定了么?

还没,周末有事
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-8 04:18 , Processed in 0.048632 second(s), 20 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表