我如何 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;

我希望这个解释能让一切都清楚。