C语言 无需访问库即可将整数转换为字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3982320/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 06:45:11  来源:igfitidea点击:

Convert integer to string without access to libraries

cstringinttype-conversionitoa

提问by Nick Sinas

I recently read a sample job interview question:

我最近阅读了一个示例工作面试问题:

Write a function to convert an integer to a string. Assume you do not have access to library functions i.e., itoa(), etc...

编写一个将整数转换为字符串的函数。假设您无权访问库函数,即 itoa() 等...

How would you go about this?

你会怎么做?

采纳答案by John Boker

fast stab at it: (edited to handle negative numbers)

快速刺杀它:(编辑以处理负数)

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] = '
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];

}
'; 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] = '
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));
}
'; } printf(buffer);

回答by dnbwise

The algorithm is easy to see in English.

该算法在英文中很容易看到。

Given an integer, e.g. 123

给定一个整数,例如 123

  1. divide by 10 => 123/10. Yielding, result = 12 and remainder = 3

  2. add 30h to 3 and push on stack (adding 30h will convert 3 to ASCII representation)

  3. repeat step 1 until result < 10

  4. add 30h to result and store on stack

  5. the stack contains the number in order of | 1 | 2 | 3 | ...

  1. 除以 10 => 123/10。产量,结果 = 12,余数 = 3

  2. 将 30h 添加到 3 并压入堆栈(添加 30h 会将 3 转换为 ASCII 表示)

  3. 重复步骤 1 直到结果 < 10

  4. 将 30h 添加到结果并存储在堆栈中

  5. 堆栈包含按顺序排列的数字 | 1 | 2 | 3 | ...

回答by Benoit Thiery

A look on the web for itoa implementation will give you good examples. Here is one, avoiding to reverse the string at the end. It relies on a static buffer, so take care if you reuse it for different values.

在网上查看 itoa 实现会给你很好的例子。这是一个,避免在最后反转字符串。它依赖于静态缓冲区,因此如果将其重用于不同的值,请务必小心。

// 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) = '
#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>
'; } else { *dest = '-'; *myitoa_helper(dest + 1, a) = '
   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;
   }   
'; } return dest; } void myitoa_test(int a) { char s[100]; memset(s, 'x', sizeof s); printf("%11d <%s>\n", a, myitoa(s, a)); }

回答by Beyondo

The faster the better?

越快越好吗?

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;
}

If you want to debug, You can split the conditions (instructions) into
lines of code inside the while scopes {}.

如果要调试,可以将条件(指令)拆分
为 while 范围内的代码行{}

回答by chux - Reinstate Monica

Convert integer to string without access to libraries

无需访问库即可将整数转换为字符串

Convert the least significant digit to a character first and then proceed to more significant digits.

先将最低有效数字转换为字符,然后再转换为更高有效数字。



Normally I'd shift the resulting stringinto place, yet recursion allows skipping that step with some tight code.

通常我会将结果字符串移到位,但递归允许使用一些紧凑的代码跳过该步骤。

Using neg_ain myitoa_helper()avoids undefined behavior with INT_MIN.

使用neg_ainmyitoa_helper()避免了未定义的行为INT_MIN

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] = '##代码##';
    return RDest;
}
#include <stdio.h>
int main(int argc, char *argv[]) {
    char String[32];
    puts(SignedIntToStr(String, -100, 16));
    return 0;
}

Test code & output

测试代码和输出

##代码##

回答by eyalm

An implementation of itoa()function seems like an easy task but actually you have to take care of many aspects that are related on your exact needs. I guess that in the interview you are expected to give some details about your way to the solution rather than copying a solution that can be found in Google (http://en.wikipedia.org/wiki/Itoa)

itoa()函数的实现似乎是一项简单的任务,但实际上您必须处理与您的确切需求相关的许多方面。我想在面试中你应该提供一些关于解决方案的细节,而不是复制可以在谷歌找到的解决方案(http://en.wikipedia.org/wiki/Itoa

Here are some questions you may want to ask yourself or the interviewer:

以下是您可能想问自己或面试官的一些问题:

  • Where should the string be located (malloced? passed by the user? static variable?)
  • Should I support signed numbers?
  • Should i support floating point?
  • Should I support other bases rather then 10?
  • Do we need any input checking?
  • Is the output string limited in legth?
  • 字符串应该位于哪里(malloced?由用户传递?静态变量?)
  • 我应该支持签名数字吗?
  • 我应该支持浮点数吗?
  • 我应该支持其他基础而不是 10 个吗?
  • 我们需要任何输入检查吗?
  • 输出字符串是否有长度限制?

And so on.

等等。

回答by nategoose

I would keep in mind that all of the digit characters are in increasing order within the ASCII character set and do not have other characters between them.

我会记住,所有数字字符在 ASCII 字符集中都是按递增顺序排列的,并且它们之间没有其他字符。

I would also use the /and the%operators repeatedly.

我也会反复使用/%运算符。

How I would go about getting the memory for the string would depend on information you have not given.

我将如何获取字符串的内存取决于您未提供的信息。

回答by Armen Tsirunyan

Assuming it is in decimal, then like this:

假设它是十进制的,那么像这样:

##代码##

回答by R.. GitHub STOP HELPING ICE

Here's a simple approach, but I suspect if you turn this in as-is without understanding and paraphrasing it, your teacher will know you just copied off the net:

这是一个简单的方法,但我怀疑如果你在没有理解和解释的情况下按原样转换它,你的老师会知道你只是从网上复制的:

##代码##

Various improvements are possible, especially if you want to efficiently support larger-than-word integer sizes up to intmax_t. I'll leave it to you to figure out the way these functions are intended to be called.

各种改进都是可能的,特别是如果您想有效地支持高达intmax_t. 我会让你去弄清楚这些函数的调用方式。

回答by No Body

I came across this question so I decided to drop by the code I usually use for this:

我遇到了这个问题,所以我决定放弃我通常用于此的代码:

##代码##

This will automatically allocate memory if NULL is passed into Dest. Otherwise it will write to Dest.

如果将 NULL 传递给 Dest,这将自动分配内存。否则它将写入 Dest。