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

📄 formatfp1.c

📁 从iccavr7中破解得到的lib库源代码
💻 C
字号:
/* FormatFP_1.c        09/09/2002       to develop Imagecraft formatting function 
                       09/12/2002
                       09/13/2002
                       09/14/2002
                       09/15/2002
                       09/28/2002
                       09/29/2002
                       10/25/2002
                       10/28/2002
                       10/29/2002
                       10/30/2002
                       11/01/2002
                       11/09/2002
                       11/10/2002



  by Tom Digby for Imagecraft

*/




// debug in Windows 32 environment, use in Imagecraft environment
#ifdef _WIN32

#include "stdlib_ForWin32.h"


#endif
#ifdef __IMAGECRAFT__
#include <stdlib.h>
#include <string.h>
#endif

#include "_stdio.h"
#include "formatfp1.h"

// maximum size of exponent:  "e", minus sign, two digits, null, guard
#define MAX_EXP_WIDTH 6

static char *FtoaError(char *buf, int code)
	{
    static FLASH char err0[] = { "ftoa error: number too big" };
    static FLASH char err1[] = { "ftoa error: number too small" };
    static FLASH char err2[] = { "ftoa error: unexpected error" };
	FLASH char *cs;
	
	if (code == _FTOA_TOO_LARGE)
		cs = err0;
	else if (code == _FTOA_TOO_SMALL)
		cs = err1;
	else
		cs = err2;

  #if defined(_AVR)
	cstrcpy(buf, cs);
	return buf;
  #else
	return (char *)cs;
  #endif
	}

