⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pidloop.c

📁 稀疏矩阵、链表、图、队列、二叉树、多叉树、排序、遗传算法等的实现
💻 C
📖 第 1 页 / 共 3 页
字号:
    return 1;
  }

  return 0;
}

/*********************************************************
 *
 * Function:    ParseValue
 *
 * Parameters:  const PARAM_PARSE pp, pointer to a structure
 *              containing the acceptable limits for a
 *              PID parameter value
 *
 *              const char *cp, points to a C string,
 *              array of chars terminated by '\0'
 *
 *              const double *d, pointer to a double where
 *              the value represented by the text string will
 *              be stored if it is witing range
 *
 * Returns:     zero if a successful conversion is made and
 *              stored, non zero if not
 *
 * Description: validates, converts, and stores a value
 *
 ********************************************************/
static int
ParseValue(const PARAM_PARSE *pp, const char *cp, double *d)
{
  char              *end_ptr;
  double            val;
  
  /* see if strtod() can convert to a double          */
  val = strtod(cp, &end_ptr);
  
  /* strtod() sets end_ptr to the input parameter if  */
  /* it could not perform a conversion                */
  if (end_ptr == cp)
  {
    fprintf(stderr, "error: non number entered for '%c'\n",
            pp->token);
    return 1;
  }

  /* did convert a value, check it for range          */
  if ((val < pp->min_val) || (val > pp->max_val))
  {
    fprintf(stderr, "error: %0.4f out of range for '%c'\n",
            val, pp->token);  
    return 1;
  }
  
  /* see if the value should be forced to an integer  */
  if (pp->force_to_int)
  {
    val = (long)val;
  }
  
  /* value is valid, build a pointer to store it      */
  *d = val;
  return 0;
}

/*********************************************************
 *
 * Function:    FindParseParam
 *
 * Parameters:  const char *cp, points to a C string,
 *              array of chars terminated by '\0'
 *
 * Returns:     NULL if the string does not start with the
 *              sequence of a letter followed by an equal
 *              sign, or the letter does not match one
 *              of the PARAM_PARSE structures in the array
 *
 *              if there is a match, a pointer to the
 *              matching PARAM_PARSE pointer is returned
 *
 * Description: find a match for a properly formed string
 *              which indicates a parameter to be changed
 *
 ********************************************************/
static PARAM_PARSE
*FindParseParams(const char *cp)
{
  PARAM_PARSE       *pp                     = NULL;
  int               upper;

  /* must have at least 2 chars for token and '='     */
  if (cp && strlen(cp) >= 2)
  {
    /* make all letters uppercase for comparison      */
    upper = toupper(*(unsigned char *)cp);

    /* converted copy of first character must be an   */
    /* upper case letter and the second character     */
    /* must be an equal sign                          */
    if (isupper(upper) && '=' == cp[1])
    {
      /* look for a match in the parse[] array        */
      pp = bsearch(&upper, parse,
                   sizeof parse / sizeof *parse,
                   sizeof *parse, Compare);
    }
  }
  return pp;
}

/*********************************************************
 *
 * Function:    ParseEvent
 *
 * Parameters:  const char *cp, pointing to a string
 *              beginning with the character '@'
 *
 * Returns:     zero if an event was successfully parsed and
 *              stored, non zero if not
 *
 * Description: if there is space remaining in the events
 *              array, parses the string for a pattern of
 *
 *              "@#####[optional white space]letter=#####" 
 *              
 *              where the first "#####' is convertable into
 *              an unsigned long value representing the cycle
 *              count at which the event is to take effect,
 *              and the "letter=#####" is an ordinary parameter
 *              setting, or is 'q' or 'Q' for quit
 *
 ********************************************************/
static int
ParseEvent(const char *cp)
{
  char              *end_ptr;
  PARAM_PARSE       *pp;
  EVENT             ev                      = { 0 };

  /* make sure of room to store the event             */
  if (event_index >= MAX_EVENTS)
  {
    return 1;
  }

  /* now get the time value after the '@'             */
  ev.event_time = strtoul(cp + 1, &end_ptr, 10);
  
  /* check for errors, strtoul unable to perform a    */
  /* conversion or the value is 0                     */
  if (end_ptr == cp || 0 == ev.event_time)
  {
    return 1;
  }

  /* skip any white space between time and token      */
  if (NULL == (end_ptr = SkipWhiteSpace(end_ptr)))
  {
     return 1;
  }

  /* now see if the remaining string contains a valid */
  /* parameter specifier                              */
  if (NULL == (pp = FindParseParams(end_ptr)))
  {
    /* it might still be a 'q' or 'Q' for a command   */
    /* to quit the program                            */
    if ('q' == *end_ptr || 'Q' == *end_ptr)
    {
      /* it is a quit command, fill in the token and  */
      /* store it, return successful indication       */
      ev.event_token = 'Q';
      events[event_index++] = ev;
      fputs("Stored Quit Event\n", stderr);
      return 0;
    }
    return 1;
  }

  if (ParseValue(pp, end_ptr + 2, &ev.event_value))
  {
    return 1;
  }

  /* ev.event_time and ev.event_value contain valid   */
  /* values, ev_event_token is 0, just need to fill    */
  /* in the event_dest value from the pp structure    */
  ev.event_dest = pp->destination;
  ev.event_token = toupper(*(unsigned char *)end_ptr);
  events[event_index++] = ev;
  fprintf(stderr, "Event @%lu, value %f, to %l\n",
      ev.event_time, ev.event_value, 
      (long)((double *)ev.event_dest - &params.p_gain));
  return 0;
}

