2013-05-20 2 views
15

का न्यूनतम कार्यान्वयन मैं एक एम्बेडेड डीएसपी पर काम कर रहा हूं जहां गति महत्वपूर्ण है, और स्मृति बहुत कम है।sprintf या printf

फिलहाल, sprintf मेरे कोड में किसी भी फ़ंक्शन के अधिकांश संसाधनों का उपयोग करता है। मैं केवल कुछ सरल पाठ प्रारूपित करने के लिए इसका उपयोग करता हूं: %d, %e, %f, %s, सटीक या विदेशी कुशलता के साथ कुछ भी नहीं।

मैं मूल स्पिंटफ या प्रिंटफ फ़ंक्शन को कैसे कार्यान्वित कर सकता हूं जो मेरे उपयोग के लिए अधिक उपयुक्त होगा?

+0

google में अपना विषय शीर्षक दर्ज करना यहां बहुत सारी हिट मिली। बीटीडब्ल्यू: आप हमेशा अपना खुद का रोल कर सकते हैं। % ई और% एफ थोड़ा कठिन हो सकता है, लेकिन% d और% s तुच्छ हैं। – wildplasser

+0

@wildplasser टिप्पणी के बाद, क्या आपको वास्तव में फ़्लोटिंग-पॉइंट का उपयोग करना है? –

+0

हां मैं करता हूं, डीएसपी का उपयोग एडीसी के माध्यम से मापा जाता है जो मूल्य प्रदान करने के लिए किया जाता है .. इसलिए फ्लोट की आवश्यकता है। – Gui13

उत्तर

8

यह एक itoa के अस्तित्व को एक int से चरित्र प्रतिनिधित्व में परिवर्तित करने के लिए, और fputs को जहां भी आप जाना चाहते हैं वहां एक स्ट्रिंग लिखने के लिए मानते हैं।

चल बिन्दु उत्पादन कम से कम एक मामले में गैर-अनुरूप है: इसे सही ढंग से गोलाई में कोई प्रयास करता है, के रूप में मानक की आवश्यकता है, इसलिए यदि आप (उदाहरण के लिए) है कि आंतरिक रूप से 1.2399999774 के रूप में संग्रहीत किया जाता है 1.234 के एक मूल्य , इसे 1.2340 के बजाय 1.2399 के रूप में मुद्रित किया जाएगा। यह काफी काम बचाता है, और अधिकांश सामान्य उद्देश्यों के लिए पर्याप्त बना रहता है।

यह भी %c और रूपांतरण आप के बारे में पूछा के अलावा %x का समर्थन करता है, लेकिन वे बहुत दूर करने के लिए तुच्छ हो आप उनमें से छुटकारा पाने के लिए चाहते हैं (और ऐसा करने स्पष्ट रूप से एक थोड़ा स्मृति की बचत होगी) यदि।

#include <stdarg.h> 
#include <stdio.h> 
#include <string.h> 
#include <windows.h> 

static void ftoa_fixed(char *buffer, double value); 
static void ftoa_sci(char *buffer, double value); 

int my_vfprintf(FILE *file, char const *fmt, va_list arg) { 

    int int_temp; 
    char char_temp; 
    char *string_temp; 
    double double_temp; 

    char ch; 
    int length = 0; 

    char buffer[512]; 

    while (ch = *fmt++) { 
     if ('%' == ch) { 
      switch (ch = *fmt++) { 
       /* %% - print out a single % */ 
       case '%': 
        fputc('%', file); 
        length++; 
        break; 

       /* %c: print out a character */ 
       case 'c': 
        char_temp = va_arg(arg, int); 
        fputc(char_temp, file); 
        length++; 
        break; 

       /* %s: print out a string  */ 
       case 's': 
        string_temp = va_arg(arg, char *); 
        fputs(string_temp, file); 
        length += strlen(string_temp); 
        break; 

       /* %d: print out an int   */ 
       case 'd': 
        int_temp = va_arg(arg, int); 
        itoa(int_temp, buffer, 10); 
        fputs(buffer, file); 
        length += strlen(buffer); 
        break; 

       /* %x: print out an int in hex */ 
       case 'x': 
        int_temp = va_arg(arg, int); 
        itoa(int_temp, buffer, 16); 
        fputs(buffer, file); 
        length += strlen(buffer); 
        break; 

       case 'f': 
        double_temp = va_arg(arg, double); 
        ftoa_fixed(buffer, double_temp); 
        fputs(buffer, file); 
        length += strlen(buffer); 
        break; 

       case 'e': 
        double_temp = va_arg(arg, double); 
        ftoa_sci(buffer, double_temp); 
        fputs(buffer, file); 
        length += strlen(buffer); 
        break; 
      } 
     } 
     else { 
      putc(ch, file); 
      length++; 
     } 
    } 
    return length; 
} 

