我错过了在这里发帖,你总是教我很多东西!
因此,我有一个任务要编写自己的 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);
某些功能应该在这两个函数中:
- 他们应该支持 base 2 到 base 16。
- 不应使用字符串函数或库。
- 所有操作都需要使用指针算法而不是数组索引来执行。
- 函数需要处理签名数据。
对于 my_itoa:
- Integer-to-ASCII 需要将数据从标准整数类型转换为 ASCII 字符串。
- 您希望转换的数字作为带符号的 32 位整数传入。
- 将转换后的字符串复制到作为参数(ptr)传入的uint8_t*指针
- 带符号的 32 位数字将具有最大字符串大小(提示:以 2 为基数)。
- 您必须在转换后的 C 字符串的末尾放置一个空终止符
- 函数应返回转换后数据的长度(包括负号)。示例 my_itoa(ptr, 1234, 10) 应返回长度为 5 的 ASCII 字符串(包括空终止符)。
对于 my_atoi:
- ASCII-to-Integer 需要将数据从 ASCII 表示的字符串转换回整数类型。
- 要转换的字符串作为 uint8_t * 指针 (ptr) 传入。
- 字符集中的位数作为 uint8_t 整数(位数)传入。
- 应返回转换后的 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/