Jump to content
Sign in to follow this  
encik pot pet

Coding Function Atoi()

Recommended Posts

Masa aku belajar matematik moden tingkatan empat dulu, ada satu topik menarik iaitu Asas Nombor. Dalam kelas tu juga aku terfikir kenapa la orang-orang tua zaman dulu duk buat benda macam ni? Asas 10 (decimal) memang dah sempurna membuat pengiraan, kenapa nak ditambah-tambah lagi?

Lepas habis zaman sekolah, aku masuk kolej matrikulasi. Kat sini la aku belajar computer programming dengan menggunakan C++ (sebenarnya bukan C++ betul pun, sebaliknya C + iostream.h sebab takde bab OOP). Subject kat sini kira cukup la untuk faham 'what is computer programming' (variable, arithmetic, loop, etc), dan paling menarik apabila sampai bab Pointer, semua budak pening termasuk aku. Dengan sepantas kilat, cikgu kelas tu tutup buku dan halau kami semua pegi suruh makan kat kantin Maksu Timah.

OK. Kembali kepada topik.

Masa kat matrik ni ler aku faham kenapa orang tua zaman dulu cipta nombor asas dua (binary) dan seterusnya dari binary dikembangkan kepada asas lapan (oct) dan asas enam belas (hex). Sebabnya komputer ni otak dia lain sikit (ting tong), tak macam otak manusia. Kalau nak mengira, komputer terpaksa pakai nombor binary. Tapi masa ni, aku masih lagi blur atau ting tong macam mana komputer guna binary tu. Lepas habis matrik, aku sambung pulak kejuruteraan electrical/electronical. Masa ni la hampir-kesemua-persoalan-terjawab sebab aku ambik paper digital electronic dan micro computer design/architecture.

OK. Kembali kepada persoalan sebenar topik.

Kita tengok coding dibawah

/* main.c */
#include <stdio.h>
#include <stdlib.h>

int main()
{
    int x = 0;
    x = atoi("123456");
    printf("%d",x);
    return 0;
}
Soalannya, apakah nilai x? Senang jer kan, x = 123456. Tiga setengah tahun lepas, aku secara tiba-tiba nak pakai atox (convert hexadecimal string to int). Tapi atox tak wujud dalam standard library C. Sebagai contoh;
    int x = 0;
    x = atox("FFA2CD9");
    printf("%d",x);

Aku nak output keluar sebagai x == 268053721. Oleh itu, aku nak adik-adik student yang bertandang kat forum ni, tolong buatkan function atox(hex) untuk saya. Bagi memudahkan saya di masa hadapan, jangan lupa untuk buat atob(binary),dan atoc(oct). Akan tetapi, anda kena buat sendiri, jangan tiru atau copy/paste. May god bless you.

Basic Hints:

234d = 2 × 10^2 + 3 × 10^1 + 4 × 10^0

11001b = 1 × 2^4 + 1 × 2^3 + 0 × 2^2 + 0 × 2^1 + 1 × 2^0

^ -> kuasa, 10^2 -> sepuluh kuasa dua

Sekian, harap maklum.

p.s. Cerita selingan di atas adalah rekaan semata-mata untuk menyedapkan jalan cerita.

Share this post


Link to post
Share on other sites

note that atoi means ascii-to-integer, yang convert C-style ascii string ke integer. bukankah nama atox membayangkan fungsi ascii-to-hex... sesuatu yang pelik, since integer adalah (kelas nombor?, e.g integer vs float).. dan hex adalah base number (e.g hex vs bin).. rasanya kalau ikut objektif mr zeph, sepatutnya kita namakan fungsi ni hextoint, atau lebih tepat lagi asciihextoint atau sesuatu yang macam tu.. tak gitu?

satu nota lagi.. atoi sebenarnya dah lapuk. ansi C ader define fungsi strtol dan stroul, yang convert string ke int dalam base 2-36. so saper2 yang nak idea buat benda ni, bolehlaa kot tengok sources standard C library compiler/system awak ;).

