charの-1以下がすべて0になってしまいます.

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Hituji
記事: 9
登録日時: 11年前

charの-1以下がすべて0になってしまいます.

#1

投稿記事 by Hituji » 10年前

こんばんは,C++を始めたばかりの者です.

今回RS485通信の受信プログラムを書いたのですが,
出力する際に―1以下の値がすべて0で扱われてしまいます.

原因がいまいち不明なのでご指導お願いします.

以下にソースコードを示します.
VC++2013を使用しています.

コード:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <windows.h>

int main(void) {

  HANDLE hComm; /*シリアルポートのハンドル*/
  int i = 0;
  char sBuf[1];
  char str[1000]; /*i=1000までの値を取得*/
  unsigned long nn;
  unsigned int len;

  DCB dcb; /*DCB:プログラム側で通信パラメータを決める*/
  COMMTIMEOUTS cto; /*cto = CommTimeOuts*/

  hComm = CreateFile("COM3", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
  if (hComm == INVALID_HANDLE_VALUE) {
    printf("Open Error!\n");
    exit(1);
  }

  GetCommState(hComm, &dcb); /*シリアルポートの状態を取得*/
  dcb.BaudRate = 38400;      /*通信速度*/
  SetCommState(hComm, &dcb); /*シリアルポートの状態を設定*/

  GetCommTimeouts(hComm, &cto);
  cto.ReadIntervalTimeout = 0;
  cto.ReadTotalTimeoutMultiplier = 0;
  cto.ReadTotalTimeoutConstant = 0;

  cto.WriteTotalTimeoutMultiplier = 0;
  cto.WriteTotalTimeoutConstant = 0;

  SetCommTimeouts(hComm, &cto);

  FILE *outputfile; /*FILEポインタ*/

  outputfile = fopen("56bit.txt", "w"); /*56bit.txtを書き込み(ファイルがなければ自動で作成)*/
  if (outputfile == NULL) { /*オープン処理&エラー対応*/
    printf("cannot open\n");
    exit(1);
  }

  while (1) {
    len = ReadFile(hComm, sBuf, 1, &nn, 0);
    if (len == 0) {
      continue;
    }

    if (len < 0) {
      printf("ERROR---\n");
      exit(2);
    }

    for (i = 0; i < len; i++) {
      str[i] = sBuf[0];
      printf("%d\n", str[i]);
      fprintf(outputfile, "%d\n", str[i]);
    }
  }

  fclose(outputfile);
  CloseHandle(hComm);

  return 0;
}

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: charの-1以下がすべて0になってしまいます.

#2

投稿記事 by みけCAT » 10年前

コードを提示するときはcolorタグを用いたシンタックスハイライトは行わず、
BBcodeを有効にした状態でcodeタグで囲み、かつ適切なインデントをしていただけると、
見やすい上、引用画面からコピペしてのテストもしやすいので助かります。
Hituji さんが書きました:

コード:

	while (1){
		len = ReadFile(hComm, sBuf, 1, &nn, 0);
		if (len == 0){
			continue;
		}

		if (len<0){
			printf( "ERROR---\n" );
			exit(2);
		}

		for (i = 0; i<len; i++){
			str[i] = sBuf[0];
			printf( "%d\n" , str[i]);
			fprintf(outputfile, "%d\n" , str[i]);
		}
	}
この部分のfor文の処理は直感に反する気がします。
(結果的に間違いとは言えませんが、無駄な処理がある気がします)
問題を切り分けるため、シリアルポートを扱う前にファイルから読み込んでテストをしてみてはいかがでしょうか?

【追記】
ReadFile 関数
戻り値

ReadFile 関数は、次のいずれかが成立すると制御を返します。パイプの書き込み側で書き込みが完了するか、指定されたバイト数の読み取りが終わるか、エラーが発生した場合です。

関数が成功すると、0 以外の値が返ります。

戻り値が 0 以外で、実際に読み取ったバイト数が 0 の場合、読み取り操作を開始する時点でファイルポインタがファイルの終わり(EOF)を超えていたことを示します。ただし、FILE_FLAG_OVERLAPPED フラグを指定してファイルを開いていた場合、lpOverlapped パラメータに NULL 以外の値を指定すると、戻り値は 0(FALSE)になります。このとき、ファイルポインタがファイルの終わりを超えていると、 関数は ERROR_HANDLE_EOF を返します。

関数が失敗すると、0 が返ります。拡張エラー情報を取得するには、 関数を使います。
変数lenに代入されているものは、読み取った長さではない可能性が高い気がします。
この謎の値を用いたforループは、やはり不自然な処理だとおもいます。
len<0の時errorとみなしているのもReadFile関数の仕様と合致しませんし、何よりlenはunsigned int型なので負にはなりません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

閉鎖

“C言語何でも質問掲示板” へ戻る