我最近看到一道面试题:
编写一个将整数转换为字符串的函数。假设您没有访问库函数(如itoa()等)…
你会怎么做呢?
我最近看到一道面试题:
编写一个将整数转换为字符串的函数。假设您没有访问库函数(如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);
INT_MIN
。 - schot在网络上搜索itoa实现的例子,会给您提供很好的示例。这里是一个示例,它避免了在最后反转字符串的操作。它依赖于静态缓冲区,因此请注意如果您想为不同的值重复使用它。
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];
}
这个算法很容易用英语来描述。
给定一个整数,例如123
将其除以10 => 123/10。得到结果为12和余数为3
将3加上30h并压入堆栈中(加上30h将3转换为ASCII表示)
重复步骤1直到结果小于10
将结果加上30h并存储在堆栈中
堆栈按顺序包含数字 | 1 | 2 | 3 | ...
'0'
是将代码与 ASCII 绑定在一起——您假定 '0'..'9' 依次排列。添加 0x30 可以生成 ASCII 输出,而不考虑编译器的代码集。如果编译器的代码集是 ASCII,则添加 '0' 会产生相同的输出,否则可能会产生乱码输出。话虽如此,如果我的编译器不使用字符常量的 ASCII 值,我会更换它! - Nicholas Wilsonunsigned 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));
}
{}
。char tochar(unsigned short from)
可以被优化:inline char tochar(unsigned char from) { if (from > 9) return '0'; return '0' + from; }
在这个特定的例子中,可以删除边界情况,因为你确定将始终传递从 0 到 9 的数字给 tochar
。 - Cristiancalloc
,这显然需要一个库,我还记得~所以,谢谢你。现在它甚至更好了。 :) - Beyondo我看到了这个问题,所以决定提供我通常用于此的代码:
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;
}
假设它是十进制的,那么就像这样:
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;
}
MaxDigitCount
需要设置为 MaxDigitCountPlusTwo
来考虑一元减号和空终止符。 - James McNellis将整数转换为字符串,无需访问库
首先将最低位数字转换为字符,然后再处理更高位的数字。
// 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>
itoa()
函数的实现似乎是一项容易的任务,但实际上你必须注意许多与你的确切需求相关的方面。我猜想在面试中,你应该详细说明解决方案的方式,而不是复制可以在Google(http://en.wikipedia.org/wiki/Itoa)中找到的解决方案。
以下是您可能想要问自己或面试官的一些问题:
等等。
//Fixed the answer from [10]
#include <iostream>
void CovertIntToString(unsigned int n1)
{
unsigned int n = INT_MIN;
char buffer[50];
int i = 0;
n = n1;
bool isNeg = n<0;
n1 = isNeg ? -n1 : n1;
while(n1!=0)
{
buffer[i++] = n1%10+'0';
n1=n1/10;
}
if(isNeg)
buffer[i++] = '-';
buffer[i] = '\0';
// Now we must reverse the string
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("%s", buffer);
}
int main() {
unsigned int x = 4156;
CovertIntToString(x);
return 0;
}
atoi()
更有趣,因为你需要处理前导空格、一元加或减以及正负溢出(等等)。 - James McNellis