Share this post


Link to post
Share on other sites

Rasanya ini tak menjawab soalan tapi saja gatal nak post jugak... huhu

#include <stdio.h>

int
main()
{
  printf("Int = %d\n", 0xFFA2CD9); 

  return 0;
}

Share this post


Link to post
Share on other sites

note that atoi means ascii-to-integer, yang convert C-style ascii string ke integer. bukankah nama atox membayangkan fungsi ascii-to-hex... sesuatu yang pelik, since integer adalah (kelas nombor?, e.g integer vs float).. dan hex adalah base number (e.g hex vs bin).. rasanya kalau ikut objektif mr zeph, sepatutnya kita namakan fungsi ni hextoint, atau lebih tepat lagi asciihextoint atau sesuatu yang macam tu.. tak gitu?

this is my topic, and i just invite student to reply.

satu nota lagi.. atoi sebenarnya dah lapuk. ansi C ader define fungsi strtol dan stroul, yang convert string ke int dalam base 2-36. so saper2 yang nak idea buat benda ni, bolehlaa kot tengok sources standard C library compiler/system awak ;).

if u want all the function ready to be use, why use C. go learn java, .net, python, ruby.

Share this post


Link to post
Share on other sites

saya cuma berikan pendapat supaya nama fungsi awak konsisten dengan nama atoi.. in the end ia awak punya fungsi dan saya takkan suruh awak tukar :). dan seperti kata awak.. topik awak dan awak mod, kalau post saya tiada kaitan dengan thread awak.. silalah jangan segan untuk dipadamkan.

also saya juga berikan maklumat tambahan, manalah tahu sesiapa yang tak aware (seperti awak..hehehe) wujudnya beberapa fungsi dalam C library yang boleh membantu mereka.. but in the end.. ia awak punya topik... sorry to interferes dengan benda2 yang remeh ni.

Share this post


Link to post
Share on other sites

berdasarkan komen membina Paralys3r, function 'atox' tu aku tukar jadi 'hexatoi' bermaksud 'hexadecimal ascii to integer' :)

macam biasa la kalau buat kuiz mcm ni, takde student nak tolong buatkan.

oleh itu, aku nak bagi contoh jawapan. tapi kod ada sedikit masalah dengan optimization option. tugas korang la tolong fix utk speed up dan lain2.

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

/* slow version */
int myatoi2(char* s)
{
    int digit = 0;
    int total = 0;
    int i = 0;


    for (i = (strlen(s)-1); i >= 0; i--)
    {
        //total += (s[i]-'0') * (int)(pow (10.0,digit));
        total += (s[i]-'0') * (int)(pow (10.0,digit));
        digit++;
    }

    return total;
}

/* faster version */
int myatoi (char* s)
{

    int total = 0;
    int c =*s++;

    while ( (c = chartodigit(c)) != -1 )
    {
        total = (10 * total) + c;     /* accumulate digit */
        c = *s++;    /* get next char */
    }
    return total;
}

/* slow version */
int hexatoi2 (char* s)
{
    int len, i;
    int total = 0;
    int digit = 0;

    len = strlen(s);
    if (len > 8)    /* we just accept DWORD value */
    {
        return -1;
    }

    for (i = len - 1; i >= 0; i--)
    {
        if (s[i] >= '0' && s[i] <='9')
        {
            total += (s[i]-'0') * (int)(pow (16.0,digit));
            digit++;
        }
        else if (s[i] >= 'A' && s[i] <='Z')
        {
            total += (s[i]-55) * (int)(pow (16.0,digit));
            digit++;
        }
        else if (s[i] >= 'a' && s[i] <= 'z')
        {
            total += (s[i]-87) * (int)(pow (16.0,digit));
            digit++;
        }
        else
        {
            printf ("\nwrong number format\n");
            return -1;
        }
    }

    return total;
}

