我最近阅读了一份面试问题样本:
编写一个转换整数的函数 到一个字符串。假设你没有 访问图书馆功能,即, itoa()等...
你会怎么做?
答案 0 :(得分:9)
快速刺伤:(编辑以处理负数)
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);
答案 1 :(得分:6)
该算法很容易用英语看到。
给定一个整数,例如123
除以10 =&gt; 10分之123。屈服,结果= 12,余数= 3
将30h添加到3并推入堆栈(添加30h将3转换为ASCII表示)
重复步骤1直到结果&lt; 10
将30小时添加到结果并存储在堆栈
堆栈按|的顺序包含数字1 | 2 | 3 | ...
答案 2 :(得分:3)
在web上查看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];
}
答案 3 :(得分:1)
我要记住,所有数字字符在ASCII字符集中的顺序递增,并且它们之间没有其他字符。
我还会反复使用/
和%
运算符。
如何获取字符串的内存取决于你没有给出的信息。
答案 4 :(得分:1)
假设它是十进制的,那么就像这样:
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;
}
答案 5 :(得分:1)
itoa()
函数的实现似乎是一项简单的任务,但实际上您必须处理与您的确切需求相关的许多方面。我想在访谈中你应该提供一些关于你的解决方案的细节,而不是复制一个可以在谷歌找到的解决方案(http://en.wikipedia.org/wiki/Itoa)
以下是您可能想问自己或面试官的一些问题:
等等。
答案 6 :(得分:1)
将整数转换为字符串,而无需访问库
首先将最低有效数字转换为字符,然后再转换为较高有效数字。
通常我会将生成的 string 移到适当的位置,但是递归允许使用一些紧凑的代码跳过该步骤。
在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>
答案 7 :(得分: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
的大于字的整数大小。我会留给你来弄清楚这些函数的调用方式。
答案 8 :(得分: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这里的决定对于初学者来说是一些有用的功能。我希望你会有所帮助。
答案 9 :(得分:0)
越快越好?
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范围{}
内的代码行。
答案 10 :(得分:0)
我遇到了这个问题,因此决定放弃我通常用于此的代码:
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,它将自动分配内存。否则它将写入目标。
答案 11 :(得分:0)
这是我能想到的最短的函数:
正确处理所有带符号的32位整数,包括0,MIN_INT32,MAX_INT32。
返回一个可以立即打印的值,例如:printf("%s\n", GetDigits(-123))
请评论以寻求改进:
static const char LARGEST_NEGATIVE[] = "-2147483648";
static char* GetDigits(int32_t x) {
char* buffer = (char*) calloc(sizeof(LARGEST_NEGATIVE), 1);
int negative = x < 0;
if (negative) {
if (x + (1 << 31) == 0) { // if x is the largest negative number
memcpy(buffer, LARGEST_NEGATIVE, sizeof(LARGEST_NEGATIVE));
return buffer;
}
x *= -1;
}
// storing digits in reversed order
int length = 0;
do {
buffer[length++] = x % 10 + '0';
x /= 10;
} while (x > 0);
if (negative) {
buffer[length++] = '-'; // appending minus
}
// reversing digits
for (int i = 0; i < length / 2; i++) {
char temp = buffer[i];
buffer[i] = buffer[length-1 - i];
buffer[length-1 - i] = temp;
}
return buffer;
}