【解決方法】整数を文字列として分割する (よく説明されていませんが…)


こんにちは、みんな、
これは、この思考訓練をどのように行うかとして使用されています。
バランスセンサーから値を返すユニオンがあります。 シリアルモニターでは正常に動作しますが、LCDに表示しようとしています。いくつか調べてみると、表示する機能が示されています。

C++
lcd.print()

画面には 1 文字だけが表示されます。

私が試したこと:

ユニオンの出力を文字列に変換すると、問題は文字列がこのシステムに存在しないことです。

C++
char[]

存在するので、できますか

C++
char readOut[8];  
for(int a =0; a<=7; a++) 
  gyro.output.z = readOut[a];

問題は、配列を文字にアップロードできる個々の値に分割する方法です。[]??

私がここでどこへ行こうとしているのか、おわかりでしょう…
私はバランス センサーを使用して、「プレス」が水平かどうか (床の傾斜ではない) を正確に報告しようとしているので、マギンズにはそれを証明するタスクが与えられました…バランス センサーは (accel_t_gyro.value.z_gyro) を返します。これは次のものから作られた結合です:

C
typedef union accel_t_gyro_union
{
struct {
uint8_t x_accel_h;
uint8_t x_accel_l;
uint8_t y_accel_h;
uint8_t y_accel_l;
uint8_t z_accel_h;
uint8_t z_accel_l;
uint8_t t_h;
uint8_t t_l;
uint8_t x_gyro_h;
uint8_t x_gyro_l;
uint8_t y_gyro_h;
uint8_t y_gyro_l;
uint8_t z_gyro_h;
uint8_t z_gyro_l;
} reg;

struct {
int16_t x_accel;
int16_t y_accel;
int16_t z_accel;
int16_t temperature;
int16_t x_gyro;
int16_t y_gyro;
int16_t z_gyro;
} value;
};

したがって、たとえば 4988 という 4 桁の数字が得られます。 大丈夫。 私が使用しているLCDは一度に1文字しか表示しません。たとえば、「4988」を送信すると「4」が返されるので、intをcharに変換するかどうかを考えていました。[] 配列 for() を使用して位置をカウントし、そこから出力できます

C
for(int a = 0; a <= 7; a++) {
  // char[a] to int[a] type thing
}
lcd.print(a);

解決策 1

C では、char[] 実質的には文字列です。末尾に null 値 ‘\0’ を追加すると、実用的な目的で文字列になります。これらは「null で終了する文字列」と呼ばれます。

文字列に出力するには、次のように割り当てる必要があります。 readOut[a] そこから読み取るのではなく、値を文字に分割します。これは難しいことではありませんが、入力が実際に格納されている内容によって異なります。

Google で「C 整数を文字列に変換」および「C 整数を 16 進文字列に変換」を検索してアイデアを探してください。

解決策 2

提示されたデータ タイプに従って、センサーは結果を 16 ビット整数の 2 進数として保存します。 最初のステップは、z_gyro の最大値と最小値を調べることです。 符号付き4桁の値となった場合、文字列に変換するには最低6文字必要となります。 バッファ readOut が 8 バイトで宣言されている場合、出力に文字列長を使用しても問題はありません。
最初に整数値を文字列に変換することをお勧めします。 C コマンド sprintf() を使用できる場合は、これは簡単です。

C
sprintf(readOut, "%d", sensor.value.z_gyro);

次に、for ループを使用して、文字列の末尾にあるすべての文字を個別に print() 関数に渡します。

C
for (int i = 0; i < strlen(readOut); i++)
    lcd.print(readOut[i]);

sprintf() 関数が使用できない場合でも、itoa() を使用することは可能です。または、ループ内で変換を自分でプログラムすることもできます。

追加情報として、「sprintf、実際にはすべての f 関数 (print、scan) が存在しません。」 単純な汎用関数を自分で書くことも可能です。 次のようになります。

C
void intToCString(int num, char* str) {
    if (num < 0) {
        *str++ = '-';
        num = -num;
    }

    int divisor = 1;
    while (num / divisor > 9) {
        divisor *= 10;
    }

    while (divisor > 0) {
        *str++ = '0' + (num / divisor);
        num %= divisor;
        divisor /= 10;
    }

    *str = '\0';
}

解決策 3

itoa がない場合は sprintf() を使用することもできますが、これはこのような軽いタスクにとっては非常に重いです。 以下はうまくいくはずです

C
int magnitude(int x)
{
    int i;
    x = abs(x);
    for(i = 0; x > 0; x /= 10, ++i);
    return i;
}

char *i2cstr(int i, char *buff) 
{
    int n = magnitude(i);

    /*  The following is only needed if i may be negative */ 
    int last = 0;
    if(i < 0) {
        i *= -1;
        buff[0] = '-';
        n += 1;
        last = 1;
    }
    /* end of dealing with negative numbers */
    
    buff[n] = 0;
    for(--n; n >= last; --n ) {
        buff[n] = i%10 + '0';
        i/= 10;
    }
    return buff;
}

注意: パラメータ buff i2cstr() のサイズは適切に設定する必要があります。 uint16_t の場合、終端の null を含めて 6 文字になります。

解決策 4

値を出力するだけの場合は、最初に文字列に変換する必要はありません。

C
void putaschar(int16_t n)
{
    if( n == 0 ) {
        /* special case for n == 0 */
        putchar('0');
    } else {
        if(n < 0) {
            /* oputput sign, and make n +ve */
            putchar('-');
            n *= -1;
        }

        /* determine largest power of 10 smaller than n */
        int16_t divisor = 10000;  /* maximum power of 10 that will fit in int16 */
 
        while( n / divisor == 0) {
            divisor /= 10;
        }

        /* send chars to the output device */
        do {
            putchar(n/divisor + '0');
            n %= divisor;
            divisor /= 10;
        } while(divisor > 0);
    }
}

上記では、次のように仮定します putchar() ディスプレイに文字を送信するために必要なあらゆる魔法の代わりになります。

コメント

タイトルとURLをコピーしました