/* faster version */
int hexatoi (char* s)
{

    int c =*s++;
    int total = 0;

    while ( (c = hexchartodigit(c)) != -1 )
    {
        total = (total * 16) + c; /* accumulate digit */
        /* total = (total << 4) + c; */ /* alternate way */
        c = *s++;    /* get next char */
    }
    return total;
}


int chartodigit(int c)
{
    int d;
    d = (c) >= '0' && (c) <= '9' ? (c) - '0' : -1;
    return d;
}

int hexchartodigit(int c)
{
    int d;
    d = (c) >= '0' && (c) <= '9' ? (c) - '0' : -1;
    if (d != -1)
    {
        return d;
    }

    d = (c) >= 'A' && (c) <= 'Z' ? (c) - 55 : -1;
    if (d != -1)
    {
        return d;
    }

    d = (c) >= 'a' && (c) <= 'z' ? (c) - 87 : -1;
    if (d != -1)
    {
        return d;
    }
    else
        return -1;
}

/* test our functions */
int main()
{
    int value = 0;
    unsigned long int start, end, total_time;
    int i = 0;
    int j = 0;
    int dummy = 0;

    /* test faster version */
    value = hexatoi("aF1234A");
    printf("%d - fast\n",value);

    /* test slow version */
    value = hexatoi2("aF1234A");
    printf("%d - slow\n",value);

/*----------------- hexatoi ----------------------*/
printf("\n");

    /* how fast is fast? */
    start = GetTickCount();
    for (j = 0; j < 0x1FFFFF; j++)
    {
        dummy = hexatoi2("fF12345");
    }
    end = GetTickCount();

    total_time = end - start;
    printf("result for hexatoi2: ");
    printf("%d.%03d saat (sangat perlahan)\n",total_time/1000, total_time%1000);

        start = GetTickCount();
    for (i = 0; i < 0x1FFFFF; i++)
    {
        dummy = hexatoi("fF12345");
    }
    end = GetTickCount();

    total_time = end - start;
    printf("result for hexatoi : ");
    printf("%d.%03d saat\n",total_time/1000, total_time%1000);

/*----------------- atoi -----------------------*/
    printf("\n");

    start = GetTickCount();
    for (j = 0; j < 0x1FFFFF; j++)
    {
        dummy = myatoi("2854368068");
    }
    end = GetTickCount();

    total_time = end - start;
    printf("result for myatoi: ");
    printf("%d.%03d saat (myatoi lagi laju :))\n",total_time/1000, total_time%1000);

    start = GetTickCount();
    for (i = 0; i < 0x1FFFFF; i++)
    {
        dummy = atoi("2854368068");
    }
    end = GetTickCount();

    total_time = end - start;
    printf("result for atoi  : ");
    printf("%d.%03d saat - ni atoi dari C standard library\n",total_time/1000, total_time%1000);

    return 0;
}

notes: myatoi lebih laju dari standard atoi sebab myatoi takde extensive error checking.

Share this post


Link to post
Share on other sites

adakah awak compile dengan optimization option? sebab kalau tak, atoi still lebih pantas dari myatoi (tested in XP and Gentoo Linux).

*ASSUME NO COMPILER OPTIMIZATION FLAGS ARE ON*, gunakan shift sepatutnya lebih pantas dari multiplication. So, myatoi_p berikut sepatutnya GENERALLY lebih pantas dari myatoi. Ceritanya mungkin jadi lain bila kita start gunakan optimization option dan arch-specific option (-O* in gcc atau /O* in cl). Contohnya, dengan -O3 dalam gcc dalam sistem saya, myatoi dan myatoi_p lebih kurang je.

int myatoi_p(const char *s)
{
    int total = 0, neg = 0;
    unsigned char c;
    const char *s1 = s;
    do { if (!isspace(*s1++)) break; } while (1);
    s = s1 - 1;
    c = *s;
    if (c == '+') s++;
    if (c == '-') {
        s++;
        neg++;
    }
    while ((c = *s++ - '0') <= 9) total = (total << 3) + (total << 1) + c;
    return (neg ? -total : total);
}
Ia lebih menyerupai atoi dari standard c (note that std c define atoi as similar to (int)strtol(nptr, (char **)NULL, 10), except in behavior on error) dan pantas :). hexatoi (rename as hexatoi_p) saya pula :
int hexatoi_p(const char *s)
{
    int total = 0, neg = 0;
    unsigned char c;
    const char *s1 = s;
    do { if (!isspace(*s1++)) break; } while (1);
    s = s1 - 1;
    c = *s;
    if (c == '+') s++;
    if (c == '-') {
        s++;
        neg++;
    }
    do {
        c = *s++ - '0';
        if (c > 9) {
            c -= 7;
            if (c > 15) c -= 32;
            if (c > 15) break;
        }
        total = (total << 4) + c;
    }
    while (1);
    return (neg ? -total : total);
}
Result (amik the best from each) :
#gcc -otest test.c #./test calling ascii-hex-to-int 1000000 times time for hexatoi: 0.140000 time for hexatoi_p: 0.070000 time for strtol: 0.050000 calling ascii-int-to-int 1000000 times time for myatoi: 0.150000 time for myatoi_p: 0.080000 time for atoi : 0.070000 #gcc -O -otest test.c #./test calling ascii-hex-to-int 1000000 times time for hexatoi: 0.060000 time for hexatoi_p: 0.030000 time for strtol: 0.060000 calling ascii-int-to-int 1000000 times time for myatoi: 0.050000 time for myatoi_p: 0.030000 time for atoi : 0.060000 #gcc -O2 -otest test.c #./test calling ascii-hex-to-int 1000000 times time for hexatoi: 0.040000 time for hexatoi_p: 0.020000 time for strtol: 0.060000 calling ascii-int-to-int 1000000 times time for myatoi: 0.040000 time for myatoi_p: 0.030000 time for atoi : 0.060000 #gcc -O3 -otest test.c #./test calling ascii-hex-to-int 1000000 times time for hexatoi: 0.020000 time for hexatoi_p: 0.020000 time for strtol: 0.050000 calling ascii-int-to-int 1000000 times time for myatoi: 0.020000 time for myatoi_p: 0.020000 time for atoi : 0.060000
System - Intel EM64T (Core 2 Duo) 1.86 GHz + Gentoo Linux 64-bit + glibc-2.5. your modified test.c function (gunakan std c timing functions instead of Windows specific) :
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int chartodigit(int c)
{
    int d;
    d = (c) >= '0' && (c) <= '9' ? (c) - '0' : -1;
    return d;
}

int hexchartodigit(int c)
{
    int d;
    d = (c) >= '0' && (c) <= '9' ? (c) - '0' : -1;
    if (d != -1) {
        return d;
    }

    d = (c) >= 'A' && (c) <= 'Z' ? (c) - 55 : -1;
    if (d != -1) {
        return d;
    }

    d = (c) >= 'a' && (c) <= 'z' ? (c) - 87 : -1;
    if (d != -1) {
        return d;
    } else
        return -1;
}

int myatoi_p(const char *s)
{
    int total = 0, neg = 0;
    unsigned char c;
    const char *s1 = s;
    do { if (!isspace(*s1++)) break; } while (1);
    s = s1 - 1;
    c = *s;
    if (c == '+') s++;
    if (c == '-') {
        s++;
        neg++;
    }
    do {
        c = *s++ - '0';
        if (c > 9) break;
        total = (total << 3) + total + total + c;
    }
    while (1);
    return (neg ? -total : total);
}

int myatoi(char *s)
{
    int total = 0;
    int c = *s++;

    while ((c = chartodigit(c)) != -1) {
        total = (10 * total) + c;
        c = *s++;
    }
    return total;
}

int hexatoi(char *s)
{
    int c = *s++;
    int total = 0;

    while ((c = hexchartodigit(c)) != -1) {
        total = (total << 4) + c;
        c = *s++;
    }
    return total;
}

