配列、添え字に関するコンパイルエラーについて

このQ&Aのポイント
  • arduinoで赤外線リモコンを作成しており、赤外線のON/OFFパターンの配列データを扱っています。
  • 配列の添え字(インデックス)のデータ型に関するエラーが発生し、解決策を求めています。
  • 添え字のデータ型を変えてもエラーが解消されず、どのように対処すればよいかわかりません。
回答を見る
  • ベストアンサー

配列、添え字に関するコンパイルエラーにつきまして。

現在、arduinoで赤外線リモコンを作成しております。 ネット上の情報を参考にON/OFFのみの送信・受信はできたので、ボタンの数(mode)を21種類に増やして送信機を作成を試みております。 赤外線のON/OFFパターンの配列データが大きかったのでdata[][67]としてPROGMEM に保管し、SRAMにondata[67]として読み込もうとしています。 この状態でコンパイルすると下記のようなエラーが出てしまいます。 [mode][i][cnt]を配列のインデックス(添え字)として使っていますが、これを使用している行にこのエラーが出ます。 調べてみると添え字はintではいけないといった情報もみかけますが、data[i]のように使用されているのをよく見かけます。 データ型を変えてみたり試してみたのですが、'char[int]' や'int[char]'のように変わるだけで解決しませんでした。 このエラーに対して何か解決策があればご教授願えないでしょうか。 よろしくお願い致します。 ※エラー invalid types 'int[int]' for array subscript ※グローバル変数(PROGMEM に保存) const uint16_t data[21][67] PROGMEM = { /* 4bytes(16bits), Leader code & Customer code(CC) & Data code & ^Data code & Mode code */ /* data[0] */ {9200, 4500, 600, 1650, 600, 1650, 600, 550, 600, 550, 600, 1650, 600, 1650, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 1650, 600, 1650, 600, 1650, 600, 1650, 600, 1650, 600, 1650, 600, 1650, 600, 1650, 600, 550, 600, 1650, 600, 550, 600, 1650, 600, 550, 600, 1650, 600, 550, 600, 1650, 600}, /* data[1] */ {9200, 4500, 600, 1650, 600, 1650, 600, 550, 600, 550, 600, 1650, 600, 1650, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 1650, 600, 1650, 600, 1650, 600, 1650, 600, 1650, 600, 1650, 600, 1650, 600, 1650, 600, 550, 600, 550, 600, 1650, 600, 550, 600, 1650, 600, 550, 600, 1650, 600, 550, 600, 1650, 600},           ・           ・           ・ /* data[20] */ {9200, 4500, 600, 1650, 600, 1650, 600, 550, 600, 550, 600, 1650, 600, 1650, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 1650, 600, 550, 600, 1650, 600, 1650, 600, 1650, 600, 1650, 600, 1650, 600, 1650, 600, 550, 600, 1650, 600, 550, 600, 1650, 600, 550, 600, 1650, 600, 550, 600, 1650, 600, 550, 600, 1650, 600}, }; ※関数 void sendOnSignal(int mode){ int ondata[67]; for (int i = 0; i < 67; i++) {ondata[i] = pgm_read_word_near(&(data[mode][i]));} int dataSize = sizeof(ondata[mode]) / sizeof(ondata[mode][0]); /* IRcodeの配列数を計算。67になるはず。 */ for(int cnt = 0; cnt < 67; cnt++) /* iIndexIRcode(現在の配列)が偶数番目ならhigh。 奇数番目ならlow。 */ { unsigned long len = ondata[mode][cnt]; /* lenに現在の配列の時間を代入。 */ unsigned long us = micros(); /* usにパルス開始時刻を記録。 */ do { /* 周波数38kHzでOn/Offするように配列の時間分点滅。 */ digitalWrite(IRLED_pin, (cnt%2) ? LOW : HIGH); /* 三項演算子[A ? B : C] (Aがtrueの場合はB,falseの場合はCを実行する) */ delayMicroseconds(8); /* キャリア周波数38kHzでON/OFFするよう時間調整 */ digitalWrite(IRLED_pin, LOW); delayMicroseconds(7); } while (long(us + len - micros()) > 0); /* 送信時間に達するまでループ */ } } /* void sendSignal終了*/

質問者が選んだベストアンサー

  • ベストアンサー
  • wormhole
  • ベストアンサー率28% (1621/5657)
回答No.1

>int ondata[67]; ... >unsigned long len = ondata[mode][cnt]; /* lenに現在の配列の時間を代入。 */ ではないでしょうか。

gallus
質問者

お礼

ありがとうございます! PROGMEMに保存している data[mode][]と、SRAMに準備したondata[cnt]の2つが名前が似ていたのでondataに[mode]つけたりと混同していました。 しっかり分けることで解決しました! (はっきりと区別できる名前にすべきでした。) 下記に修正後のスケッチを記載しておきます。 こんな短時間で解決策を提示していただいてありがとうございました。 int ondata[67]; for (int i = 0; i < 67; i++) {ondata[i] = pgm_read_word_near(&(data[mode][i]));} int dataSize = sizeof(ondata) / sizeof(ondata[0]); for(int cnt = 0; cnt < 67; cnt++) { unsigned long len = ondata[cnt];

関連するQ&A

  • 配列の和を求めるプログラム

    キーから入力したデータを配列に入力した後、その和を求めるプログラムを作成したいのですが、プログラミング初心者の私にはさっぱりわかりません。 和を求めたいのに平均値が出てきてしまいます。 どこが間違っているのか教えてください。 #include <stdio.h> float data[5]; float total(int max); void main(void) { int cnt = 0; float d; printf("please input a data: "); scanf("%f", &d); while((cnt < 5) && (d > 0.0)) { data[cnt] = d; cnt++; printf("please input a data: "); scanf("%f", &d); } printf("total data: %5.2f\n", total(cnt)); } float total(int max) { int i; float total = 0.0; for(i = 0; i < max; i++) { total += data[i]; } return total / max; }

  • 配列の配列?

    80字より長い行を全て印字するというプログラムを作ろうと思います。 それで今現在下記の状態なんですが #include <stdio.h> #define MAXLINE 1000 int getline(char line[], int maxline); void copy(char s1[], char s2[]); int main(int argc, char* argv[]) { int len; int max; char line[MAXLINE]; char longest[MAXLINE]; max = 0; while((len = getline(line, MAXLINE))> 0){ if(len > 80){ max = len; copy(longest, line); } } if(max > 0){ printf("%s", longest); } return 0; } int getline(char s[], int lim) { int c, i; for(i = 0; i < lim -1 && (c = getchar()) != EOF && c != '\n'; ++i){ s[i] = c; } if(c == '\n'){ s[i] = c; ++i; } s[i] = '\0'; return i; } void copy(char s1[], char s2[]) { int i; i=0; while((s1[i] = s2[i]) != '\0'){ ++i; } } この状態だと80字以上の行を1行しか表示しません。 おそらくは配列の配列を使って保存しておくのだとは考えたのですが 使い方がわかりません。教えて下さい。

  • 配列の中に複数存在する数がいくつあるか

    お世話になります。配列の中に同じ数が存在する数がいくつあるかを調べたいのですが、途中でつまづいてしまいました。 例えば配列arrayの中に、0, 0, 5, 0, 5, 1, 5といった数が格納されているとしたら 複数ある数は0と5の2つなので、2を返す、というだけのプログラムです。 int n=array.length; int cnt=0; for(int i=0;i<n;i++){ for(int j=i+1;j<n;j++){ if(array[i]==array[j]){ cnt++; break; } } } return cnt; forループで配列0から同じ数を順番に調べ、もしヒットすればカウントを増やして内側のループをブレイクし、配列1からまた順番に調べようとしたのですが、 上の例の場合、配列0と配列1が同じ数(0)ですので、カウントが余計に増えてしまいます。 どのように組めばうまく動作するでしょうか。宜しくお願いします。

    • ベストアンサー
    • Java
  • 配列

    String型の配列の中の文字列の文字数を数える方法で困っています。 問題は、int型の変数lenで与えられた数字よりも大きい文字数の文字列はいくつあるか調べます。 例) stringsLongerThan({"a","ab","abc"}, 0) 3つ全ての文字列の文字数は0より大きいので3を返す stringsLongerThan({"a","ab","abc"}, 2) "abc"の文字数が2より大きいので1を返す stringsLongerThan({"a","ab","abc","abcd","abcde","abcdef","abcdefg"}, 3) "abcd","abcde","abcdef","abcdefg"の4つが文字数3より大きいので4を返す 途中まで組んだのですが、配列array[]の中の文字列の文字数を数えるにはどうしたらよいのでしょうか? public int stringsLongerthan(String[] array, int len){       int result=0;      for(int i=0;i<array.length;i++){        //ここで配列array[i]の文字列の文字数を数える       int count=文字数;       if(cont>len)        result++;     }      return result; } 宜しくお願いします。

    • ベストアンサー
    • Java
  • ARDUINOで5つのLEDをそれぞれ点滅させたり、フェードインさせた

    ARDUINOで5つのLEDをそれぞれ点滅させたり、フェードインさせたりしたい!! ARDUINO初心者です。5つのLEDをそれぞれ上記の様に制御したいと思っています。点滅は点灯、消灯が一定の点滅ではない効果を持たせたく、5つのLEDのうち、2つはフェードインフェードアウトで蛍のような効果にしたいと思っております。 以下、途中まで3つのLEDで試行錯誤してスケッチを構築したのですが、なかなかこれ以上、前へすすみません。 まず、このスケッチでの第一関門はプログラムの並列処理ができない、ということでした。 int ledPina = 9; int ledPinb = 10; int ledPinc = 11; void setup(){ pinMode(ledPina, OUTPUT); pinMode(ledPinb, OUTPUT); pinMode(ledPinc, OUTPUT); //LedPin a b cを出力に設定。 } void loop() { digitalWrite(ledPina, HIGH); // aのLEDをオン delay(500); //待機 digitalWrite(ledPina, LOW); //aをオフ delay(500); digitalWrite(ledPinb, HIGH); // bのLEDをオン delay(800); // 待機 digitalWrite(ledPinb, LOW); //bをオフ delay(300); digitalWrite(ledPinc, HIGH); // cのLEDをオン delay(100); // 待機 digitalWrite(ledPinc, LOW); //cをオフ delay(50); } おわかりの方、いらっしゃいましたら、お教え願えますでしょうか? よろしくお願い致します!!

  • 下記のプログラムがコンパイラでエラーになります。

    いつも教えて頂きありがとうございます。 実は基本を理解しておらず、キーパンチの練習になっています。 もう1冊自分にも解る書籍を購入しようと思います。 このプログラムの誤りだけでも教えて頂きたいのです。 2000文字では足りないので、2回に分けて投稿させて頂きます。 下記のプログラムです。 /***************************************************** 基本交換法による並べ替えを行うプログラム ******************************************************/ #include <stdio.h> #define N 7 /*データ個数*/ #define ON 1 /*sw : 交換しました*/ #define OFF 0 /*sw : 交換していません*/ #define DATA_LEN 20 /*データ配列の1列の要素数*/ /*関数のプロトタイプ宣言*/ void printData(char p[][DATA_LEN], int n); /*文字列を表示する関数*/ void sort(char p[][DATA_LEN], int n); /*文字列を並び替える関数*/ void str_change(char *ps1,char *ps2); /*文字列と文字列とを交換する関数*/ void atr_cpy(char *pd,char *ps) /*文字列を複写する関数*/ int str_cmp(char *ps1,char *ps2) /*文字列と文字列とを比較する関数*/ main() { /*データの宣言*/ char p_data[N][DATA_LEN] = {"ふじさわ","えのしま","しちりがはま", "ごくらくじ","はせ","ゆいがはま","かまくら"}; /*最初の状態を表示*/ printData(p_data,N); /*並べ替え*/ sort(p_data,N); /*結果を表示*/ printf("¥nソ¥ートしました¥n¥n"); printData(p_data,N); } /**************************************************** ポインタ型から文字列を表示 ****************************************************/ void printData(char p[][DATA_LEN], int n) /* p : 二次元配列*/ /* n : 文字列の要素数*/ { int i; /*添え字*/ for(i=0;i<n;i++) { printf("%s¥n",p[i]); } } /***************************************************** 基本交換法 *****************************************************/ void sort(char p[][DATA_LEN],int n) /* p : 二次元配列*/ /* n : 文字列の要素数*/ { int sw; /*交換したか*/ int i,j; /*添え字*/ sw = ON; for(i = n-1 ; i>=1 && sw == ON ; i--) { sw = OFF; for(j = 0; j< i ;j++) { /* p[j] <= p[j+1]となるようにする*/ if(str_cmp(p[j],p[j+1]) > 0) { str_change(p[j],p[j+1]; /*交換*/ sw = ON; } } } } もう1回投稿致します。

  • 配列長参照のオーバーヘッド

    for等ループでループ終了条件に配列長を使用する場合、配列長を毎回参照する場合と一旦変数に格納して参照する場合、定数を使用する場合と処理速度の差はありますか? つまり 1、for( int i = 0; i < array.length; i++ ) { ... } 2、for( int i = 0; i < len; i++ ) { ... } *(int len=array.length) 3、for( int i = 0; i < 10; i++ ) { ... } *(int[] array = new int[10]) forループ内の処理のメモリ使用量の多寡は不明で、毎ループで読み取られる全ての変数はコンピュータのキャッシュに残るかどうかは不明だとします。

    • ベストアンサー
    • Java
  • 配列生成される限り、ループしたい

    function arrayxml (){ urlで取得したXMLから、配列を取得 return $hairetu; //戻り値は多次元配列 } $data = arrayxml(); $cnt = count($data); do { for ($i=0; $i < $cnt; $i++) { $data = arrayxml($data[$i][0]); } } while (count($data) > 0); //関数によって配列が作られる限り このスクリプトではループはうまくされません。 $data = arrayxml($data[$i][0]);を--->arrayxml($data[$i][0]);にすると $cnt分ループされますが、do~whileのループはなされません。 関数で配列が生成される限り、do~whileループをさせたいのですが正しい方法を教えていただけないでしょうか。 よろしくお願いします。

    • ベストアンサー
    • PHP
  • 添字範囲エラー送出とデストラクタについて

    添字範囲エラー送出とデストラクタについて 下記のように(1)SiZE=5,(2)num=6 を投入した場合、添字演算子[]関数で(3)添字範囲エラー送出(size=5,I=5)の時、 IdxRngErr例外を発生し、(4)デストラクタを呼んでcatch((5)catch (IntArray::IdxRngErr&)で捕捉される。 質問 IdxRngErr例外を発生により、デストラクタを呼ばれる理由を教えて頂きたい。 *********************************************************************************** main() { int size, num; cout << "要素数:"; cin >> size;   (1) 5を投入 cout << "データ数:"; cin >> num; 、 (2) 6を投入 f(size, num); return 0; }/ *************************************************************************************** //===== 整数配列クラス ======// class IntArray { int size; // 配列の要素数 int* vec; // 先頭要素へのポインタ ~IntArray() { delete[] vec; } // (4)デストラクタよりIdxRngErrがcatch(5)される。 int& operator[](int i) { // 添字演算子[] if (i < 0 || i >= size) throw IdxRngErr(this, i); (3)// 添字範囲エラー送出(size=5,I=5)の時, return vec[i]; } ******************************************************************************************* / //--- 要素数sizeの配列にnum個のデータを代入して表示 --// void f(int size, int num) { try { IntArray x(size); for (int i = 0; i < num; i++) { x[i] = i; cout << "x[" << i << "] = " << x[i] << '\n'; } }    (5)catch (IntArray::IdxRngErr& x) { cout << "添字オーバフロー:" << x.Index() << '\n'; return; i

  • AOJの問題で、質問があります。

    AOJの問題で考えても全然わからない問題があり、他の人の解答例を参考にしようと思い、見てみたのですが、一つ分からないところがあり、質問させていただきます。 問題です。 http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0089 自分が参考にしている解答例です。 http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=570672 以下は分かっていないところを書かせていただきます。 なお、コードは解答例と同じです。 include <stdio.h> #include <string.h> int max(int a,int b){ return (a > b) ? a : b; } /*上の数、i-1行目の数から、i行目の大きい数をとっていく関数だと思いましたが、じっくり考えてみると、何パターンかのdataの足し算をしていることに気づきました。まずは左端のみ足す場(data[i+1][0] += data[i][0];)、次に右端だけを足す場合( data[i+1][i+1] += data[i][i];) 、そして for(j = 1;j <= i;j++){ data[i+1][j] += max(data[i][j-1],data[i][j]); } という、端以外の数から足すものです。ここで分からないことは ・このdata[i+1][j] += max(data[i][j-1],data[i][j]);という解答はi+1行目から、i行目の大きな数を選んでいますが、i行目からi+1行目の隣の大きいほうの数を足すようにしないと、ただしい経路は求まらないと思うのですが、どうでしょうか?また、端のみを足しているdataは、どういう役割をしているのでしょうか? 試しに端だけを足す式を削除したら、間違いとなってしまいます。また、この関数はreturn などがないですが、どの値が残るのでしょうか?main関数内では、どのような役割をするのでしょうか?*/ void solve(int data[100][50],int cnt){ int i,j; for(i = 0;i < cnt/2;i++){ data[i+1][0] += data[i][0]; for(j = 1;j <= i;j++){ data[i+1][j] += max(data[i][j-1],data[i][j]); } data[i+1][i+1] += data[i][i]; } for(i = cnt/2+1;i < cnt;i++){ for(j = 0;j < cnt-i;j++){ data[i][j] += max(data[i-1][j],data[i-1][j+1]); } } } int main(){ int h,i,j,cnt,len,num; int data[100][50]; char str[1024]; memset(data,0,sizeof(data)); i = 0; cnt = 0; while(scanf("%s",str) != EOF){ h = 0; j = 0; len = strlen(str); while(h <= len){ if(h < len && str[h] != ','){ num = 0; while(h < len && str[h] != ','){ num *= 10; num += str[h]-'0'; h++; } data[i][j] = num; j++; } h++; } i++; cnt++; } solve(data,cnt);//ここでは、計算した結果、どのような値が帰ってくるのでしょうか? printf("%d\n",data[cnt-1][0]); return 0; } 長文失礼しました。 よろしくお願いします。