ライブラリにアクセスせずに整数を文字列に変換します
-
09-10-2019 - |
質問
私は最近、サンプル就職のインタビューの質問を読みました:
関数を書き込み、整数を文字列に変換します。ライブラリ機能にアクセスできないと仮定しますIE、ITOA()など...
これについてどうやって行きますか?
解決
それでの速い刺し:(負の数を処理するために編集)
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);
他のヒント
アルゴリズムは英語で簡単に見ることができます。
整数が与えられた場合、例えば123
10 => 123/10で割る。降伏、結果= 12および残り= 3
30Hから3を追加してスタックを押します(30Hを追加すると3をASCII表現に変換します)
結果<10までステップ1を繰り返します
結果を30時間追加し、スタックに保存します
スタックには、|の順に数値が含まれています1 | 2 | 3 | ...
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];
}
すべての数字文字がASCII文字セット内で順序を増やしており、それらの間に他の文字がないことを心に留めておいてください。
私も使用します /
そしてその%
繰り返しオペレーター。
文字列のメモリを取得する方法は、与えられていない情報によって異なります。
それが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;
}
の実装 itoa()
機能は簡単な作業のように思えますが、実際には、正確なニーズに関連する多くの側面を処理する必要があります。インタビューでは、Googleで見つけることができるソリューションをコピーするのではなく、ソリューションへの道についての詳細を提供することが期待されていると思います。http://en.wikipedia.org/wiki/itoa)
自分自身やインタビュアーに尋ねたいと思うかもしれない質問がいくつかあります。
- 文字列はどこに配置する必要がありますか(マロックされていますか?ユーザーが通過しますか?静的変数?)
- 署名番号をサポートする必要がありますか?
- フローティングポイントをサポートする必要がありますか?
- 10ではなく他のベースをサポートする必要がありますか?
- 入力チェックが必要ですか?
- 出力文字列はlegが制限されていますか?
等々。
ライブラリにアクセスせずに整数を文字列に変換します
最も重要な数字を最初にキャラクターに変換し、より重要な数字に進みます。
通常、結果をシフトします ストリング 所定の位置に、しかし再帰により、いくつかのタイトなコードでそのステップをスキップできます。
使用 neg_a
の myitoa_helper()
未定義の動作を回避します INT_MIN
.
// Return character one past end of character digits.
static char *myitoa_helper(char *dest, int neg_a) {
if (neg_a <= -10) {
dest = myitoa_helper(dest, neg_a / 10);
}
*dest = (char) ('0' - neg_a % 10);
return dest + 1;
}
char *myitoa(char *dest, int a) {
if (a >= 0) {
*myitoa_helper(dest, -a) = '\0';
} else {
*dest = '-';
*myitoa_helper(dest + 1, a) = '\0';
}
return dest;
}
void myitoa_test(int a) {
char s[100];
memset(s, 'x', sizeof s);
printf("%11d <%s>\n", a, myitoa(s, a));
}
テストコードと出力
#include "limits.h"
#include "stdio.h"
int main(void) {
const int a[] = {INT_MIN, INT_MIN + 1, -42, -1, 0, 1, 2, 9, 10, 99, 100,
INT_MAX - 1, INT_MAX};
for (unsigned i = 0; i < sizeof a / sizeof a[0]; i++) {
myitoa_test(a[i]);
}
return 0;
}
-2147483648 <-2147483648>
-2147483647 <-2147483647>
-42 <-42>
-1 <-1>
0 <0>
1 <1>
2 <2>
9 <9>
10 <10>
99 <99>
100 <100>
2147483646 <2147483646>
2147483647 <2147483647>
簡単なアプローチは次のとおりですが、理解して言い換えずにこれをAS-OSで回すと、先生はあなたがネットからコピーしたことを知っているでしょう。
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
. 。これらの機能が呼び出されることを意図している方法を把握するために、私はあなたに任せます。
ソリューションよりわずかに長い:
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 Longの決定は初心者にとって有用な機能ですが。お役に立てば幸いです。
速いほど良いですか?
unsigned int findDigits(long long x)
{
int i = 1;
while ((x /= 10) && ++i);
return i;
}
// return the number of digits in x.
unsigned int digits(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 : findDigits(x);
}
char tochar(unsigned short from)
{
return from == 0 ? '0' :
from == 1 ? '1' : from == 1 ? '1' : from == 2 ? '2' :
from == 3 ? '3' : from == 4 ? '4' : from == 5 ? '5' :
from == 6 ? '6' : from == 7 ? '7' : from == 8 ? '8' :
from == 9 ? '9' : '\0';
}
char * tostring(long long from)
{
unsigned char negative = from < 0;
unsigned int i = digits(from);
char* to = (char*)calloc(1, i + negative);
if (negative && (*to = '-') & (from = -from) & i++);
*(to + i) = 0;
while ((i>0+negative) && (*(to + (--i)) = tochar(((from) % 10))) | (from /= 10));
return to;
}
デバッグしたい場合は、条件(命令)を分割できます
while scopes内のコードの行 {}
.