增加一个算术类型的值,在C中存储在一个char数组中

Increase the value of an arithmetic type, stored in a char array in C

我对相互通信的小型设备进行编程,我需要用唯一 ID 标记每个动作(并且有很多)。由于架构的原因,我不能使用任何大于 int(4 字节)的东西。所以我想到了将 ID 存储为一个 char 数组,每次我在这样的场景中调用某个函数时我都会递增它:

void increaseIDByOne(char *ID){
  //increase "string"
}

int main (int argc, char *argv[]){
  char ID [12] = "00000000000";
  while(true){
    doStuff(&ID); 
    increaseIDByOne(&ID);
  }
}

我遇到的问题是,我不知道如何在不将 "string" 临时转换为算术类型的情况下对其进行操作。在 ID 达到值“99999999999”后,系统应该有一个解决方案,通过为数字分配更多 space 或使用其他一些解决方案来防止溢出或重复 ID。 我希望你能给我提供正确的想法,这样我就可以找到解决问题的方法。

没有负数使问题变得非常简单。只要有可能溢出,就简单地使用 realloc

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

void increaseIDByOne(char *ID){
  //increase "string"
  size_t len = strlen(ID);
  int all9 = 1;
  //int carry = 0;
  for(size_t i=0;i<len;i++)
  {
    if(ID[i]=='9')
        continue;
    else
    {
        all9 = 0;
        break;
    }
  }
  if(all9)
  {
    ID = realloc(ID, len + 2);
    ID[len] = '0';
  }
  len = strlen(ID);
  for(size_t i=len-1;i>=0;i--)
  {
    if(ID[i]=='9')
    {
        ID[i] = '0';
    }
    else if(ID[i]<'9')
    {
        ID[i]++;
        return;
    }
    //printf("%c\n", ID[i]);
  }
}

int main (int argc, char *argv[]){
  char *ID = malloc(12);
  strcpy(ID, "99999999995");
  while(1){
    //doStuff(&ID); 
    increaseIDByOne(ID);
    printf("%s\n",ID);
  }
}

输出:

99999999996
99999999997
99999999998
99999999999
999999999991
999999999992
999999999993
999999999994
999999999995
999999999996
999999999997
999999999998
999999999999
9999999999991
9999999999992
9999999999993
9999999999994
9999999999995
9999999999996
9999999999997
9999999999998
9999999999999
99999999999991
99999999999992
99999999999993
99999999999994
99999999999995
99999999999996
99999999999997
99999999999998
99999999999999
and so on...

这是一种可能的实现方式:

#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>

typedef struct id {
    char   *str;
    size_t strLen;
} id_s;

#define ID_CONSTRUCTOR {.str    = NULL,\
                        .strLen = 0}

void Id_Constructor(id_s *self)
{
    id_s tmp = ID_CONSTRUCTOR;

    *self = tmp;
}

void Id_Destructor(id_s *self)
{
    free(self->str);
}

bool Id_Init(id_s *self, size_t nbDigit)
{
    // Checking (assert ?)
    if (nbDigit == 0) {
        fprintf(stderr, "%s : nbDigit can't be 0.\n", __func__);
        return (false);
    }
    // Memory allocation
    free(self->str);
    if (!(self->str = malloc(nbDigit + 1))) {
        fprintf(stderr, "%s : malloc(nbDigit + 1) : nbDigit=%zu, errno='%s'.\n", __func__, nbDigit, strerror(errno));
        return (false);
    }
    // initialization
    self->strLen = nbDigit;

    self->str[0] = self->strLen == 1 ? '0' : '1';
    for (size_t i = 1; i < self->strLen; ++i) {
        self->str[i] = '0';
    }
    self->str[self->strLen] = '[=10=]';

    return (true);
}

bool Id_Increment(id_s *self)
{
    char *idTmp;

    for (int i = self->strLen - 1; i >= 0; --i) {
        if (self->str[i] == '9') {
            self->str[i] = '0';
        } else {
            ++self->str[i];
            return (true);
        }
    }

    if (!(idTmp = realloc(self->str, self->strLen + 2))) {
        fprintf(stderr, "%s : realloc(self->str, self->strLen + 2) : self->str='%s', self->strLen=%zu, errno='%s'.\n", __func__, self->str, self->strLen, strerror(errno));
        return (false);
    }
    self->str = idTmp;
    self->str[0] = '1';
    self->str[self->strLen] = '0';
    self->str[self->strLen + 1] = '[=10=]';
    ++self->strLen;
    return (true);
}

int main (void)
{
    id_s id = ID_CONSTRUCTOR;

    if (!Id_Init(&id, 1)) {
        printf("Unable to initialize id.\n");
        return (1);
    }

    printf("%s\n", id.str);
    for (int i = 1; i < 101; ++i){
        Id_Increment(&id);
        printf("%s\n", id.str);
    }

    Id_Destructor(&id);
    return (0);
}