int normalize(double *val) { 
    int exponent = 0; 
    double value = *val; 

    while (value >= 1.0) { 
     value /= 10.0; 
     ++exponent; 
    } 

    while (value < 0.1) { 
     value *= 10.0; 
     --exponent; 
    } 
    *val = value; 
    return exponent; 
} 

static void ftoa_fixed(char *buffer, double value) { 
    /* carry out a fixed conversion of a double value to a string, with a precision of 5 decimal digits. 
    * Values with absolute values less than 0.000001 are rounded to 0.0 
    * Note: this blindly assumes that the buffer will be large enough to hold the largest possible result. 
    * The largest value we expect is an IEEE 754 double precision real, with maximum magnitude of approximately 
    * e+308. The C standard requires an implementation to allow a single conversion to produce up to 512 
    * characters, so that's what we really expect as the buffer size.  
    */ 

    int exponent = 0; 
    int places = 0; 
    static const int width = 4; 

    if (value == 0.0) { 
     buffer[0] = '0'; 
     buffer[1] = '\0'; 
     return; 
    }   

    if (value < 0.0) { 
     *buffer++ = '-'; 
     value = -value; 
    } 

    exponent = normalize(&value); 

    while (exponent > 0) { 
     int digit = value * 10; 
     *buffer++ = digit + '0'; 
     value = value * 10 - digit; 
     ++places; 
     --exponent; 
    } 

    if (places == 0) 
     *buffer++ = '0'; 

    *buffer++ = '.'; 

    while (exponent < 0 && places < width) { 
     *buffer++ = '0'; 
     --exponent; 
     ++places; 
    } 

    while (places < width) { 
     int digit = value * 10.0; 
     *buffer++ = digit + '0'; 
     value = value * 10.0 - digit; 
     ++places; 
    } 
    *buffer = '\0'; 
} 

void ftoa_sci(char *buffer, double value) { 
    int exponent = 0; 
    int places = 0; 
    static const int width = 4; 

    if (value == 0.0) { 
     buffer[0] = '0'; 
     buffer[1] = '\0'; 
     return; 
    } 

    if (value < 0.0) { 
     *buffer++ = '-'; 
     value = -value; 
    } 

    exponent = normalize(&value); 

    int digit = value * 10.0; 
    *buffer++ = digit + '0'; 
    value = value * 10.0 - digit; 
    --exponent; 

    *buffer++ = '.'; 

    for (int i = 0; i < width; i++) { 
     int digit = value * 10.0; 
     *buffer++ = digit + '0'; 
     value = value * 10.0 - digit; 
    } 

    *buffer++ = 'e'; 
    itoa(exponent, buffer, 10); 
} 

int my_printf(char const *fmt, ...) { 
    va_list arg; 
    int length; 

    va_start(arg, fmt); 
    length = my_vfprintf(stdout, fmt, arg); 
    va_end(arg); 
    return length; 
} 

int my_fprintf(FILE *file, char const *fmt, ...) { 
    va_list arg; 
    int length; 

    va_start(arg, fmt); 
    length = my_vfprintf(file, fmt, arg); 
    va_end(arg); 
    return length; 
} 


#ifdef TEST 

int main() { 

    float floats[] = { 0.0, 1.234e-10, 1.234e+10, -1.234e-10, -1.234e-10 }; 

    my_printf("%s, %d, %x\n", "Some string", 1, 0x1234); 

    for (int i = 0; i < sizeof(floats)/sizeof(floats[0]); i++) 
     my_printf("%f, %e\n", floats[i], floats[i]); 

    return 0; 
} 

#endif