char *_FormatFP_1(char *my_buffer, 
    int format, float f, unsigned flag, int field_width, int prec)
  {
  char * my_ascii_float;
  int ftoa_status;

  float test_number;  // add to f to round decimals 
  float f_abs;  // abs value of f for magnitude checks 

  int last_digit_position_found = -1;
  int dp_position_found = -1, dp_position_assumed = -1;
  int first_non_z_position_before_dp = -1;
  int first_non_z_position_found = -1;
  int last_non_z_position_after_dp = -1;
  int num_sig_figs_before_dp = 0;
  int end_of_string; 

  int first_result_digit_position;

  int number_width;

  int exponent = 0xFF; // want to know if it's not initialized 

  int is_minus = 0;
  int want_eform = 0;
  int i, j, k;

  char lpad_char = ' ', rpad_char = ' ';
  char exp_char = 'e';
  char this_char, sign_char;

  // sanity checks on some parameters
  if(field_width > F_FP_BFR_SIZE) field_width = F_FP_BFR_SIZE; 
  if(prec > F_FP_BFR_SIZE) prec = F_FP_BFR_SIZE; 


  switch(format){ // what format do we want? 

    case FMT_NORMAL:    // default 
      break;

    case FMT_SCIENTIFIC_BIG_E:  // want exponential with upper case "E"
      exp_char = 'E';  
    // fall into 
    case FMT_SCIENTIFIC:   // want exponential notation
      want_eform = 1;
      break;

    case FMT_OPTIMUM_BIG_E:  // may want exponential with upper case "E"
      exp_char = 'E';  
      // fall into 
    case FMT_OPTIMUM:   // may want exponential notation, test for it

      f_abs = f;
      if(f < 0) f_abs = (f * -1);

      test_number = (float) 1; // test for size vs precision
      for(i = 0; i < prec; i++) test_number *= 10;

      if((f_abs < (float) .0001) || (f_abs > test_number))     
        want_eform = 1;
      break;

  } // switch 


  // some preliminaries 
  if (flag & F_ZEROPADD) lpad_char = '0';
  sign_char = lpad_char;  // will test for this equality later 
  if (flag & F_ADDSIGN) sign_char = '+';

  // get the ASCII string to reformat 

  if(want_eform){
    my_ascii_float = ftoa(f, &ftoa_status); // will round later
  } // want exponential form
  else{// don't want exponential format, round by addition

    test_number = (float) 0.5; // add to f to round decimals, want one place beyond last
    for(i = 0; i < prec; i++) test_number /= 10;
    
    if(f < 0) 
      my_ascii_float = ftoa(f - test_number, &ftoa_status);
    else
      my_ascii_float = ftoa(f + test_number, &ftoa_status);

  } // don't want exponential format


  if (ftoa_status != 0)
	return FtoaError(my_buffer, ftoa_status);

  // analyze the number and the parameters
  for(i = 0; i < F_FP_BFR_SIZE; i++){ 

    // do we have enough digits past the decimal yet(non-exp only)?
    if((want_eform == 0) && (dp_position_found >= 0) && ((i - dp_position_found) > prec))
      break;  

    this_char = *(my_ascii_float + i);  // get a character 

    // see if this character is a digit, and keep count of significant figures 
    if((this_char >= '0') && (this_char <= '9')){ // is a digit

      last_digit_position_found = i;

      if(this_char > '0') // non-zero digit found
        if(first_non_z_position_found < 0) first_non_z_position_found = i;

      if(dp_position_found < 0) { // before decimal (if any)

        if((first_non_z_position_before_dp < 0) && (this_char > '0')){ 
          first_non_z_position_before_dp = i;
        } // first non-zero before decimal

        if(first_non_z_position_before_dp >= 0) num_sig_figs_before_dp++; 
        // digits after first non-zero

      } // before decimal

      if(dp_position_found >= 0){ // after decimal
  
        if (this_char > '0'){ // sig figs after decimal 

          last_non_z_position_after_dp = i;
          // last non-zero after decimal
          
        } // sig figs after decimal 

      } // after decimal 

    } // is a digit

    // is this character the decimal point? 
    if(this_char == '.'){
      dp_position_found = i;
    } // decimal found

    // is the number negative? 
    if(this_char == '-'){
      is_minus = 1;
      sign_char = '-';
    } // minus

    // stop at end of string
    if(this_char == 0) break; // terminating null

  } // for 

  // if no decimal found, assume it's right after last digit
  // for consistency in later checks
  if(dp_position_found < 0){

    dp_position_assumed = last_digit_position_found + 1;
    end_of_string = dp_position_assumed + 1;

  } // no decimal
  else { // decimal

    dp_position_assumed = dp_position_found;

    if(last_non_z_position_after_dp < 0){ // no non-zero digits after decimal
      end_of_string = dp_position_assumed + 1;
    } // no non-zero digits after decimal
    else { // non-zero digits after decimal 
      end_of_string = last_non_z_position_after_dp + 1;
    } // non-zero digits after decimal 

  } // decimal

  // any non-zero digits before the decimal?
  if(first_non_z_position_before_dp < 0) // no non-zero before decimal  
    first_non_z_position_before_dp = dp_position_assumed - 1;

  if(want_eform){ // exponential format 

    // build the string from the left
    //  if don't want left-justified, move it over later

    // sign plus leading digit plus decimal 
    i = 0;
    if(sign_char != lpad_char){ // minus or want plus sign 
      my_buffer[i++] = sign_char;
    } // if
    my_buffer[i++] = *(my_ascii_float + first_non_z_position_found);
    my_buffer[i] = '.'; // decimal point
    if(prec > 0) i++; // don't overwrite decimal point later with E char 

/*    if(prec > 0) my_buffer[i++] = '.'; // decimal point */

    j = first_non_z_position_found + 1;
    k = 0;
    while((k < prec) && (i < (F_FP_BFR_SIZE - MAX_EXP_WIDTH))){ // digits

      if(j != dp_position_assumed){ // digits, skip the decimal point
        if(j < end_of_string) // still in string
          my_buffer[i++] = *(my_ascii_float + j);
        else{ // past end of found digits, check for alt form or X.[nothing] 
          if((flag & F_ALTFORM) || (0 == k)) my_buffer[i++] = '0';
          else break;
        } // past end of found digits 
        k++;
      } // digits, skip the decimal point
      j++;

    } // while digits 

    k = i - 1; // last output digit position, for use in rounding later 
    if(0 == prec) k = i; // point to decimal if zero precision (needed for testing)

/*    my_buffer[i++] = exp_char; // "e" or "E" */

    // now for the exponent
    // what power of ten depends on where first non-zero digit was 
    // rounding assumes we have exponent value, so do it now, not later
    exponent = (dp_position_assumed - first_non_z_position_found - 1);

    if((j < end_of_string) && (*(my_ascii_float + j) == '.')) j++;

    if((j < end_of_string) //  digits left for rounding
      && (*(my_ascii_float + j) >= '5') && (*(my_ascii_float + j) <= '9')){ // round up

      while(k >= 0){ // more digits need adjusting 

        if((my_buffer[k] >= '0') && (my_buffer[k] <= '8')){ // round up digit, no carry
          my_buffer[k]++; // round up digit, no carry
          break; // done rounding
        } // round up digit, no carry

        if((my_buffer[k] == '.') 
          /* || (0 == prec) && ((my_buffer[k] == 'e') || (my_buffer[k] == 'E'))*/ 
          )
          { // skip the decimal point, only one more digit 

          k--;

          if((my_buffer[k] >= '0') && (my_buffer[k] <= '8')){ // round up digit, no carry
            my_buffer[k]++; // round up digit, no carry
            break; // done rounding
          } // round up digit, no carry
          
          if(my_buffer[k] == '9'){ // special case
            my_buffer[k] = '1'; // was a string of 9's, will be 1 and a string of zeros
            exponent++;
            break;
          } // special case

        }// skip the decimal point, only one more digit 

        if(my_buffer[k] == '9'){ // propagate carry 
          my_buffer[k] = '0';
        }  // propagate carry 
        // fall into

        k--; // next digit

      } // more digits need adjusting 

    } // rounding

    my_buffer[i++] = exp_char; // "e" or "E" 

    // convert the exponent to ASCII
    if(exponent < 0){ // negative exponent
      my_buffer[i++] = '-';
      exponent = ~exponent; // unsigned itoa()
    } // negative exponent

#ifdef _WIN32
    itoa_W32(&my_buffer[i], exponent, 10); // for tests in Win32 environment 
#endif
#ifdef __IMAGECRAFT__
    itoa(&my_buffer[i], exponent, 10); // for real ICC environment 
#endif

    // now align and pad as needed
    for(i = 0; i < F_FP_BFR_SIZE; i++){ // how long is our output string? 
      if(0 == my_buffer[i]){ 
        number_width = i; break; 
      } // found terminating null
    } // for 

    // left or right align? 
    if(flag & F_LEFTALIGN){ // pad on right
      if(number_width < field_width){ // need padding, including overwriting null 
        for(j = number_width; j < field_width; j++){ 
          my_buffer[j] = rpad_char;
        } // for
        my_buffer[field_width - 1] = 0; // new terminating null
      } // need padding
    } // pad on right
    //if not want left align, find length of string, shift to right
    else{ // right align, pad on left
      if(number_width < field_width){ // room to shift to right
        for(j = number_width; j >= 0; j--){
          my_buffer[j + field_width - number_width] = my_buffer[j];
        } // for 
        for(j = field_width - number_width - 1; j >= 0; j--){ // padding  
          my_buffer[j] = lpad_char;
        } // for padding
        // move sign character?
        if((flag & F_ZEROPADD) && (sign_char != lpad_char)){ // move sign to left
          my_buffer[0] = sign_char;
          my_buffer[field_width - number_width] = lpad_char;
        } // move sign
      } // room to shift to right
    } // right align

  } // exponential format 
  else
  { // normal format

    // do we want trailing zeros? 
    if(flag & F_ALTFORM){
      if(end_of_string <= (dp_position_assumed + prec)) 
        end_of_string = dp_position_assumed + prec + 1;
    } // space for trailing zeros
    else {
      // if no digits after decimal, drop decimal
      if(end_of_string == dp_position_assumed + 1) end_of_string = dp_position_assumed;
    } // don't want trailing zeros

    // buffer size check

    if(end_of_string > F_FP_BFR_SIZE) end_of_string = F_FP_BFR_SIZE;

    // width of number, not counting sign
    number_width = end_of_string - first_non_z_position_before_dp;

    // now include the sign
    if(sign_char != lpad_char) number_width++;

    // allow it to overflow the specified field width 
    if(field_width < number_width) field_width = number_width;

    // buffer size check
    if(field_width > F_FP_BFR_SIZE) field_width = F_FP_BFR_SIZE;
    if(number_width > F_FP_BFR_SIZE) number_width = F_FP_BFR_SIZE;
  
    // do left or right alignment
    if((flag & F_LEFTALIGN) || (field_width == number_width)){ // no empty space to the left
  
      first_result_digit_position = 0;  // left alignment 
      if(sign_char != lpad_char){
        my_buffer[0] = sign_char;
        first_result_digit_position = 1;
      } // space for sign?
  
    } // left alignment
    else { // right alignment
    
      first_result_digit_position = field_width - number_width; 
  
      // padding first, may overwrite one char with the sign
      for(j = 0; j <= first_result_digit_position; j++)
        my_buffer[j] = lpad_char;
    
      if(sign_char != lpad_char){ // show the sign 
        if(flag & F_ZEROPADD)my_buffer[0] = sign_char; 
        else my_buffer[first_result_digit_position] = sign_char;
        first_result_digit_position++; // point to first actual digit
      } // show the sign    
  
    } // right alignment

    // now start building the output string 
    j = first_result_digit_position;

    if(num_sig_figs_before_dp == 0) {
      my_buffer[j] = '0';
      j++;
    } // no leading non-zero digits 

    for(i = 0; i < num_sig_figs_before_dp; i++){ // copy digits before decimal 
  
      my_buffer[j] = *(my_ascii_float + i + first_non_z_position_before_dp);
      j++;
    } // copy digits before decimal
   
    if(end_of_string > dp_position_assumed){ // want decimal point
      my_buffer[j] = '.';
      j++;
    } // want decimal point 
    
    for(i = 0; (i < prec) && (j < F_FP_BFR_SIZE); i++){ // digits after decimal
  
      if(i < (last_non_z_position_after_dp - dp_position_found)) // more digits  
        my_buffer[j] = *(my_ascii_float + i + dp_position_found + 1);
      else{ // test for Alternate form
        if(flag & F_ALTFORM) my_buffer[j] = '0';
        else break;
      } // test for Alternate form
    
      j++;
    
    } // digits after decimal

    while(j < field_width){ // final padding
      my_buffer[j] = rpad_char;
      j++;
    } // final padding
  
    my_buffer[j] = 0; // terminating null
    
  } // normal format
    
    return &my_buffer[0];
  
} // FormatFP_1

⌨️ 快捷键说明

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