Как се правят математически операции в 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 Той иска да преобразува числата в символна форма в int числа. Функцията, която написах, получава желания резултат само ако въведеният char е число. '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' --› false, '0' › '\0' › '9' --› 1 › '9' --› false. това винаги е невярно. - person BLUEPIXY; 11.01.2016
comment
@Magisch Добре, ще работи... но това предполага, че програмистът 1) не е наясно с имплицитните правила за промоция в C и 2) че програмистът не е наясно с типа символни литерали в C. Докато самият код е t проблематично, това е типичен случай на предупредителни знаци за други програмисти, които четат кода. Ако открия код като този при преглед на кода, бих прочел целия друг код от този програмист много по-внимателно. По принцип return (something), а не return something е друг такъв предупредителен знак. - person Lundin; 11.01.2016
comment
И ето го, след като прочете кода по-внимателно, BLUEPIXY току-що забеляза основен бъг за начинаещи на първия ред... Споменатите предупредителни знаци са почти винаги правилни. - person Lundin; 11.01.2016
comment
@Lundin Предполагам, че OP не е наясно с това. Знам, че не е нужно да го правиш. Но ако го публикувате, както предложихте, OP ще трябва да е наясно с имплицитната промоция и литералите и ако беше, той нямаше да задава този въпрос. И да, както вероятно се досещате, аз съм чирак и започнах да уча C преди около 3 месеца. - person magisch; 11.01.2016
comment
@BLUEPIXY Виждам това сега. Поправих това. Съжалявам за това. И се оказа, че съм направил още една грешка, опитвайки се да поправя първата. Lundin обаче го поправи сега, съжалявам за това. - 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
@V.Kravchenko Бях използвал първата дефиниция, защото не знаех какъв ще бъде размерът на масива с географска ширина. Но по-добре да го определя с достатъчно висок размер. Благодаря за отговора, изясних се. - 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: не, не казах в първоначалния си отговор, че разликата от две chars е int - person Basile Starynkevitch; 11.01.2016
comment
Първоначалният коментар вероятно е бил загрижен за знаковите литерали като '4', които вече са от тип int в C. За разлика от C++, където те са от тип char. Целочислената промоция се прилага само когато имате символни променливи от тип char, поради което публикувах коментара по-горе. - person Lundin; 11.01.2016