Как выполнять математические операции в Ascii?

Я пытаюсь разобрать значения широты и долготы из пакета GPS NMEA. Я получаю пакет в виде массива символов. Я проанализировал массив широты, и теперь мне нужно выполнить над ним операцию умножения. Но это массив символов. Например, вот пример массива:

char *latitude;

latitude[0] = '4';
latitude[1] = '0';
latitude[2] = '5';

Я хочу умножить это значение на 2. Оно должно выводить 8,0,10 соответственно. Поэтому мне нужно получить значения 4,2,6 как целое число. Но если я использую содержимое этого массива как целое число, оно, естественно, выводит 52,48,53. Я не хочу получать целочисленное значение, которое соответствует этим символам ascii, я хочу получить фактическое значение, как я вижу.


person abdullah cinar    schedule 11.01.2016    source источник
comment
Вы уверены, что каждое из введенных чисел одна цифра?   -  person Basile Starynkevitch    schedule 11.01.2016
comment
Пример вычисления был бы хорош. Итак, у вас есть строка 405, и вы хотите получить 8010?   -  person Koshinae    schedule 11.01.2016
comment
Скомпилируйте со всеми предупреждениями и отладочной информацией gcc -Wall -Wextra -g, затем используйте отладчик (gdb), чтобы понять поведение вашей программы.   -  person Basile Starynkevitch    schedule 11.01.2016
comment
4,2,6 =› стать 52,50,54. почему 52,48,53?(4,0,5?) покажи свой код.   -  person BLUEPIXY    schedule 11.01.2016
comment
@BLUEPIXY извините, я забыл изменить значения. Это 4,0,5, соответствующие этим значениям ascii. А для Basile, да, это однозначные числа, но я также добавил элемент управления, чтобы проверить это.   -  person abdullah cinar    schedule 11.01.2016
comment
вам нужно 8010 или 810? или 504 => 1008?   -  person BLUEPIXY    schedule 11.01.2016
comment
Мне нужно 8010 или {8,0,10} как целое число   -  person abdullah cinar    schedule 11.01.2016


Ответы (3)


Прежде всего, вы должны убедиться, что числа либо однозначные, либо у вас есть обработка. Обратите внимание, что chars можно использовать как целые числа без явного преобразования из-за продвижения целых чисел. Например, если

latitude[0] = '1';
latitude[1] = '3';
latitude[2] = '9';

Вы должны пройти их по отдельности, а затем связать их вместе. Вы можете получить значение int из char, вычитая '0', поскольку все однозначные значения int в ascii следуют друг за другом. Для этого напишите такую ​​функцию:

int asciiToInt (char ascii) {
if ( ascii < '0' || ascii > '9' ) {
return -1; //error
}
else
{
return (int)(ascii - '0'); // This works because '0' has the int value 48 in Ascii and '1' 49 and so on.
}
}

Тогда назовите это так

int a = asciiToInt(latitude[0])*2;

Или, если вы хотите иметь 3-значный номер

int a;
a = asciiToInt(latitude[0]);
a += asciiToInt(latitude[1])*10;
a += asciiToInt(latitude[2])*100;
a = a*2;
person magisch    schedule 11.01.2016
comment
Это тоже полностью работает. Но знаете ли вы, в чем разница между определением массива как char *latitude или char latitude[3]? Первое определение не работает или не печатает его должным образом. - person abdullah cinar; 11.01.2016
comment
@abdullahcinar stackoverflow.com/questions/1704407/ - person magisch; 11.01.2016
comment
return (int)(ascii - '0'); Приведение, а также круглые скобки - лишний беспорядок. return ascii - '0'; более читабелен и делает то же самое. Если причина приведения заключалась в том, чтобы избежать неявного повышения типа, вы должны были написать return (int)ascii - '0';. - person Lundin; 11.01.2016
comment
@Lundin Если хотите, вы можете отредактировать это. Лично я считаю, что это нормально. - person magisch; 11.01.2016
comment
@BLUEPIXY Он хочет преобразовать числа в форме char в числа int. Функция, которую я написал, получает желаемый результат только в том случае, если введенный символ является числом. «0» равно 48, а «9» — 57. Таким образом, функция делает то, для чего предназначена, только если значение int введенного char находится между 48 и 57 или «0» и «9». - person magisch; 11.01.2016
comment
@BLUEPIXY Почему это ерунда? Он обрабатывает символы как значения int. Пожалуйста, объясните, почему вы думаете, что это не сработает. - person magisch; 11.01.2016
comment
'0' › '1' › '9' --› 0 › '9' --› ложь, '0' › '\0' › '9' --› 1 › '9' --› ложь. это всегда неверно. - person BLUEPIXY; 11.01.2016
comment
@Magisch Что ж, это сработает ... но это предполагает, что программист 1) не знает о неявных правилах продвижения в C и 2) что программист не знает о типе символьных литералов в C. Хотя сам код не Это проблематично, это типичный случай предупреждающих знаков для других программистов, читающих код. Если бы я нашел такой код при просмотре кода, я бы прочитал весь остальной код этого программиста гораздо внимательнее. В общем, return (something), а не return something — еще один такой предупреждающий знак. - person Lundin; 11.01.2016
comment
И вот, после более внимательного прочтения кода BLUEPIXY только что заметил серьезную ошибку новичка в первой строке... Упомянутые предупреждающие знаки почти всегда верны. - person Lundin; 11.01.2016
comment
@Lundin Я предполагаю, что ОП не знает об этом. Я знаю, что тебе не нужно этого делать. Но если вы разместите это, как вы предложили, ОП должен был знать о неявном продвижении и литералах, и, если бы он знал, он бы не задавал этот вопрос. И да, как вы, наверное, догадались, я ученик и сам начал изучать C около 3 месяцев назад. - person magisch; 11.01.2016
comment
@BLUEPIXY Теперь я это вижу. Я исправил это. Прости за это. И оказывается, я совершил еще одну ошибку, пытаясь исправить первую. Лундин исправил это сейчас, извините за это. - person magisch; 11.01.2016

