Arduino 數(shù)據(jù)類型轉(zhuǎn)換

使用過Python的數(shù)據(jù)類型后,會(huì)發(fā)現(xiàn)C/C++的數(shù)據(jù)類型比較單一。Arduino實(shí)際上是C++,除了基礎(chǔ)數(shù)據(jù)類型,增加了String類。通過了解標(biāo)準(zhǔn)庫和類的頭文件,可以減少不必要的、重復(fù)的、瑣碎的、易錯(cuò)的手工代碼。除了Arduino,其他的GCC和嵌入式C語言中也可以參照?qǐng)?zhí)行。

IoT相關(guān)數(shù)據(jù)類型

  • byte, unsigned char
  • char
  • int, int and unsigned int
  • float
  • String,class of char array
  • struct

IoT需要解決的主要是采集、傳輸、判斷、控制。傳輸通道上數(shù)據(jù)以二進(jìn)制數(shù)據(jù)為主。

C語言設(shè)計(jì)中,二進(jìn)制數(shù)據(jù)采用unsigned char[],使用簡單。二進(jìn)制處理采用struct結(jié)構(gòu)體可以很好地解決固定長度的unsigned char[]。但是動(dòng)態(tài)長度的傳輸協(xié)議的結(jié)構(gòu)體往往需要包含額外的緩沖區(qū)指針。

C語言中,字符串采用char[],即字符數(shù)組來實(shí)現(xiàn)。但是無論是初始化、轉(zhuǎn)換、處理起來,代碼都很瑣碎。所以ANSI標(biāo)準(zhǔn)的C語言標(biāo)準(zhǔn)庫中提供了大量的面向字符以及字符串的函數(shù)。在Java/C++等OOP語言中,也都定義String類。注意,這些是類(class),而非數(shù)據(jù)類型(type)。

由于IoT引入了許多Web協(xié)議,而大多數(shù)Web協(xié)議如HTTP/FTP/Telnet都基于字符串。所以許多情況下,代碼需要在這兩種協(xié)議之間進(jìn)行轉(zhuǎn)換。所以u(píng)nsigned char和char是最基礎(chǔ)的數(shù)據(jù)類型。

unsigned char和char可以通過強(qiáng)制類型轉(zhuǎn)換來實(shí)現(xiàn)。但是unsigned char[],char[],String三者之間卻有著一定的差異,主要因?yàn)閏har[]/String定義的字符串結(jié)束符必須使用NULL,即\0來實(shí)現(xiàn)。在某些特殊情況下會(huì)因?yàn)閮煞N數(shù)據(jù)類型長度不一致,或者缺乏NULL結(jié)束符導(dǎo)致程序跑飛。

String類

在Arduino的WString.h/WString.cpp中可以找到對(duì)應(yīng)的String類定義。

inline void String::init(void) {
    buffer = NULL;
    capacity = 0;
    len = 0;
}

WString.cpp引用了stdlib_noiso.h這個(gè)頭文件,也就是底層依然調(diào)用了libc來實(shí)現(xiàn)一些功能。在構(gòu)建函數(shù)中,可以看到其調(diào)用utoa(),itoa(),ltoa()等stdlib.h中定義的函數(shù)。

類型轉(zhuǎn)換

雖然C語言是理工科大學(xué)必修課程,但是在MCU級(jí)別使用C語言卻是在工作中。從Keil的C51語言開始,因?yàn)橘Y源受限,實(shí)際工程中很少使用標(biāo)準(zhǔn)庫,一些小的常用函數(shù)都是自己寫的,目的是通過不同模塊的緩沖區(qū)復(fù)用(overlap)實(shí)現(xiàn)少占用RAM空間。而現(xiàn)在STM32/ESP8266的RAM都比之前8051 256B要多許多,使用標(biāo)準(zhǔn)庫和類庫以實(shí)現(xiàn)標(biāo)準(zhǔn)化開發(fā),可以明顯加快開發(fā)。

當(dāng)然,不必將所有的庫和類庫都背下來,可以在使用中摸索出操作的常用函數(shù),然后在標(biāo)準(zhǔn)庫和類庫中去尋找對(duì)應(yīng)物。

  • String to char array
  • String to byte array
  • String to int
  • String to float

各種庫

不同C編譯器環(huán)境有著類似(ANSI C libc)但是有細(xì)微差異的庫(glibc)。需要自行檢索。

  • stdlib.h,libc的一部分,包含了部分str轉(zhuǎn)其他類型的函數(shù)定義。
  • ctypes.h, libc的一部分,包含了字符char的函數(shù)定義。
  • string.h, libc的一部分,包含了大多數(shù)字符串操縱如復(fù)制、檢索、比較等函數(shù)定義。
  • Wstring.h,Arduino自定義的String類,依賴于stdlib.h/string.h的函數(shù)。
  • Wcharater.h,Arduino定義的字符類型操作,如判斷、轉(zhuǎn)換。依賴于ctype.h的轉(zhuǎn)換函數(shù)。
#include <stdlib.h>

