簡體   English   中英

如何修復我的`itoa`實現,使其不輸出反向輸出?

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

我想將整數轉換為C中的數字字符字符串。

我嘗試使用itoa ,但是它是非標准的,不是我的C庫提供的。

我嘗試實現自己的itoa ,但無法正常工作:

#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

我希望它的輸出是: 1011010

如何解決此問題?


類似問題


我已經看到了這個問題: 是否有一個printf轉換器可以二進制格式打印?

我不希望printf格式說明符將整數打印為二進制,我想將二進制轉換為字符串。

我已經看到了這個問題: 使用C以二進制表示形式打印int

盡管答案確實將整數轉換為二進制數字字符串,但這是它唯一能做的。


限制


我想itoa能夠與其它的工作base S,如108等,並且打印正確地(即12345翻譯為"12345" ,而不是"11000000111001" )。

我不想使用printfsprintf來執行此操作。

我不在乎字符串的長度,只要結果正確即可。

我不希望將整數轉換為數字字符以外的ASCII字符,但base大於10的情況除外,在這種情況下,字符可能是字母數字。

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

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

可能有一個稱為nitoa的函數具有此原型,並返回保存itoa結果所需的字符數:

size_t nitoa(int val, int base);

如何修復itoa實現,使其不輸出反向輸出?

從右到左形成字符串,而不是反轉字符串。 @ user3386109中的 #4


我建議助手功能也要接收一定的尺寸。

#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))

現在您可以多次調用它。

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

注意: sizeof(c)*8+1對於以INT_MIN為底的2來說太小了。

此解決方案適用於我:

#include <errno.h>
#include <stdlib.h>
#include <string.h>

#define itoa lltoa
#define utoa ulltoa
#define ltoa lltoa
#define ultoa ulltoa
#define nitoa nlltoa
#define nutoa nulltoa
#define nltoa nlltoa
#define nultoa nulltoa

#define BASE_BIN 2
#define BASE_OCT 8
#define BASE_DEC 10
#define BASE_HEX 16
#define BASE_02Z 36

__extension__
char *ulltoa(unsigned long long val, char *buf, int base)
{
    int remainder;
    char c, *tmp = buf;

    if(base < BASE_BIN)
    {
        errno = EINVAL;
        return NULL;
    }

    do {
        remainder = val % base;
        if(remainder >= BASE_DEC) c = 'a' - BASE_DEC;
        else c = '0';
        *tmp++ = remainder + c;
        val /= base;
    } while(val);

    *tmp = 0;
    return strrev(buf);
}

__extension__
size_t nulltoa(unsigned long long val, int base)
{
    size_t size = 0;

    if(base < BASE_BIN)
    {
        errno = EINVAL;
        return 0;
    }

    if(!val) size++;

    for( ; val; val /= base, size++ );

    return size;
}

__extension__
char *lltoa(long long val, char *buf, int base)
{
    if(val < 0 && base > BASE_BIN)
    {
         val = -val;
         *buf++ = '-';
    }

    return ulltoa(val, buf, base);
}

__extension__
size_t nlltoa(long long val, int base)
{
    size_t size = 0;

    if(val < 0 && base > BASE_BIN)
    {
        val = -val;
        size++;
    }

    return size + nulltoa(val, base);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM