在 C 中将 "char" 转换为 "int" 的逻辑

LOGIC of Converting a "char" into an "int" in C

各位!

请帮我理解以下问题... 所以我将有一个字符串类型的音符输入,看起来像 "A5" 或 "G#2" 或 "Cb4" 等。我需要提取一个八度索引,这是最后一个数字“5 “或“2”或“4”...提取后我需要它作为 int 类型。

所以我这样做了:

string note = get_string("Input: ");
int octave = atoi(note[strlen(note) - 1]);
printf("your octave is %i \n", octave);

但是它给了我一个错误"error: incompatible integer to pointer conversion passing 'char' to parameter of type 'const char *'; take the address with & [-Werror,-Wint-conversion]"

然后我尝试从函数中去掉数学运算,然后这样做:

int extnum = strlen(note) - 1;
int octave = atoi(note[extnum]);

它也没有用。所以我研究了 atoi 函数,但我不明白...

  1. ATOI 需要一个字符串 (CHECK)
  2. 将其转换为整数,而不是 ASCII 含义(检查)
  3. atoi 函数库(检查)

基本上我在问什么"take n-th character of that string and make it an int"。

在谷歌搜索一段时间后,我发现了另一个代码示例,其中一个人使用带有此符号“&”的 atoi。 所以我这样做了:

int octave = atoi(&note[strlen(note) - 1]);

成功了!但我不明白为什么它与 & 符号一起工作而没有它就不能工作......因为没有它它总是有效!有一百万次我给出了一个像“5”这样的单字符字符串,只是使用了 atoi 并且它完美地工作......

请帮帮我,为什么在这种情况下它表现得如此奇怪?

函数atoi将指向字符数组的指针作为输入参数(const char*)。当您调用 note[strlen(note) - 1] 时,这是单个字符 (char),为了使 atoi 工作,您需要提供指针。您可以通过添加 & 来实现。这样就可以了,因为在那个单个数字之后有一个终止字符串的空字符 [=17=] - 因为您的原始字符串是以空值终止的。

但是请注意,这样做并不是一个好主意:

char a = '7';
int b = atoi(&a);

因为无法确定内存中的下一个字节是什么(跟在属于 a 的字节之后),但是该函数无论如何都会尝试读取它,这可能会导致未定义的行为.

最后一个角色是……好角色!不是字符串。因此,通过添加 & 符号,您使其成为指向字符 (char*)!

的指针

您也可以试试这个代码:

char a = '5';
int b = a - '0';

给你 5 的 ASCII 码减去 0

的 ASCII 码

C 没有原生字符串类型。字符串通常表示为 char 数组或指向 char 的指针。

假设 string 只是 char * 的类型定义。

如果 note 是一个字符数组,note[strlen(note)-1] 只是最后一个字符。由于 atoi 需要指向 char 的指针(必须以 null 结尾),因此您必须传递 char 的地址而不是值。

将一个 char 数字转换为 int 的任务也可以更容易地解决:

int octave = note[strlen(note) - 1] - '0';

来自manual pagesatoi的签名是:int atoi(const char *nptr);。所以,你需要传递一个char的地址。

当您这样做时:atoi(note[strlen(note) - 1]) 您传递了 char 本身。因此,调用 UB.

当您使用 & 时,您传递的是函数所期望的 - 地址。因此,这有效。

atoi 除了字符串(指向字符的指针),而不是单个字符。

但是,您永远不应使用 atoi,因为该函数的错误处理很糟糕。函数 strtol 100% 等效但更安全。

您需要分两步完成:

  1. 找到字符串中的第一个数字。
  2. 从那里,通过调用 strtol.
  3. 将其转换为整数

1) 可以通过遍历字符串来解决,通过从 ctype.h 调用 isdigit 检查每个项目是否是数字。同时,检查字符串的结尾,空终止符 [=15=]。当您找到第一个数字时,保存指向该地址的指针。

2)通过将保存的指针传给strtol来解决,比如result = strtol(pointer, NULL, 10);.