我如何 return 来自 C/C++ 函数的多个可选变量?
How do I return several optional variables from a function in C/C++?
我正在用 SIM7000 4G 调制解调器对 ESP32 进行编程,调制解调器库有一个函数,可以从调制解调器获取包含 21 个变量的 CSV 字符串,并将其部分解析为变量。原作者只关心一小部分变量,所以传递了指针。
如果我想修改代码以使所有变量可用,传递 21 个指针似乎很笨拙,尤其是当我可能只关心其中几个变量时一次。这是结构的情况吗?使数据可用的最用户友好的方式是什么?
该函数将 AT command 发送到带有 GPS 芯片的蜂窝调制解调器 (SIM7000)。收到命令后,芯片会在内部解析来自 GPS 的 NEMA 数据以及包含所有相关数据的 returns 和 CSV 字符串。
//FUNCTION FROM LIBRARY
// get GPS information
bool getGPS(float *lat, float *lon, float *speed=0, float *alt=0, float *course=0, int *vsat=0, int *usat=0) {
//String buffer = "";
bool fix = false;
sendAT(GF("+CGNSINF"));
if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 1) {
return false;
}
stream.readStringUntil(','); // mode [GNSS off=0, GNSS on=1]
if ( stream.readStringUntil(',').toInt() == 1 ) fix = true;
stream.readStringUntil(','); //utctime yyyyMMddhhmmss.sss
*lat = stream.readStringUntil(',').toFloat(); //lat ±dd.dddddd
*lon = stream.readStringUntil(',').toFloat(); //lon ±ddd.dddddd
if (alt != NULL) *alt = stream.readStringUntil(',').toFloat(); //altitude metere
if (speed != NULL) *speed = stream.readStringUntil(',').toFloat(); //speed Km/hour [0,999.99]
if (course != NULL) *course = stream.readStringUntil(',').toFloat(); //course over ground degrees [0,360.00]
stream.readStringUntil(',');//Fix mode [0,1,2]
stream.readStringUntil(',');//Reserved1
stream.readStringUntil(',');//HDOP [0,99.9]
stream.readStringUntil(',');//PDOP [0,99.9]
stream.readStringUntil(',');//VDOP [0,99.9]
stream.readStringUntil(',');//Reserved2
if (vsat != NULL) *vsat = stream.readStringUntil(',').toInt(); //viewed satelites
if (usat != NULL) *usat = stream.readStringUntil(',').toInt(); //used satelites
stream.readStringUntil(',');//GLONASS Sats used
stream.readStringUntil(',');//Reserved3
stream.readStringUntil(',');//C/N0 max (dBHz 0-55)
stream.readStringUntil(',');//HPA (meters [0,9999.9])
stream.readStringUntil(',');//VPA (meters [0,9999.9])
stream.readStringUntil('\n');
waitResponse();
return fix;
}
//CALL FROM CODE
gps_fixstatus = modem.getGPS(&gps_latitude, &gps_longitude, &gps_speed, &gps_altitude, &gps_course, &gps_view_satellites, &gps_used_satellites);
if ( gps_fixstatus ) {
gps_altitude=gps_altitude*3.2808;
sprintf(payload, "{\"lat\":%8f,\"long\":%8f,\"speed\":%2f,\"head\":%2f,\"alt\":%2f}", gps_latitude,gps_longitude, gps_speed, gps_course, gps_altitude); //JSON-ify
SerialMon.println(payload); //JSON object
}
完整代码:Library-see line 771 / Code calling library-line 134
我分叉图书馆也有它 return GPS 课程信息,我想为什么不让所有 returned 数据可用,但必须通过 21 似乎对用户不友好指针或定义一个 21 成员结构并传递它,如果他们的主要代码只关心 lat/lon 甚至只关心速度。
我喜欢并与独立 gps 接收器一起使用的一个库是 TinyGPS++。它 return 将数据作为对象的一部分,例如Serial.print(TinyGPSplus.location.lat())
。这是最好的方法吗?我一直在通过 Arduino 将不同的示例混合在一起来学习 C/C++。
是的。这是结构的一个很好的例子(c/c++ 结构的关键字)。
"结构 — 有时称为聚合 — 是同一个名称下的相关变量的集合。结构可能包含许多不同数据类型的变量 — 与仅包含相同数据元素的数组相反type." - C 如何编程 6.Ed 作者:Paul 和 Harvey Deitel。
在您的情况下,您必须 return 大约 21 个不同的变量,对吗?所以使用结构来创建自定义数据类型可以说 gpsData 其成员是您想要 return 的 21 个变量将使您能够使用 [=37= 编写 returns 数据的函数] 以紧凑的方式。当然,您必须将 gsm 模块中的每个 derived/parsed 数据项分配给 "gpsData".
的每个成员
参考你的代码:
bool getGPS(float *lat, float *lon, float *speed=0, float *alt=0, float *course=0, int *vsat=0, int *usat=0) {
//String buffer = "";
bool fix = false;
sendAT(GF("+CGNSINF"));
if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 1) {
return false;
}
stream.readStringUntil(','); // mode [GNSS off=0, GNSS on=1]
if ( stream.readStringUntil(',').toInt() == 1 ) fix = true;
stream.readStringUntil(','); //utctime yyyyMMddhhmmss.sss
*lat = stream.readStringUntil(',').toFloat(); //lat ±dd.dddddd
*lon = stream.readStringUntil(',').toFloat(); //lon ±ddd.dddddd
if (alt != NULL) *alt = stream.readStringUntil(',').toFloat(); //altitude metere
if (speed != NULL) *speed = stream.readStringUntil(',').toFloat(); //speed Km/hour [0,999.99]
if (course != NULL) *course = stream.readStringUntil(',').toFloat(); //course over ground degrees [0,360.00]
stream.readStringUntil(',');//Fix mode [0,1,2]
stream.readStringUntil(',');//Reserved1
stream.readStringUntil(',');//HDOP [0,99.9]
stream.readStringUntil(',');//PDOP [0,99.9]
stream.readStringUntil(',');//VDOP [0,99.9]
stream.readStringUntil(',');//Reserved2
if (vsat != NULL) *vsat = stream.readStringUntil(',').toInt(); //viewed satelites
if (usat != NULL) *usat = stream.readStringUntil(',').toInt(); //used satelites
stream.readStringUntil(',');//GLONASS Sats used
stream.readStringUntil(',');//Reserved3
stream.readStringUntil(',');//C/N0 max (dBHz 0-55)
stream.readStringUntil(',');//HPA (meters [0,9999.9])
stream.readStringUntil(',');//VPA (meters [0,9999.9])
stream.readStringUntil('\n');
waitResponse();
return fix;
}
这些变量:float *lat, float *lon, float *speed=0, float *alt=0, float *course=0, int *vsat=0, int *usat=0 可以放在一个结构如下:
struct gpsData{
bool fix;
float lat;
float lon;
float speed;
float alt;
float course;
int vsat;
int usat;
....x_datatype y_variable;
};
其中x_datatype y_variable指的是您可能要添加的其他成员变量。
您的 getGPS 函数现在将变成这样:
gpsData getGPS(){
gsmData temp;
temp.fix = false;
// required processing...
// ...
return temp;
}
调用getGPS()时,如下例:
gpsData parsed_gps_data = getGPS();
您现在可以像这样获取您感兴趣的parameters/members/attributes:
parsed_gps_data.fix;
parsed_gps_data.lat;
parsed_gps_data.lon;
我希望这个解释能让一切都清楚。
我正在用 SIM7000 4G 调制解调器对 ESP32 进行编程,调制解调器库有一个函数,可以从调制解调器获取包含 21 个变量的 CSV 字符串,并将其部分解析为变量。原作者只关心一小部分变量,所以传递了指针。
如果我想修改代码以使所有变量可用,传递 21 个指针似乎很笨拙,尤其是当我可能只关心其中几个变量时一次。这是结构的情况吗?使数据可用的最用户友好的方式是什么?
该函数将 AT command 发送到带有 GPS 芯片的蜂窝调制解调器 (SIM7000)。收到命令后,芯片会在内部解析来自 GPS 的 NEMA 数据以及包含所有相关数据的 returns 和 CSV 字符串。
//FUNCTION FROM LIBRARY
// get GPS information
bool getGPS(float *lat, float *lon, float *speed=0, float *alt=0, float *course=0, int *vsat=0, int *usat=0) {
//String buffer = "";
bool fix = false;
sendAT(GF("+CGNSINF"));
if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 1) {
return false;
}
stream.readStringUntil(','); // mode [GNSS off=0, GNSS on=1]
if ( stream.readStringUntil(',').toInt() == 1 ) fix = true;
stream.readStringUntil(','); //utctime yyyyMMddhhmmss.sss
*lat = stream.readStringUntil(',').toFloat(); //lat ±dd.dddddd
*lon = stream.readStringUntil(',').toFloat(); //lon ±ddd.dddddd
if (alt != NULL) *alt = stream.readStringUntil(',').toFloat(); //altitude metere
if (speed != NULL) *speed = stream.readStringUntil(',').toFloat(); //speed Km/hour [0,999.99]
if (course != NULL) *course = stream.readStringUntil(',').toFloat(); //course over ground degrees [0,360.00]
stream.readStringUntil(',');//Fix mode [0,1,2]
stream.readStringUntil(',');//Reserved1
stream.readStringUntil(',');//HDOP [0,99.9]
stream.readStringUntil(',');//PDOP [0,99.9]
stream.readStringUntil(',');//VDOP [0,99.9]
stream.readStringUntil(',');//Reserved2
if (vsat != NULL) *vsat = stream.readStringUntil(',').toInt(); //viewed satelites
if (usat != NULL) *usat = stream.readStringUntil(',').toInt(); //used satelites
stream.readStringUntil(',');//GLONASS Sats used
stream.readStringUntil(',');//Reserved3
stream.readStringUntil(',');//C/N0 max (dBHz 0-55)
stream.readStringUntil(',');//HPA (meters [0,9999.9])
stream.readStringUntil(',');//VPA (meters [0,9999.9])
stream.readStringUntil('\n');
waitResponse();
return fix;
}
//CALL FROM CODE
gps_fixstatus = modem.getGPS(&gps_latitude, &gps_longitude, &gps_speed, &gps_altitude, &gps_course, &gps_view_satellites, &gps_used_satellites);
if ( gps_fixstatus ) {
gps_altitude=gps_altitude*3.2808;
sprintf(payload, "{\"lat\":%8f,\"long\":%8f,\"speed\":%2f,\"head\":%2f,\"alt\":%2f}", gps_latitude,gps_longitude, gps_speed, gps_course, gps_altitude); //JSON-ify
SerialMon.println(payload); //JSON object
}
完整代码:Library-see line 771 / Code calling library-line 134
我分叉图书馆也有它 return GPS 课程信息,我想为什么不让所有 returned 数据可用,但必须通过 21 似乎对用户不友好指针或定义一个 21 成员结构并传递它,如果他们的主要代码只关心 lat/lon 甚至只关心速度。
我喜欢并与独立 gps 接收器一起使用的一个库是 TinyGPS++。它 return 将数据作为对象的一部分,例如Serial.print(TinyGPSplus.location.lat())
。这是最好的方法吗?我一直在通过 Arduino 将不同的示例混合在一起来学习 C/C++。
是的。这是结构的一个很好的例子(c/c++ 结构的关键字)。
"结构 — 有时称为聚合 — 是同一个名称下的相关变量的集合。结构可能包含许多不同数据类型的变量 — 与仅包含相同数据元素的数组相反type." - C 如何编程 6.Ed 作者:Paul 和 Harvey Deitel。
在您的情况下,您必须 return 大约 21 个不同的变量,对吗?所以使用结构来创建自定义数据类型可以说 gpsData 其成员是您想要 return 的 21 个变量将使您能够使用 [=37= 编写 returns 数据的函数] 以紧凑的方式。当然,您必须将 gsm 模块中的每个 derived/parsed 数据项分配给 "gpsData".
的每个成员参考你的代码:
bool getGPS(float *lat, float *lon, float *speed=0, float *alt=0, float *course=0, int *vsat=0, int *usat=0) {
//String buffer = "";
bool fix = false;
sendAT(GF("+CGNSINF"));
if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 1) {
return false;
}
stream.readStringUntil(','); // mode [GNSS off=0, GNSS on=1]
if ( stream.readStringUntil(',').toInt() == 1 ) fix = true;
stream.readStringUntil(','); //utctime yyyyMMddhhmmss.sss
*lat = stream.readStringUntil(',').toFloat(); //lat ±dd.dddddd
*lon = stream.readStringUntil(',').toFloat(); //lon ±ddd.dddddd
if (alt != NULL) *alt = stream.readStringUntil(',').toFloat(); //altitude metere
if (speed != NULL) *speed = stream.readStringUntil(',').toFloat(); //speed Km/hour [0,999.99]
if (course != NULL) *course = stream.readStringUntil(',').toFloat(); //course over ground degrees [0,360.00]
stream.readStringUntil(',');//Fix mode [0,1,2]
stream.readStringUntil(',');//Reserved1
stream.readStringUntil(',');//HDOP [0,99.9]
stream.readStringUntil(',');//PDOP [0,99.9]
stream.readStringUntil(',');//VDOP [0,99.9]
stream.readStringUntil(',');//Reserved2
if (vsat != NULL) *vsat = stream.readStringUntil(',').toInt(); //viewed satelites
if (usat != NULL) *usat = stream.readStringUntil(',').toInt(); //used satelites
stream.readStringUntil(',');//GLONASS Sats used
stream.readStringUntil(',');//Reserved3
stream.readStringUntil(',');//C/N0 max (dBHz 0-55)
stream.readStringUntil(',');//HPA (meters [0,9999.9])
stream.readStringUntil(',');//VPA (meters [0,9999.9])
stream.readStringUntil('\n');
waitResponse();
return fix;
}
这些变量:float *lat, float *lon, float *speed=0, float *alt=0, float *course=0, int *vsat=0, int *usat=0 可以放在一个结构如下:
struct gpsData{
bool fix;
float lat;
float lon;
float speed;
float alt;
float course;
int vsat;
int usat;
....x_datatype y_variable;
};
其中x_datatype y_variable指的是您可能要添加的其他成员变量。
您的 getGPS 函数现在将变成这样:
gpsData getGPS(){
gsmData temp;
temp.fix = false;
// required processing...
// ...
return temp;
}
调用getGPS()时,如下例:
gpsData parsed_gps_data = getGPS();
您现在可以像这样获取您感兴趣的parameters/members/attributes:
parsed_gps_data.fix;
parsed_gps_data.lat;
parsed_gps_data.lon;
我希望这个解释能让一切都清楚。