1

組み込みデバイスで C を使用しており、現在、SD カードからファイルの詳細を読み取るコードをテストしています。私は独自の API を使用していますが、可能な限りそれを削除しようとします。

説明するのではなく、コード自体に語らせるようにします。

 char* getImage() {
  int numFiles = //number of files on SD card
  for(int i=0; i<numFiles;i++) {
    \\lists the first file name in root of SD
    char *temp = SD.ls(i, 1, NAMES);
      if(strstr(temp, ".jpg") && !strstr(temp, "_")) {
        return temp;
      }
  }
  return NULL;
}

void loop()
{
  \\list SD contents
  USB.println(SD.ls());
  const char * image = getImage();
  if(image != NULL) {
    USB.println("Found an image!");
    USB.println(image);
    int byte_start = 0;
    USB.print("Image Size: ");
    **USB.println(SD.getFileSize(image));
    USB.println(SD.getFileSize("img.jpg"));**
}

一番下の二行が面倒くさいです。リテラル文字列を渡すと、ファイル サイズが完全に取得されます。ただし、(イメージ変数で表される) 文字列を渡すと、見事な -1 が与えられます。理由はありますか?

わかりやすくするために、画像の印刷には正しいファイル名が表示されます。

編集: C で char を返し、関数に渡された変数を変更する方が良いことに眉をひそめていることを私は知っています。私もこのアプローチを使用しました。コードの例を以下に示しますが、結果は同じです。

char * image = NULL;
getSDImage(&image, sizeof(image));
void getSDImage(char ** a, int length) {
  int numFiles = SD.numFiles();
  for(int i=0; i<numFiles;i++) {
    char *temp = SD.ls(i, 1, NAMES);
      if(strstr(temp, ".jpg") && !strstr(temp, "_")) {
        *a = (char*)malloc(sizeof(char) * strlen(temp));
        strcpy(*a, temp);
      }
  }
}

編集 2: エントリへのリンクは次のとおりです: SD.lsおよびファイル サイズ関数のリンク: SD.getFileSize

戻り値が -1 (0 ではない) であり、SD のルートを一覧表示するときに結果が返されるため、戻り値から問題がファイル サイズ関数にあるようです。

ありがとう!

更新: null で終了する文字列のチェックを追加しました (これは問題だったようです)。これは getSDImage 関数で次のように対処されています。

        void getSDImage(char ** a, int length) {
      int numFiles = SD.numFiles();
      for(int i=0; i<numFiles;i++) {
        char *temp = SD.ls(i, 1, NAMES);
          if(strstr(temp, ".jpg") && !strstr(temp, "_")) {
            *a = (char*)malloc(sizeof(char) * strlen(temp));
            strncpy(*a, temp, strlen(temp)-1);
            *a[strlen(*a)-1] = '\0';
          }
      }
}

これは機能しているようで、標準出力への結果は問題ありません。サイズはエラーを示す -1 ではなく -16760 として表示されるようになりました。誰かがアイデアを持っている場合に備えて更新を投稿する必要があると思いましたが、これはファイル名の文字列に関係していると思います。

4

2 に答える 2

1

コードに問題がある可能性がいくつかあります:
1) 空白などの「見えない」文字を渡している可能性があります。渡す文字列がまったく同じであることを確認してください。つまり、ヌル終端を含めて文字ごとに出力し、それらが同じかどうかを確認してください。
2) API によって返される値と、他の API によって使用される後者の値は、期待どおりではない可能性があります。(可能であれば)API ソース コードを確認することをお勧めします。API 自体をコンパイルできる場合は、問題を簡単に見つけることができます (getFileSize() がパラメーターから取得する API を確認してください)。送信した API ドキュメントに基づいて、buffer[DOS_BUFFER_SIZE]-1 を取得した後に格納されている値を確認してください。

EDIT(APIソースコードを見た後):00657
行目(func )に: if(strcmp(dir_entry-> long_name、name)== 0) 文字列を使用するときに異なる応答が得られる唯一の理由のようです関数から名前を取得するのではなく、リテラル。そのため、同じ値を渡していない可能性が非常に高いです (つまり、目に見えない文字を渡しているか、文字列の終端がありません)。 最後の注意: SD API への各コードの前に、バッファ [DOS_BUFFER_SIZE] の内容を確認してください。find_file_in_dir


これが役立つことを願っています。

敬具、
ボー

于 2012-05-28T09:07:11.313 に答える
0

これ:

  if(strstr(temp, ".jpg") && !strstr(temp, "_")) {
    *a = (char*)malloc(sizeof(char) * strlen(temp));
    strcpy(*a, temp);
  }

が壊れているため、ターミネータ用のスペースが割り当てられておらず、バッファオーバーフローが発生しています。

次を使用する必要があります。

*a = malloc(strlen(temp) + 1);

malloc()Cでの戻り値をキャストする必要はなく、sizeof (char)常に1です。

于 2012-05-28T09:13:54.463 に答える