/*********************************************************
 *
 * Function:    ParseImmediate
 *
 * Parameters:  const char *cp, pointing to a string
 *              beginning with a latter, to be checked
 *              for containing a valid parameter setting
 *
 * Returns:     zero if a parameter setting was successfully
 *              parsed and stored, non zero if not
 *
 * Description: test for a properly formatted parameter
 *              setting, then verifies that the value
 *              is within range, and sets the parameter
 *              if so
 *
 ********************************************************/
static int
ParseImmediate(const char *cp)
{
  PARAM_PARSE       *pp;

  /* now see if the remaining string contains a valid */
  /* parameter specifier                              */
  if (NULL == (pp = FindParseParams(cp)))
  {
      return 1;
  }

  if (ParseValue(pp, cp + 2, pp->destination))
  {
    return 1;
  }
  else
  {
    return 0;
  }
}

/*********************************************************
 *
 * Function:    ParseParams
 *
 * Parameters:  const char *cp, a command line argument
 *              assumed to be the name of a file containing
 *              immediate parameter settings and timed
 *              events
 *
 * Returns:     nothing
 *
 * Description: attempts to used the string to open a file
 *
 *              if successful, the file is read and
 *              parameter settings and timed events are
 *              parsed and stored
 *
 ********************************************************/
static void
ParseParams(const char *fname)
{
  FILE              *fin;
  char              inbuff[1000];
  int               upper;

  if (NULL == (fin = fopen(fname, "r")))
  {
    fprintf(stderr, "error: can't open %s\n", fname);
    return;
  }

  while (NULL != (fgets(inbuff, sizeof inbuff, fin)))
  {
    upper = toupper(*(unsigned char *)inbuff);
    
    /* check for an event command                         */
    if ('@' == upper)
    {
      if (ParseEvent(inbuff))
      {
        fprintf(stderr, "bad event: %s", inbuff);
      }
    }
    else if (isupper(upper))
    {
      if (ParseImmediate(inbuff))
      {
        fprintf(stderr, "bad param: %s", inbuff);
      }
    }
  } /* end of the while loop, finished reading file       */

  fclose(fin);

  /* must sort the events array into time order if any    */
  /* were entered                                         */
  if (event_index > 1)
  {
    qsort(events, event_index, sizeof *events, EventCompare);
  }

  event_index = 0;
  
  for (upper = 0; upper < event_index; ++upper)
  {
    fprintf(stderr, "%3d: time %6lu ", upper, events[upper].event_time);
    if ('Q' == events[upper].event_token)
    {
      fprintf(stderr, "Q = Quit!\n");
    }
    else
    {
      fprintf(stderr, "%c %f to %p\n", events[upper].event_token,
              events[upper].event_value,
              (void *)events[upper].event_dest);
    }
  }

  fprintf(stderr, "Set Point @ %p\n", (void *)&params.setpt);
  fprintf(stderr, "Cycles    @ %p\n", (void *)&params.cycles);
}

/*********************************************************
 *
 * Function:    CheckEvents
 *
 * Parameters:  unsigned long count, the count of cycles
 *              executed in the simulation so far
 *
 * Returns:     1 if the simulation should continue to run,
 *              0 if the program should exit
 *
 * Description: controls the process of the simulation
 *              when not running a preset number of cycles
 *
 *              on each iteration it checks for timed
 *              events ready to be processed
 *
 *              returns 0 if a 'Q' event is processed,
 *              otherwise 1 after processing all events
 *              whose time has come
 *
 ********************************************************/
static int
CheckEvents(unsigned long count)
{
  int               quit                    = 0;
  
  /* except for the very first pass, check for timed  */
  /* events ready to be executed                      */
  if (0 != count)
  {
    /* look for events with lower cycle counts not    */
    /* yet executed as well as the current count, in  */
    /* case running preset cycles passed them up      */
    while (0 != events[event_index].event_time
             && events[event_index].event_time <= count)
    {
      /* if event token is 'Q', exit the simulation   */
      if ('Q' == events[event_index].event_token)
      {
        quit = 1;
      }
      else
      {
        *events[event_index].event_dest =
              events[event_index].event_value;
      }
      ++event_index;
    }
  }
  return quit;
}

/*********************************************************
 *
 * Function:    Continue
 *
 * Parameters:  none
 *
 * Returns:     1 if the simulation should continue to run,
 *              0 if the program should exit
 *
 * Description: controls the process of the simulation
 *              when not running a preset number of cycles
 *
 *              allows parameter setting by entries of the
 *              form token=value, or just a token letter
 *              in which case it displays a prompt and
 *              accepts the value entry
 *
 *              continues until one of the following:
 *
 *              receives a 'q' or 'Q' from stdin, or sees EOF
 *              on stdin, all of which cause it to return 0
 *              to terminate the simulation
 *
 *              processes a '\n' not part of a parameter
 *              entry, causing it to return 1 to continue
 *              the simulation
 *
 *              processes a parameter setting which sets
 *              cycle count to a non-zero value, indicating
 *              that the simulation should run the new
 *              number of cycles without user input, in
 *              which case it also returns 1 to continue
 *
 ********************************************************/
static int
Continue(void)
{
  char              inbuff[100];
  int               ch;
  int               show_params;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -