12

最近、就職面接の質問のサンプルを読みました。

整数を文字列に変換する関数を書きます。ライブラリ関数、つまり itoa() などにアクセスできないと仮定します...

これについてどう思いますか?

4

12 に答える 12

10

それを素早く突き刺す:(負の数を処理するように編集)

int n = INT_MIN;
char buffer[50];
int i = 0;

bool isNeg = n<0;

unsigned int n1 = isNeg ? -n : n;

while(n1!=0)
{
    buffer[i++] = n1%10+'0';
    n1=n1/10;
}

if(isNeg)
    buffer[i++] = '-';

buffer[i] = '\0';

for(int t = 0; t < i/2; t++)
{
    buffer[t] ^= buffer[i-t-1];
    buffer[i-t-1] ^= buffer[t];
    buffer[t] ^= buffer[i-t-1];
}

if(n == 0)
{
    buffer[0] = '0';
    buffer[1] = '\0';
}   

printf(buffer);
于 2010-10-20T21:17:11.787 に答える
8

itoaの実装については、Webを参照すると、良い例が得られます。これが1つで、最後に文字列を逆にすることを避けています。静的バッファに依存しているため、別の値に再利用する場合は注意が必要です。

char* itoa(int val, int base){

    static char buf[32] = {0};

    int i = 30;

    for(; val && i ; --i, val /= base)

        buf[i] = "0123456789abcdef"[val % base];

    return &buf[i+1];

}
于 2010-10-21T13:11:45.727 に答える
7

アルゴリズムは英語で見やすいです。

与えられた整数、例えば 123

  1. 10 で割る => 123/10。降伏、結果 = 12、剰余 = 3

  2. 30h を 3 に追加し、スタックにプッシュします (30h を追加すると、3 が ASCII 表現に変換されます)

  3. 結果が 10 未満になるまでステップ 1 を繰り返します

  4. 結果に 30h を追加し、スタックに格納します

  5. スタックには | の順に番号が含まれます。1 | 2 | 3 | ...

于 2010-10-20T22:01:12.263 に答える
1

すべての数字文字は ASCII 文字セット内で昇順であり、その間に他の文字が含まれていないことに注意してください。

/また、%演算子と演算子を繰り返し使用します。

文字列のメモリを取得する方法は、あなたが提供していない情報によって異なります。

于 2010-10-20T21:14:01.980 に答える
1

10 進数だとすると、次のようになります。

   int num = ...;
   char res[MaxDigitCount];
   int len = 0;
   for(; num > 0; ++len)
   {
      res[len] = num%10+'0';
      num/=10; 
   }
   res[len] = 0; //null-terminating

   //now we need to reverse res
   for(int i = 0; i < len/2; ++i)
   {
       char c = res[i]; res[i] = res[len-i-1]; res[len-i-1] = c;
   }   
于 2010-10-20T21:15:09.537 に答える
1