// string to double or float
double atof(const char *s);
float atoff(const char *s);

// string to integer
int atoi(const char *s);    // = (int)strtol(s, NULL, 10);
long atol(const char *s);   // = strtol(s, NULL, 10);

// double or float to string
char *ecvt(double val, int chars, int *decpt, int *sgn);
char *ecvtf(float val, int chars, int *decpt, int *sgn);
char *fcvt(double val, int decimals, int *decpt, int *sgn);
char *fcvtf(float val, int decimals, int *decpt, int *sgn);

// format double or float as string
char *gcvt(double val, int precision, char* buf);
char *gcvtf(float val, int precision, char* buf);

// double or float to string
char *ecvtbuf(double val, int chars, int *decpt, int *sgn, char *buf);
char *ecvtfbuf(float val, int chars, int *decpt, int *sgn, char *buf);

// integer or unsigned int to string
char *itoa(int value, char *str, int base);
char *utoa(unsigned value, char *str, int base);

// string to double or float
double strtod(const char *restrict str, char **restrict tail);
float strtof(const char *restrict str, char **restrict tail);

// string to long or unsigned long
long strtol(const char *restrict s, char **restrict ptr, int base);
unsigned long strtoul(const char *restrict s, char **restrict ptr, int base);

// binary search
void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *));

#include <ctype.h>

int isalnum(int c); // is alphanumberic
int isalpha(int c); // is alphabetic
int isascii(int c); // is ASCII char
int isblank(int c); // 
int iscntrl(int c);
int isdigit(int c);
int islower(int c);
int isprint(int c); // is printable
int ispunct(int c); // punctuation
int isspace(int c); // is space
int isupper(int c);
int isxdigit(int c); // is hexdecimal digit
int toascii(int c); // force to ascii, by clearing MSB
int tolower(int c);
int toupper(int c);

#include <string.h>

int bcmp(const void *s1, const void *s2, size_t n); // = memcmp
int bcopy(const void *in, void *out, size_t n); // = memmove
void bzero(void *b, size_t length);
char *index(const char *string, int c);    // = strchr
void *memccpy(void *restrict out, const void *restrict in, int endchar, size_t n);
void *memchr(const void *src, int c, size_t length);
int memcmp(const void *s1, const void *s2, size_t n);
void *memcpy(void *restrict out, const void *restrict in, size_t n);
char *memmem(const void *s1, size_t l1, const void *s2, size_t l2);
void *memmove(void *dst, void *src, size_t length);
void *memrchr(const void *src, int c, size_t length);
void *memset(void *dst, int c, size_t length);
void *rawmemchr(const void *src, int c);
void *rindex(const char * string, int c);
char *strpcpy(char *restrict dst, const char *restrict src);
char *strncpy(char *restrict dst, const char *restrict src, size_t length);
int strcasecmp(const char *a, const char *b);
char *strcasestr(const char *s, const char *find);
char *strcat(char *restrict dst, const char *restrict src);
char *strchr(const char *string, int c);
char *strchrnul(const char *string, int c);
int strcmp(const char *a, const char *b);
char *strcpy(char *dst, char *src);
size_t strlen(const char *str);
char *strlwr(char *a);
int strncasecmp(const char *a, const char *b, size_t length);
char *strncat(char *restrict dst, const char *restrict src, size_t length);
int strncmp(const char *a, const char *b, size_t length);
char *strncpy(char *restrict dst, const char *restrict src, size_t length);
size_t strlen(const char *str, size_t length);
char *strpbrk(const char *s1, const char *s1);
char *strrchr(const char *string, int c);
char *strstr(const char *s1, const char *s2);
char *strtok(char *restrict source, const char *restrict delimiters);

仔細(xì)閱讀Arduino的WString/WCharater的頭文件,其底層依然是依賴于標(biāo)準(zhǔn)庫libc。

其他操作

Python編寫IoT應(yīng)用時(shí),有些特殊的操作,是沒有C語言對(duì)應(yīng)物的,都需要自己去編寫。比如split()切割字符串等。

Web URLs

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • mean to add the formatted="false" attribute?.[ 46% 47325/...
    ProZoom閱讀 2,719評(píng)論 0 3
  • 國家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說閱讀 11,082評(píng)論 6 13
  • Lua 5.1 參考手冊(cè) by Roberto Ierusalimschy, Luiz Henrique de F...
    蘇黎九歌閱讀 13,877評(píng)論 0 38
  • 人類社會(huì)大部分東西,都是具有邏輯性的,要學(xué)會(huì)經(jīng)常去思考背后的邏輯。這樣做的一個(gè)好處便是,記憶會(huì)變得比較簡單。比如公...
    中南偏南閱讀 429評(píng)論 0 0
  • 我想象那是詩經(jīng)中的第一個(gè)女人 在水的彼岸徜徉 可知道孤獨(dú)也會(huì)消瘦 寂寞也能燃燒 在幽暗的光纖隧道 看作遠(yuǎn)景多么朦朧...
    微風(fēng)LG閱讀 212評(píng)論 0 0