如何修复我的`itoa`实现,使其不输出反向输出? [英] How do I fix my `itoa` implementation so it doesn't print reversed output?

查看:115
本文介绍了如何修复我的`itoa`实现,使其不输出反向输出?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将整数转换为C语言中的数字字符字符串.

I want to convert an integer into a string of numeric characters in C.

我尝试使用itoa,但这是非标准的,不是我的C库提供的.

I've tried using itoa, but it's non-standard and not provided by my C library.

我尝试实现自己的itoa,但无法正常工作:

I tried to implement my own itoa, but it's not working properly:

#include <stdlib.h>
#include <stdio.h>

char *itoa(int val, char *buf, int base)
{
    size_t ctr = 0;
    for( ; val; val /= base )
    {
        buf[ctr++] = '0' + (val % base);
    }
    buf[ctr] = 0;
    return buf;
}

int main(void)
{
    unsigned char c = 201;
    char *buf = malloc(sizeof(c)*8+1);
    itoa(c, buf, 2);
    puts(buf);
    free(buf);
}

它提供反向输出.

例如,如果c'A'并且base2,则输出为:0101101

For example, if c is 'A' and base is 2, the output is this: 0101101

我想要的输出是这样的:1011010

The output I want it to be is this: 1011010

如何解决此问题?

我已经看到了以下问题:是有一个printf转换器可以二进制格式打印吗?

I've already seen this question: Is there a printf converter to print in binary format?

我不希望printf格式说明符将整数打印为二进制,我想将二进制转换为字符串.

I do not want a printf format specifier to print an integer as binary, I want to convert the binary to a string.

我已经看到了以下问题:以二进制形式打印int用C

I've already seen this question: Print an int in binary representation using C

尽管答案确实将整数转换为二进制数字字符串,但这是它唯一可以做的事情.

Although the answer does convert an integer into a string of binary digits, that's the only thing it can do.

我希望itoa能够与其他base(例如108等)一起使用并正确打印(即12345转换为"12345"而不是).

I want itoa to be able to work with other bases, such as 10, 8, etc. and print correctly (i.e. 12345 translates to "12345" and not to "11000000111001").

我不想使用printfsprintf来做到这一点.

I do not want to use printf or sprintf to do this.

我不在乎字符串的长度,只要结果正确即可.

I do not care about the length of the string as long is the result is correct.

我不想将整数转换为数字字符以外的ASCII字符,但base大于10的情况除外,在这种情况下,这些字符可能是字母数字.

I do not want to convert the integer into ASCII characters other than numeric ones, with the exception of bases greater than 10, in which case the characters may be alphanumeric.

答案必须完全符合此原型:

The answer must fit this prototype exactly:

char *itoa(int val, char *buf, int base);

可能有一个名为nitoa的函数具有此原型,并返回保存itoa结果所需的字符数:

There may be a function called nitoa that has this prototype and returns the number of characters required to hold the result of itoa:

size_t nitoa(int val, int base);

推荐答案

如何修复我的itoa实现,这样它就不会打印反向输出?

How do I fix my itoa implementation so it doesn't print reversed output?

从右到左形成字符串,而不是反转字符串. #4 of

Rather than reverse the string, form it right-to-left. #4 of @user3386109

我建议helper函数也要接收一个大小.

I recommend the helper function also receives in a size.

#include <limits.h>

char* itostr(char *dest, size_t size, int a, int base) {
  // Max text needs occur with itostr(dest, size, INT_MIN, 2)
  char buffer[sizeof a * CHAR_BIT + 1 + 1]; 
  static const char digits[36] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

  if (base < 2 || base > 36) {
    fprintf(stderr, "Invalid base");
    return NULL;
  }

  // Start filling from the end
  char* p = &buffer[sizeof buffer - 1];
  *p = '\0';

  // Work with negative `int`
  int an = a < 0 ? a : -a;  

  do {
    *(--p) = digits[-(an % base)];
    an /= base;
  } while (an);

  if (a < 0) {
    *(--p) = '-';
  }

  size_t size_used = &buffer[sizeof(buffer)] - p;
  if (size_used > size) {
    fprintf(stderr, "Scant buffer %zu > %zu", size_used , size);
    return NULL;
  }
  return memcpy(dest, p, size_used);
}

然后使用复合文字来提供记忆.

// compound literal C99 or later
#define INT_STR_SIZE (sizeof(int)*CHAR_BIT + 2)
#define MY_ITOA(x, base) itostr((char [INT_STR_SIZE]){""}, INT_STR_SIZE, (x), (base))

现在您可以多次调用它.

Now you can call it multiple times.

int main(void) {
  printf("%s %s %s %s\n", MY_ITOA(INT_MIN,10), MY_ITOA(-1,10), MY_ITOA(0,10), MY_ITOA(INT_MAX,10));
  printf("%s %s\n", MY_ITOA(INT_MIN,2), MY_ITOA(INT_MIN,36));
  return (0);
}

输出

-2147483648 -1 0 2147483647
-10000000000000000000000000000000 -ZIK0ZK


注意:对于INT_MIN(基数2),sizeof(c)*8+1太小了.


Note: sizeof(c)*8+1 is one too small for INT_MIN, base 2.

这篇关于如何修复我的`itoa`实现,使其不输出反向输出?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