Попробуйте преобразовать char в int, вычитая из него '0'. Пример:

int doubledLatitude[3];
for (size_t i = 0; i < 3; ++i)
    doubledLatitude[i] = (latitude[i] - '0') * 2;
person V. Kravchenko    schedule 11.01.2016
comment
Это странно. Я пытался вычесть «0», но не смог. Я понял, что если я определяю свой массив следующим образом: char *latitude; Это не работает. Но если я определяю это так: char latitude[3]; Это работает. У вас есть идеи, почему? - person abdullah cinar; 11.01.2016
comment
@abdullahcinar stackoverflow.com/questions/1704407/ - person magisch; 11.01.2016
comment
@abdullahcinar Если вы выберете char *latitude; latitude[0] = '4'; latitude[1] = '0'; latitude[2] = '5';, вы получите нарушение прав доступа при записи в неверную область памяти, поскольку в приведенном выше коде отсутствует выделение памяти. Хотя это совсем другой вопрос. - person V. Kravchenko; 11.01.2016
comment
@ В.Кравченко Я использовал первое определение, потому что не знал, каким будет размер массива широты. Но я лучше определяю его достаточно большим размером. Спасибо за ответ, я прояснился. - person abdullah cinar; 11.01.2016

Во-первых, вы должны точно указать ввод, возможно, используя EBNF и решите, что программа должна делать с ошибками. Одного примера никогда не бывает достаточно! См. это.

Чтобы преобразовать один символ '4' в целое число 4, вы можете использовать ('4' - '0') (поскольку разница chars повышается до int), поэтому я думаю, вам нужно что-то вроде (latitude[0] - '0')*2, которое вы можете напечатать с помощью printf("%d",(latitude[0] - '0')*2)

Кстати, если ваши строки цифр содержат одну или несколько цифр, вы можете использовать strtol чтобы преобразовать их в некоторые long (например, "123 " преобразовать в 123L) и получить конечный символ (следовательно, иметь возможность обнаруживать и обрабатывать ошибки).

Вы также можете использовать sscanf; обратите внимание, что он возвращает количество отсканированных элементов (которые вы всегда должны проверять) и что означают %d, %1d и %n в строке формата.

person Basile Starynkevitch    schedule 11.01.2016
comment
Как и my_char1 - my_char2, из-за целочисленного продвижения. - person Lundin; 11.01.2016
comment
@V.Kravchenko Я думаю, он комментировал, как получить 4 из '4', а не 52 ;) - person magisch; 11.01.2016
comment
@Magisch: нет, в своем первоначальном ответе я не сказал, что разница двух char составляет int - person Basile Starynkevitch; 11.01.2016
comment
Первоначальный комментарий, вероятно, был обеспокоен тем, что символьные литералы, такие как '4', уже имеют тип int в C. В отличие от C++, где они имеют тип char. Целочисленное продвижение применяется только в том случае, если у вас есть символьные переменные типа char, поэтому я разместил комментарий выше. - person Lundin; 11.01.2016