سؤال

لقد كنت أحاول كتابة أ العودية نسخة من الوظيفة itoa, ، يظهر رمز أدناه.

void itoa(int n, char s[])
{
     static int i = 0;

     if(n / 10 != 0)
         itoa(n/10, s);
     else if(n < 0)
         i = 1; /* s[0] is allready taken by - sign */
     else 
         i = 0; /* reset i to 0 */

     if(n < 0) {
          s[0] = '-';
     }

     s[i++] = abs(n % 10) + '0';
     s[i] = '\0';
}

لكن الكود ليس مثاليًا. يستخدم static متغير وربما لا يتم تنفيذه بأسرع ما ينبغي. أحاول تحقيق أ تشغيل) خوارزمية. هل يمكن لأي شخص أن يريني طريقة أفضل؟ أعتقد أيضًا أن المتغير الثابت ليس ضروريًا ، لكنني لست متأكدًا تمامًا من كيفية تجنب ذلك. هل يجب علي تقسيم الوظيفة إلى اثنين من الحدود لتجنب المتغير الثابت؟

هل كانت مفيدة؟

المحلول

إذا كنت ترغب في حلها بشكل متكرر ، فقد يكون النهج الأسهل هو إرجاع الفهرس الأخير:

int itoa(int n, char s[])
{
    int i =  0;         

    if(n / 10 != 0)
        i = itoa(n/10, s);
    else if(n < 0)
        s[i++] = '-';

    s[i++] = abs(n % 10) + '0';
    s[i] = '\0';

    return i;
}

يمكنك أيضًا حلها باستخدام مؤشرات:

char * itoa(int n, char * s)
{
    char * dest = s;

    if(n / 10 != 0)
        dest = itoa(n/10, dest);
    else if(n < 0)
        *dest++ = '-';

    *dest++ = abs(n % 10) + '0';
    *dest = '\0';

    return dest;
}

ومع ذلك ، فإن الأمر الذي يجب ملاحظة أن هذا التنفيذ عرضة لتدفق العازلة. يجب أن تكون على يقين من أنك قمت بتخصيص مخزن مؤقت كبير بما فيه الكفاية لتناسب تمثيل ASCII بأكمله من عدد صحيح. ستكون الفكرة الجيدة هي تضمين بعض التحقق من الحدود.

نصائح أخرى

يجب أن تعيد ITOA باطلة.
لم أختبر هذا ، لكنني أعتقد أنه سيعمل.
لا متغيرات ثابتة ، لا وظائف مساعد ، لا حجج إضافية.
قد يكون تقسيم عدد صحيح زائد في الحلقة نقطة ضعف.

void itoa(int n, char *s)  
{  
    char c;  
    if (n < 0)  
    {  
        *s++ = '-';  
        itoa(-n, s);  
        return;  
    }  
    c = '0' + n % 10;  
    itoa(n / 10, s);  
    while ( n /= 10 ) s++;  
    *s++ = c;  
    *s = '\0';  
}  
char* itoa(int n, char s[]) {
  if (n < 0) {
    s[0] = '-';
    return itoa(-n, s+1);
  }
  if (n/10 > 0) {
     s = itoa(n/10, s);
  }
  s[0] = '0' + (n%10);
  s[1] = '\0';
  return &s[1];
}

لديك أيضًا الميزة التي تفيد بأن itoa تُرجع عنوان نهاية السلسلة.

حل مذهل على الرغم من مشكلة صغيرة واحدة. يتلقى هذا الرمز خطأ تجزئة لأن حالة العودية الأساسية: متى n==0 لم يتم التعامل معها بشكل صحيح. لقد قمت بتغيير بسيط في برنامجك والآن يعمل بشكل جيد.

void itoa(int n,char *s)
{
    char c;
    if (n < 0)
    {
        *s++ = '-';
        itoa(-n, s);
        return;
    }
    if (n==0)
        return;
    c = '0' + n % 10;
    itoa(n/10,s);
    while ( n /= 10 ) s++;
    *s++ = c;
    *s = '\0';
}

الآن بالنسبة إلى بنسات ثنائية ، قمت بحل هذا دون استخدام التقسيم ولكن بدلاً من ذلك باستخدام مؤشرات مزدوجة للقيم لتستمر بين مكالمات الوظائف.

فقط demerit من الحل هو أننا نحتاج إلى الحفاظ على عنوان بداية صفيف الأحرف.

void itoa(char**a,int i)
{
    int dig;
    if(i<10) //base case;
    {
        **a=i+48;
        *(++(*a))='\0';
        return;
    }
    dig=i%10;
    itoa(a,i/10);
    **a=dig+48;  //char value + 48 will give me the corresponding value
    *(++(*a))='\0';
    return;
}

int main()
{
    char* t=(char*)malloc(sizeof(char)*5);
    char* save=t;
    int ti=1234;
    itoa(&t,ti);
    printf("%s",save);
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top