関数の実装はitoa()簡単な作業のように見えますが、実際には、正確なニーズに関連する多くの側面を処理する必要があります。インタビューでは、Google ( http://en.wikipedia.org/wiki/Itoa )にある解決策をコピーするのではなく、解決策への道のりについて詳細を説明することが期待されていると思います。

以下に、あなた自身または面接担当者に尋ねたい質問をいくつか示します。

  • 文字列を配置する場所 (malloced? ユーザーによって渡される? 静的変数?)
  • 署名付き番号をサポートする必要がありますか?
  • 浮動小数点をサポートする必要がありますか?
  • 10 ではなく他のベースをサポートする必要がありますか?
  • 入力チェックは必要ですか?
  • 出力文字列の長さは制限されていますか?

等々。

于 2010-10-20T21:22:21.290 に答える
1

この質問に出くわしたので、これに通常使用するコードに立ち寄ることにしました。

char *SignedIntToStr(char *Dest, signed int Number, register unsigned char Base) {
    if (Base < 2 || Base > 36) {
        return (char *)0;
    }
    register unsigned char Digits = 1;
    register unsigned int CurrentPlaceValue = 1;
    for (register unsigned int T = Number/Base; T; T /= Base) {
        CurrentPlaceValue *= Base;
        Digits++;
    }
    if (!Dest) {
        Dest = malloc(Digits+(Number < 0)+1);
    }
    char *const RDest = Dest;
    if (Number < 0) {
        Number = -Number;
        *Dest = '-';
        Dest++;
    }
    for (register unsigned char i = 0; i < Digits; i++) {
        register unsigned char Digit = (Number/CurrentPlaceValue);
        Dest[i] = (Digit < 10? '0' : 87)+Digit;
        Number %= CurrentPlaceValue;
        CurrentPlaceValue /= Base;
    }
    Dest[Digits] = '\0';
    return RDest;
}
#include <stdio.h>
int main(int argc, char *argv[]) {
    char String[32];
    puts(SignedIntToStr(String, -100, 16));
    return 0;
}

これにより、NULL が Dest に渡された場合にメモリが自動的に割り当てられます。それ以外の場合は、Dest に書き込みます。

于 2020-03-31T23:39:31.050 に答える
1

速いほど良いですか?

unsigned countDigits(long long x)
{
    int i = 1;
    while ((x /= 10) && ++i);
    return i;
}
unsigned getNumDigits(long long x)
{
    x < 0 ? x = -x : 0;
    return
        x < 10 ? 1 :
        x < 100 ? 2 :
        x < 1000 ? 3 :
        x < 10000 ? 4 :
        x < 100000 ? 5 :
        x < 1000000 ? 6 :
        x < 10000000 ? 7 :
        x < 100000000 ? 8 :
        x < 1000000000 ? 9 :
        x < 10000000000 ? 10 : countDigits(x);
}
#define tochar(x) '0' + x
void tostr(char* dest, long long x)
{
    unsigned i = getNumDigits(x);
    char negative = x < 0;
    if (negative && (*dest = '-') & (x = -x) & i++);
    *(dest + i) = 0;
    while ((i > negative) && (*(dest + (--i)) = tochar(((x) % 10))) | (x /= 10));
}


デバッグする場合は、条件 (命令) をwhile スコープ内のコード行に分割できます{}

于 2018-05-17T10:46:00.377 に答える
0

ソリューションより少し長い:

static char*
itoa(int n, char s[])
{
    int i, sign;

    if ((sign = n) < 0)  
        n = -n;        

    i = 0;

    do 
    {      
        s[i++] = n % 10 + '0';  
    } while ((n /= 10) > 0);   

    if (sign < 0)
        s[i++] = '-';

    s[i] = '\0';
    reverse(s);

    return s;
} 

逆行する:

int strlen(const char* str)
{
   int i = 0;
   while (str != '\0')
   {
       i++;
       str++;
   }

   return i;
}

static void
reverse(char s[])
{
    int i, j;
    char c;

    for (i = 0, j = strlen(s)-1; i<j; i++, j--) {
        c = s[i];
        s[i] = s[j];
        s[j] = c;
    }
}

そして、決定 davolno はここで長いですが、初心者にとっていくつかの便利な機能があります. お役に立てば幸いです。

于 2010-10-21T13:19:44.890 に答える
0

これは簡単なアプローチですが、これを理解したり言い換えたりせずにそのままにすると、先生はあなたがネットからコピーしただけだとわかると思います。

char *pru(unsigned x, char *eob)
{
    do { *--eob = x%10; } while (x/=10);
    return eob;
}

char *pri(int x, char *eob)
{
    eob = fmtu(x<0?-x:x, eob);
    if (x<0) *--eob='-';
    return eob;
}

さまざまな改善が可能です。特に、ワードより大きい整数サイズを最大intmax_t. これらの関数がどのように呼び出されることを意図しているかは、あなたに任せます。

于 2010-10-20T21:43:56.003 に答える