
GPS受信機で出力されるデータのチェックサムをC言語で算出しようと思いましたが、
下記のように$から*の文字間($*は含めず、数字とコンマ、ドット、英字)の排他的論理和を計算して、16進の2桁で表示したいのですが、printf("%x",moji[0]^moji[1]^moji[2]);などとやっていては非効率的すぎなので、for文などでループさせるのがいいのかなと思いましたが、
char a = 0x00;
for(int x = 0; x <= (sizeof moji/sizeof(char))-1 ){
a =moji[x]^moji[x+1];
}
とした場合、計算させたい配列が来た場合にエラーになってしまいます。(趣味程度の知識ので)
簡単な解決策をアドバイスいただけますでしょうか。
よろしくお願いします。
下記、char moji[]={""};に入っている文字;。*の次の2文字が送られてくるチェックサムです。
文字数は変化します。
$GNRMC,235037.000,A,1233.1234,N,12345.6543,E,101.110,858.31,300419,,,D*4F
No.2ベストアンサー
- 回答日時:
いろいろと突っ込み所があります。
> 計算させたい配列が来た場合にエラーになってしまいます
具体的に、どんなタイミングで、どんなエラーになるのですか?
例えば
for(int x = 0; x <= (sizeof moji/sizeof(char))-1 ){
は文法的に間違っているので、コンパイル時にエラーになります。
もし、書き写したときに間違えた、ということなら、「書き写す」のではなく「コピーして貼り付け」てください。
○ char moji[]={""};
は
char moji[1]={'\0'};
の省略形と解釈されます。
これだと、配列mojiは1要素しか確保されていません。
「文字列」として扱う場合には 「0文字の文字列」 しか格納できません。
正確に言うと、C言語の場合、確保した配列の範囲を越えて格納(代入)させようとすることはできます。
ただし、そのときに正しく格納できる保証はありません。
この moji に $GNR〜 を格納しようとすれば、確実に配列mojiの範囲を越えるので、当然、正しく格納できる保証はありません。
場合によっては、動作時にエラーになります。
/* 何食わぬ顔でそのまま実行が続くこともあります */
○ a =moji[x]^moji[x+1];
xはforループで、 0から配列mojiの要素数-1,つまり、 mojiの最初の添字から最後の添字までをループします(おそらく)
x=最後の添字
のときに
x+1 = 最後の添字の「次」
になります。
ここでも、配列範囲外のアクセスが発生しています。
○ a =moji[x]^moji[x+1];
この記述だと
前回までの計算結果を破棄して、新しくmoji[x]^moji[x+1]の結果をa に代入する
という意味になります。
学習時に「配列内の数値の合計を求める」というようなプログラムをやったはずです。
それの応用になります。
○ sizeof moji/sizeof(char)
sizeof moji は moji の大きさを求めます。
これは 「mojiが示している文字列の大きさ」では **ありません**
char txt[512] = "text" ;
なら、
sizeof txt = 512
txtの文字列長 = 4
です。
/*
また、sizeof moji が配列の大きさを表わしているとは限りません。
void checksum(char moji[] ) {
〜 sizeof moji 〜
}
とした場合等、範列ではなくポインタになっていることがあります。
*/
学習時に「strlen関数を自作する」というような問題なかったですか?
それの応用になります。
○「$から*の文字間」とありますが、提示された中にそのような判定を行っている様子がありません。
mojiに格納されているのが1行全てなら、このforの中でxorするかどうかを判定する必要があります。
mojiに格納されているのが「$から*の文字間」なら判定は不要です。
/* 「$から*」を格納する方法が間違っている可能性もありますが */
ご回答有り難うございます。
補足させていただきます。
C言語は全くの独学ですので学校では一切習っておりませんVB程度でです。
エラーは、アクセス違反です。
本来の機器はPICマイコンですので、焼く前のテストとしてVC++ 2017にてテストしています。
GPSデータの受信はRS-232Cで受信しPIC依存の読み込み処理RCREGで読み込みます。
バッファを128バイト用意しましたので、全文字バッファに読み込みます。
よろしくお願いします。
-----下記、ソースコピーペ-----
char a[] = { "$GNRMC,235037.000,A,1233.1234,N,12345.6543,E,101.110,858.31,300419,,,D*7B" };
char hairtu_count = 0;
char b = 0x00;
char c = 0x00;
char len = 0;
len = strlen(a);
hairtu_count = sizeof(a) / sizeof(char);
printf("%lu\n\n", hairtu_count); // 配列の要素数
for (int x = 0; x <= hairtu_count - 1; x++) {
b = a[x] ^ a[x+1];
c = 1 ^ 0 ^ 1 ^ 0 ^ 1;
}
printf("0x%x\n", b); // 0x00と出力
printf("0x%x\n", c); // 0x01と出力
}
No.1
- 回答日時:
まず
a =moji[x]^moji[x+1];
では計算できません。
a =a^moji[x];
ですね。
moji[x+1] では配列の範囲を超えてしまいますね。
for分に増分がありませんから永久ループになるのでは。
sizeof moji/sizeof(char)意味があるのか無いのか
mojiの定義がありません。
ポインタで定義されていればサイズは不明ですね。
sizeof(char)が1以外であれば結果が16進2桁にはなりませんね。
この場合上位を捨てるのか、下位を捨てるのか、上位^下位にするのかなど定義やコンパイラ、計算系で違ってくるでしょう。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Java Javaの問題なのですが、「3文字以上の英数字文字列を入力し、文字列の中に文字(9)が出てくるまでの 1 2023/06/06 18:55
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- Visual Basic(VBA) VBA シート上にドロップダウンリストを作り、予め指定値をセットしたいのですが 1 2023/03/25 15:15
- SQL Server [SQLServer] テーブル名からカラム名を取得する 1 2022/08/23 21:20
- C言語・C++・C# str[j++]の意味 2 2022/08/30 16:20
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# プログラミングの問題です。至急教えてください。 /***から***/の部分をプログラミングにしてほし 1 2022/10/13 11:48
- C言語・C++・C# 【C言語】全角文字の配列を、全角のまま1文字ずつ出力する方法 4 2023/05/09 15:08
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語 配列の長さの上限
-
先頭アドレスとは何ですか?
-
リスト構造について
-
【速いブラインドタッチ】手を...
-
テキストファイルから文字列を...
-
複数の選択範囲の行番号を個別...
-
メモリの初期値
-
VBで構造体の配列を関数に渡す...
-
Redimした動的配列はEraseする...
-
VBAでクラス設定
-
配列を使わずに、変数名を動的...
-
配列を含む構造体の初期値について
-
配列をEraseしてもメモリが開放...
-
defineを使った配列
-
C言語でcharの足し算
-
配列で格納したものをmsgboxで...
-
ポインタの配列のコンマについて
-
char型の配列 char buff[20] = ...
-
電子書籍を見るためにはどうし...
-
【C言語】配列の中に配列を入れ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語 配列の長さの上限
-
配列を使わずに、変数名を動的...
-
C# Listを使わずに2次元配列の...
-
【速いブラインドタッチ】手を...
-
配列をEraseしてもメモリが開放...
-
テキストファイルから文字列を...
-
先頭アドレスとは何ですか?
-
配列で格納したものをmsgboxで...
-
複数の選択範囲の行番号を個別...
-
C# 配列の変数宣言について。
-
C++ vectorに配列をプッシュしたい
-
配列を含む構造体の初期値について
-
VBで構造体の配列を関数に渡す...
-
C言語で特定列だけを抽出して配...
-
キーボードのキー配列について
-
ExcelVBAで質問です。離れた二...
-
2次元配列を戻り値とする関数?
-
unsigned char配列への入力の仕方
-
【C言語】配列の中に配列を入れ...
-
Redimした動的配列はEraseする...
おすすめ情報
すいません自己解決しました。
ありがとうございます。
忘備録としてソースを載せます。
int main(){
char a[] = { "$GNRMC,235037.000,A,1233.1234,N,12345.6543,E,101.110,858.31,300419,,,D*4F"};
char b = 0x00;
char len = 0;
len = strlen(a)-4;
for (int x = 1; x <= len; x++) {
b = b ^ a[x];
}
printf("0x%x\n", b);