hytrao 发表于 2014-8-15 18:47:43

arduino对TXT文件的二分查找

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

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

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


#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 != 'J' || str != 'C' || str != 'D' )
      {
      str = "";
      }
//    Serial.printf("str = %c, str = %c, str = %c\n",str,str,str);
      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 > str2) return 1;
    if(str1 < str2) return -1;
}
return 0;
}


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

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

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



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

zoologist 发表于 2014-8-15 19:23:17

会不会是因为内存占用太多导致的啊?

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

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

缺陷是:灵活度差,不能废除某些卡

Lance 发表于 2014-8-15 19:59:51

Serial.printf("Seccess low = ld, high = %ld\n", curLocation-12, curLocation );
这句难道没有语法错误? 但至少应该偏离你的本意了

hytrao 发表于 2014-8-16 10:09:32

Lance 发表于 2014-8-15 19:59 static/image/common/back.gif
Serial.printf("Seccess low = ld, high = %ld\n", curLocation-12, curLocation );
这句难道没有语法错误 ...

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

hytrao 发表于 2014-8-16 10:12:33

Lance 发表于 2014-8-15 19:59 static/image/common/back.gif
Serial.printf("Seccess low = ld, high = %ld\n", curLocation-12, curLocation );
这句难道没有语法错误 ...

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

hytrao 发表于 2014-8-16 10:13:52

zoologist 发表于 2014-8-15 19:23 static/image/common/back.gif
会不会是因为内存占用太多导致的啊?

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


想过,但不敢肯定啊而且这个工具没法调试啊

zoologist 发表于 2014-8-17 12:28:59

hytrao 发表于 2014-8-16 10:13 static/image/common/back.gif
想过,但不敢肯定啊而且这个工具没法调试啊

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

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

Lance 发表于 2014-8-17 13:03:57

hytrao 发表于 2014-8-16 10:09 static/image/common/back.gif
没有错误啊,他只是一个输出格式,而后面的变量是我的每个字符串是10

我意思是少了个%.
Seccess low = ld -> Seccess low = %ld

hytrao 发表于 2014-8-17 21:46:11

Lance 发表于 2014-8-17 13:03 static/image/common/back.gif
我意思是少了个%.
Seccess low = ld -> Seccess low = %ld

这个程序中肯定改了,关键问题不是这个啊,看主要问题。

hytrao 发表于 2014-8-17 21:46:28

zoologist 发表于 2014-8-17 12:28 static/image/common/back.gif
这个应该没问题,哪怕计算checksum也是一种校验了

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

还没,周末有事
页: [1]
查看完整版本: arduino对TXT文件的二分查找