简体   繁体   English

在C语言中将“字符”转换为“整数”的逻辑

[英]LOGIC of Converting a “char” into an “int” in C

everyone! 大家!

please help me understand the following problem... So i will have a STRING-type input of a note, looks like "A5" or "G#2" or "Cb4" etc. And i need to extract an octave index, which is the last digit "5" or "2" or "4"... And after exctraction i need it as an int-type. 请帮助我理解以下问题...因此,我将具有注释的STRING类型输入,看起来像“ A5”或“ G#2”或“ Cb4”等。并且我需要提取一个八度音阶索引,是最后一个数字“ 5”或“ 2”或“ 4” ...提取后,我需要将其作为整数类型。

So I did this: 所以我这样做:

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

But it gave me an error "error: incompatible integer to pointer conversion passing 'char' to parameter of type 'const char *'; take the address with & [-Werror,-Wint-conversion]" 但这给了我一个错误“错误:将指针'char'传递给'const char *'类型的参数的指针转换的不兼容整数;使用&[-Werror,-Wint-conversion]来获取地址”

Then I tryied to throug away the math from the function, and did this: 然后,我尝试摆脱函数中的数学运算,并执行以下操作:

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

It didn't work as well. 效果也不佳。 So i did my reserch on atoi function and i don't get it... 所以我对atoi函数进行了研究,但我不明白...

  1. ATOI expects a string (CHECK) ATOI需要一个字符串(CHECK)
  2. Converts it to an interger, not the ASCII meanning (CHECK) 将其转换为整数,而不是ASCII含义(CHECK)
  3. Library for atoi function (CHECK) 用于atoi函数的库(检查)

What I am doing in basically asking "take n-th character of that string and make it an int". 我在做的主要是询问“采用该字​​符串的第n个字符并将其设置为int”。

After googling for some time a found an other code example where a guy uses atoi with this symbol '&'. 谷歌搜索一段时间后,找到了另一个代码示例,其中一个人使用atoi并带有“&”符号。 So i did this : 所以我做到了

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

And IT WORKED! 和它的工作! But I can't understand WHY it worked with the & symbol and didnt work without it....Cause it always worked without it! 但是我不明白为什么它与&符号一起工作,而没有它却无法工作....因为它总是在没有它的情况下工作! There was a million times i was giving a single-character string like '5' or so ond just used atoi and it worked perfectly... 我曾经给过一百万次输入像atooi这样的单字符字符串'5'或类似的命令,并且效果很好。

Plesase help me, why in this case it acts so weird? 请帮我,为什么在这种情况下它表现得如此怪异?

C does not have a native string type. C没有本地字符串类型。 Strings are usually represented as char array or a pointer to char. 字符串通常表示为char数组或char指针。

Assuming that string is just a typedef to char * . 假设该string只是char *的typedef。

if note is an array of chars, note[strlen(note)-1] is just the last character. 如果note是一个字符数组,则note[strlen(note)-1]只是最后一个字符。 Since atoi expects a pointer to char (which has to be null-terminated) you have to pass the address of the char and not the value. 由于atoi需要一个指向char的指针(必须为null终止),因此您必须传递char的地址而不是值。

The task to convert one char digit to int could also be solved easier: 将一个字符转换为整数的任务也可以更容易地解决:

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

The function atoi takes a pointer to a character array as the input parameter ( const char* ). 函数atoi将指向字符数组的指针作为输入参数( const char* )。 When you call note[strlen(note) - 1] this is a single character ( char ), in order to make atoi work you need to provide the pointer. 调用note[strlen(note) - 1]这是一个字符( char ),为了使atoi工作,您需要提供指针。 You do that by adding & as you've done. 您可以通过添加&完成此操作。 This then works, because right after that single digit there is a null character \\0 that terminates the string - because your original string was null-terminated. 这样就可以了,因为在该个数字之后有一个空字符\\0终止了该字符串-因为原始字符串以空字符结尾。

Note however that doing something like this would not be a good idea: 但是请注意,这样做不是一个好主意:

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

as there is no way to be sure what the next byte in memory is (following the byte that belongs to a ), but the function will try to read it anyway, which can lead to undefined behaviour. 因为无法确定内存中的下一个字节是什么(跟在属于a的字节之后),但是该函数仍将尝试读取该字节,这可能导致未定义的行为。

The last character is... well a character! 最后一个角色是……一个角色! not a string. 不是字符串。 So by adding the & sign, you made it a pointer to character ( char* )! 因此,通过添加&符号,可以使其成为指向字符( char* )的指针!

You can also try this code: 您也可以尝试以下代码:

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

Gives you ASCII code of 5 minus ASCII code of 0 给您5 ASCII码减去0 ASCII码

From the manual pages , the signature of atoi is: int atoi(const char *nptr); 手册页上atoi的签名为: int atoi(const char *nptr); . So, you need to pass the address of a char . 所以,你需要传递的地址char

When you do this: atoi(note[strlen(note) - 1]) you pass the char itself. 执行此操作时: atoi(note[strlen(note) - 1])您将传递char本身。 Thus, invoking UB . 因此,调用UB

When you use the & , you are passing what the function expects - the address. 当使用& ,您将传递函数期望的地址。 Hence, that works. 因此,这可行。

atoi excepts a string (a pointer to character), not a single character. atoi除了字符串(指向字符的指针)以外,而不是单个字符。

However, you should never use atoi since that function has bad error handling. 但是,您永远不要使用atoi因为该函数具有错误的错误处理。 The function strtol is 100% equivalent but safer. 功能strtol是100%等效但更安全。

You need to do this in two steps: 您需要分两步执行此操作:

  1. Find the first digit in the string. 查找字符串中的第一个数字。
  2. From there, convert it to integer by calling strtol . 从那里,通过调用strtol将其转换为整数。

1) can is solved by looping through the string, checking if every item is a digit by calling isdigit from ctype.h. 1)可以通过遍历字符串来解决,可以通过从ctype.h调用isdigit来检查每个项目是否都是数字。 Simultaneously, check for the end of the string, the null terminator \\0 . 同时,检查字符串的结尾,即空终止符\\0 When you find the first digit, save a pointer to that address. 当找到第一个数字时,保存指向该地址的指针。

2) is solved by passing the saved pointer to strtol , such as result = strtol(pointer, NULL, 10); 2)通过将保存的指针传递给strtol来解决,例如result = strtol(pointer, NULL, 10); .

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM