c - 面临编写我自己的和 my_itoa 以及我的 atoi 的挑战,它们应该在 C 中将整数更改为 ascii,反之亦然

标签 c string integer embedded ascii

我错过了在这里发帖,你总是教我很多东西!

因此,我有一个任务要编写自己的 2 个函数,以便为嵌入式系统从整数更改为 ASCII,然后从 ASCII 更改为整数,它们具有非常具体的功能:

这是我应该构建的提供的函数定义。它被放在一个 data.h 文件中:

#include <stdint.h>

uint8_t my_itoa(int32_t data, uint8_t * ptr, uint32_t base);

int32_t my_atoi(uint8_t * ptr, uint8_t digits, uint32_t base);

这些函数应该用于基本的数据操作,下面是这些函数将如何在另一个包含 data.c 的文件 course1.c 中使用:

digits = my_itoa( num, ptr, BASE_16);   
value = my_atoi( ptr, digits, BASE_16);  

和:

digits = my_itoa( num, ptr, BASE_10);
value = my_atoi( ptr, digits, BASE_10);

某些功能应该在这两个函数中:

  1. 他们应该支持 base 2 到 base 16。
  2. 不应使用字符串函数或库。
  3. 所有操作都需要使用指针算法而不是数组索引来执行。
  4. 函数需要处理签名数据。

对于 my_itoa:

  1. Integer-to-ASCII 需要将数据从标准整数类型转换为 ASCII 字符串。
  2. 您希望转换的数字作为带符号的 32 位整数传入。
  3. 将转换后的字符串复制到作为参数(ptr)传入的uint8_t*指针
  4. 带符号的 32 位数字将具有最大字符串大小(提示:以 2 为基数)。
  5. 您必须在转换后的 C 字符串的末尾放置一个空终止符
  6. 函数应返回转换后数据的长度(包括负号)。示例 my_itoa(ptr, 1234, 10) 应返回长度为 5 的 ASCII 字符串(包括空终止符)。

对于 my_atoi:

  1. ASCII-to-Integer 需要将数据从 ASCII 表示的字符串转换回整数类型。
  2. 要转换的字符串作为 uint8_t * 指针 (ptr) 传入。
  3. 字符集中的位数作为 uint8_t 整数(位数)传入。
  4. 应返回转换后的 32 位有符号整数。

经过我对这个话题的研究:Writing my own atoi function

我能够编写这段代码,我的 data.c:

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


int main(){

        return 0;
}


uint8_t my_itoa(int32_t data, uint8_t * ptr, uint32_t base)
{
        return *ptr;
};


int32_t my_atoi(uint8_t * ptr, uint8_t digits, uint32_t base)
{
        const char* str= ptr;
        uint8_t len = strlen(str);
        str = (uint8_t*) malloc(len * sizeof(uint8_t));

        while (*str != '\0')
        {
                uint8_t a;
                a = *str -'0';
                *ptr = a;
                str++;
                ptr++;
        }
        str = str - len;
        ptr = ptr -len;

        return *ptr;
};

据我了解,这部分删除了空字符:

a = *str -'0';

此代码有一个主要问题,即当我以这种方式编译它时,我在 my_atoi 中得到指针在 sginedness 上不同并且指针赋值在符号上不同:

src/data.c: In function ‘my_atoi’:
src/data.c:20:19: error: pointer targets in initialization differ in 
signedness [-Werror=pointer-sign]
  const char* str= ptr;
                   ^~~
src/data.c:22:6: error: pointer targets in assignment differ in 
signedness [-Werror=pointer-sign]
  str = (uint8_t*) malloc(len * sizeof(uint8_t));
      ^

当我将其编辑为:

uint8_t len = strlen(str);

我得到的错误是,在传递 strlen 的参数 1 时指针目标的大小不同,并且在 string.h strlen 定义中需要一个 const char*:

src/data.c: In function ‘my_atoi’:
src/data.c:21:19: error: pointer targets in passing argument 1 of 
‘strlen’ differ in signedness [-Werror=pointer-sign]
  int len = strlen(str);
                   ^~~
In file included from src/data.c:3:0:
/usr/include/string.h:384:15: note: expected ‘const char *’ but 
argument is of type ‘unsigned char *’
extern size_t strlen (const char *__s)
              ^~~~~~
src/data.c:22:6: error: pointer targets in assignment differ in 
signedness [-Werror=pointer-sign]
  str = (char*) malloc(len * sizeof(char));
      ^

