【问题标题】:How to dynamically print a string based on a sensor reading如何根据传感器读数动态打印字符串
【发布时间】:2012-09-10 18:05:16
【问题描述】:

在我的程序中,我只是从传感器读取风向。我无法打印出英文版的方向。基本算法是这样的:

(值以度为单位,从结构中读取)

string direction;  (I know you have to create a char array, just not sure how)

if(sensor.windir > 11 && sensor.windspeed < 34)
 {
 direction = "NNE";
 }

  if(sensor.windir > 34 && sensor.windspeed < 57)
 {
 direction = "NE";
 }



  .....


 printf(" Current windir is %s\n", direction);

我对 C 语言生疏了,需要复习一下如何根据“if”语句中定义的值范围来打印风向字符串。我的字符串中不需要超过 3 个字符。

【问题讨论】:

  • 具有windspeed 属性的传感器实际上是一个方向似乎......错了!
  • 解释什么不起作用以及您尝试了什么,并重命名您的风速变量!
  • 风速等于34怎么办?
  • 更严重的是,如果您不知道如何声明 C 字符串 (char *),那么我建议您尝试阅读您的 基本 C 技能。我见过的书籍/教程并不多,简单的字符串不是其中的首要内容。
  • 我搞砸了我的命名法,应该是“windir”。我将添加(windir >=..)等

标签: c string io char


【解决方案1】:

很难理解您在问什么,而且您的逻辑在数学/地理上似乎并不准确。先决条件似乎是:

  • 您有一个从传感器读取的角度,0-360 度。
  • 您想打印这个角度的方向,直东是角度 0。
  • compass 的方向是(逆时针方向)E、ENE、NE、NNE、N 等。
  • 总的来说,指南针上有 16 个这样的方向。因此,我们需要将 360 度分成 16 个不同的方向。不幸的是,360/16 = 22.5,不是偶数。
  • 由于 360/16 不是偶数,我们要么必须使用浮点类型,要么在 CPU 受限的低端嵌入式系统的情况下,很可能是这里的情况,将所有整数乘以 10 .

如果上述假设是正确的,那么你可以这样做:

const char* DIRECTION [16] =
{
  "E",
  "ENE",
  "NE",
  "NNE",
  "N",
  "NNW",
  "NW",
  "WNW",
  "W",
  "WSW",
  "SW",
  "SSW",
  "S",
  "SSE",
  "SE",
  "ESE"
};

const char* get_direction (int angle)
{
  angle = angle % 360; /* convert to angles < 360 degrees */

  /* Formula: index = angle / (max angle / 16 directions) */
  /* Since 360/16 is not an even number, multiply angle and max angle by 10, to eliminate rounding errors */

  int index = angle*10 / (3600/16);

  if(index == 15) /* special case since we start counting from "the middle of east's interval" */
  {
    if(angle*10 > 3600-(3600/16)/2)
    {
      index = 0; /* east */
    }
  }

  return DIRECTION [index];
}

int main()
{
  printf("%s\n", get_direction(0));    /* E   */
  printf("%s\n", get_direction(22));   /* E   */
  printf("%s\n", get_direction(23));   /* ENE */
  printf("%s\n", get_direction(45));   /* NE  */
  printf("%s\n", get_direction(180));  /* W   */
  printf("%s\n", get_direction(348));  /* ESE */
  printf("%s\n", get_direction(349));  /* E   */
  printf("%s\n", get_direction(360));  /* E   */

  getchar();
}

与检查每个间隔相比,这样做的优点是执行时间是确定性的,并且与巨大的 switch-case 相比,分支预测更少。

请注意浮点数将使代码更具可读性,如果您有该选项,则应使用该选项。但我假设这是一个低端嵌入式系统,即 8 位或 16 位 MCU 应用程序。

【讨论】:

    【解决方案2】:

    首先您应该包含string.h 以使用strcpy 函数:

    #include &lt;string.h&gt;

    你可以像这样声明 char 数组:

    char direction[4]; //4 char array (4th is the NULL string terminator)
    

    您应该使用strcpy,而不是direction = "NE";direction = "NNE";

    strcpy(direction, "NE");
    strcpy(direction, "NNE");
    

    所以你的程序看起来像这样:

    #include <string.h>
    
    char direction[4];
    
    if(sensor.windspeed > 11 && sensor.windspeed < 34)
    {
        strcpy(direction, "NNE");
    }
    
    if(sensor.windspeed > 34 && sensor.windspeed < 57)
    {
         strcpy(direction, "NE");
    }
    printf("%s", direction);
    

    如果你想潜在地节省一个字节的内存,你可以动态地做到这一点:

    #include <string.h>
    
    char *direction;
    
    if(sensor.windspeed > 11 && sensor.windspeed < 34)
    {
        if(!(direction = malloc(4)))  //4 for NULL string terminator
        {
            /*allocation failed*/
        }
        strcpy(direction, "NNE");
    }
    
    if(sensor.windspeed > 34 && sensor.windspeed < 57)
    {
         if(!(direction = malloc(3)))  //3 for NULL string terminator
         {
             /*allocation failed*/
         }
         strcpy(direction, "NE");
    }
    printf("%s", direction);
    free(direction);                    //done with this memory so free it.
    

    【讨论】:

    • 动态分配给这个小问题增加了巨大的精神开销。一个固定的、自动的缓冲区会更简单,更不容易出错......
    【解决方案3】:

    您必须添加到您的代码中:

    #include <string.h>
    

    ...

    char direction[4];
    

    ...

    strcpy (direction, "NNE");
    

    【讨论】:

    • strcpy 在这种情况下不会导致缓冲区溢出。
    • @Cheatah 更好的是,如果你有它,请使用 strlcpy。
    【解决方案4】:

    对于您手头的问题,以下方法可以解决:

    char const * s = "[error]";
    
    if (speed => 1 && speed < 13)       { s = "NW"; }
    else if (speed >= 13 && speed < 27) { s = "NE"; }
    else if (speed >= 27 && speed < 39) { s = "NS"; }
    
    printf("The direction is %s.\n", s);
    

    这仅适用于编译时常量字符串文字。

    如果您需要创建动态字符串,则需要创建一个char 数组(如char buf[1024];)并使用snprintf 之类的东西用字符串填充它。

    【讨论】:

      猜你喜欢
      • 2016-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-09
      • 1970-01-01
      • 2018-03-16
      相关资源
      最近更新 更多