int hexatoi_p(const char *s)
{
    int total = 0, neg = 0;
    unsigned char c;
    const char *s1 = s;
    do { if (!isspace(*s1++)) break; } while (1);
    s = s1 - 1;
    c = *s;
    if (c == '+') s++;
    if (c == '-') {
        s++;
        neg++;
    }
    do {
        c = *s++ - '0';
        if (c > 9) {
            c -= 7;
            if (c > 15) c -= 32;
            if (c > 15) break;
        }
        total = (total << 4) + c;
    }
    while (1);
    return (neg ? -total : total);
}

/*
 * test our functions
 */
int main()
{

    int value = 0;
    clock_t start, end;
    double total_time;
    int i = 0;
    int j = 0;
    int dummy = 0;

    /*----------------- hexatoi ----------------------*/
    printf("\ncalling ascii-hex-to-int 1000000 times\n");
    start = clock();
    for (i = 0; i < 1000000; i++) {
        dummy = hexatoi("fF12345");
    }
    end = clock();

    total_time = ((double) (end - start)) / CLOCKS_PER_SEC;
    printf("time for hexatoi   : %f\n", total_time);

    start = clock();
    for (i = 0; i < 1000000; i++) {
        dummy = hexatoi_p("fF12345");
    }
    end = clock();

    total_time = ((double) (end - start)) / CLOCKS_PER_SEC;
    printf("time for hexatoi_p : %f\n", total_time);

    start = clock();
    for (i = 0; i < 1000000; i++) {
        dummy = strtol("fF12345",0,16);
    }
    end = clock();

    total_time = ((double) (end - start)) / CLOCKS_PER_SEC;
    printf("time for strtol    : %f\n", total_time);

    /*----------------- atoi -----------------------*/
    printf("\ncalling ascii-int-to-int 1000000 times\n");

    start = clock();
    for (j = 0; j < 1000000; j++) {
        dummy = myatoi("28543680");
    }
    end = clock();

    total_time = ((double) (end - start)) / CLOCKS_PER_SEC;
    printf("time for myatoi   : %f\n", total_time);

    start = clock();
    for (j = 0; j < 1000000; j++) {
        dummy = myatoi_p("28543680");
    }
    end = clock();

    total_time = ((double) (end - start)) / CLOCKS_PER_SEC;
    printf("time for myatoi_p : %f\n", total_time);


    start = clock();
    for (i = 0; i < 1000000; i++) {
        dummy = atoi("28543680");
    }
    end = clock();

    total_time = ((double) (end - start)) / CLOCKS_PER_SEC;
    printf("time for atoi     : %f\n", total_time);

}

Share this post


Link to post
Share on other sites

thanx para for the codes.

tengah2 korek hdd tadi, jumpa this codes. looks pretty.

//==========================================
// LIBCTINY - Matt Pietrek 2001
// MSDN Magazine, January 2001
//==========================================
#include <stdlib.h>
#include <ctype.h>

extern "C" long __cdecl atol ( const char * pstr )
{
    // The current character.
    int  cCurr;
    // The running total.
    long lTotal;
    // Holds the '-' sign.
    int  iIsNeg;

    // Slide past any whitespace.
    while ( isspace ( *pstr ) )
    {
        ++pstr;
    }

    // Get the current character.
    cCurr = *pstr++;
    // Save the negative sign.
    iIsNeg = cCurr;
    if ( ( '-' == cCurr ) || ( '+' == cCurr ) )
    {
        // We have a sign, so skip it.
        cCurr = *pstr++;
    }

    // Initialize the total.
    lTotal = 0;

    // While we have digits, addem up.
    while ( isdigit ( cCurr ) )
    {
        // Add this digit to the total.
        lTotal = 10 * lTotal + ( cCurr - '0' );
        // Do the next character.
        cCurr = *pstr++;
    }

    // If we have a negative sign, convert the value.
    if ( '-' == iIsNeg )
    {
        return ( -lTotal );
    }
    else
    {
        return ( lTotal );
    }
}

extern "C" int __cdecl atoi ( const char * pstr )
{
    return ( (int)atol ( pstr ) );
}

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

×
×
  • Create New...