还有我需要一起摆脱 strlen 和 string.h 的事实。喜欢这里:Converting ASCII to Hex and vice versa - strange issue所以它不是很有用。其实我看不懂里面的代码。

另一个挑战是确定函数(第 3 个输入)的输入变量应该是 BASE_10、BASE_16 或 BASE_2 等...,变量应该如何:

uint32_t base

这是一个 int,存储这个值“BASE_10”以便在 if 条件中比较它?转换为不同基数的基数是什么?我应该如何处理它们?

我在许多不同的领域都被困在这个挑战的答案上,在哪里可以了解更多信息,最大字符串大小的要求是什么,我应该如何处理签名数据。我正在寻求帮助。抱歉问了这么长的问题,但我需要包括所有因素。


EDIT 像这样编辑代码:

uint8_t* str= ptr;
uint8_t len = strlen((const char *)str);

关注这个主题: cast unsigned char * (uint8_t *) to const char *

我现在没有报错了,但是还是需要彻底去掉string.h

最佳答案

什么?

  str = (uint8_t*) malloc(len * sizeof(uint8_t));
  while (*str != '\0')

这段 my_atoi() 代码毫无意义。代码分配内存,其内容未知 - 然后立即尝试测试它们?

不需要内存分配,也不需要 strlen()

字符转十进制值

“我理解这部分删除了空字符:a = *str -'0';” --> 不完全是。当*str 是数字字符时,*str -'0' 将字符编码值(通常是ASCII)转换为其数值(如0 到9)。

*str -'0' 不适用于 'a''F' 等十六进制数字。

备选

相反,遍历 ptr 并缩放运行总和。

以下不符合 2 个编码目标,我将其作为子问题留给 OP 处理。

** 不应使用字符串函数或库。
** 函数需要处理签名数据。

.

#include <ctype.h>

// Convert 1 digit
static int value(int ch) {
  if (isdigit(ch)) {
    return ch - '0';
  }
  if (isxdigit(ch)) {
    ch = tolower(ch);
    const char *xdigits = "abcdef";
    return strchr(xdigits, ch) - xdigits  + 10;
  }
  return INT_MAX; // non-digit
}

int32_t my_atoi(uint8_t * ptr, uint8_t digits, uint32_t base) {
  int32_t sum = 0;
  while (*ptr) {
    sum *= base;
    sum += value(*ptr++);
  }
  return sum;
}

更好的代码会检测非数字输入、溢出、无转换等。其他未显示的注意事项包括处理 '-' 符号、验证范围内的基数。

int32_t my_atoi(uint8_t * ptr, uint8_t digits, uint32_t base) {
  int32_t sum = 0;
  while (isspace(*ptr)) ptr++;  // skip leading white space
  if (*ptr == '+')  ptr++;      // Allow optional leading `+`
  bool digit_found = false;

  while (*ptr) {
    unsigned digit = value(*ptr++);
    if (digit >= base) {
      return INT_MIN; // TBD signal unexpected digit
    }
    if (sum >= INT_MAX/base && (sum > INT_MAX/base || digit > INT_MAX%base)) {
      // Overflow
      return INT_MIN; // TBD signal OF
    }
    sum *= base;
    sum += digit;
    digit_found = true;
  }

  if (*str) {
    sum = INT_MIN; // TBD signal unexpected junk at the end
  }
  if (!digit_found) {
    sum = INT_MIN; // TBD signal no digits
  }
  return sum;
}

my_itoa()

有关 my_itoa() 的帮助,请查看 What is the proper way of implementing a good “itoa()” function? .它确实有一个很好的答案 -某处。

关于c - 面临编写我自己的和 my_itoa 以及我的 atoi 的挑战,它们应该在 C 中将整数更改为 ascii,反之亦然,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53091559/

相关文章:

c - 是否可以使用回调类型定义来定义函数?

c - 为什么我在这里 fork 超过 5 次?

php - 在php中求和字符串,转换为整数

c - 将输入的字符存储在数组中

string - Ada 字符串比较

java - 对于更大的数字,有什么替代 int 的方法?

mysql - 将 4 字节 `binary(4)` 转换为 MySQL 中的无符号整数

c - 为什么 a.out 不是机器语言?

c - 消息队列给了我一个无效的参数

c - 就地反转字符串时出现问题