2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




 
 Помогите разобраться с кодом
Сообщение13.12.2008, 17:12 
Здраствуйте. Необходимо было разобраться в коде программы по переводу из троичной системы счисления в четверичную.
Вот код:

Код:
//---------------------------------------------------------------------------

#include <vcl.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <string.h>
#pragma hdrstop

//---------------------------------------------------------------------------

#pragma argsused
/*функция перевода символов в целое число*/
int CharToInt(char alpha)//символ в число. символьная переменная альфа
{
for (int i = 'A'; i<'J'; i++)//цикл по i от А до J
if (alpha == i)//если симв. переменная равна текущему i
return i - 65 + 10; //вернуть i, равное - 65 + 10
return alpha - 48;//вернуть значение  - альфа - 48
}
/*функция перевода в десятичиную систему исчисления*/
int ConvertToDec(char input[32], int sinp)//перевод в десятичную систему
{                //sinp - троичная система счисления
                 //input[32] - начальное число - массив
int sum = 0; //общая сумма равна нулю
for (int i = 0; i<strlen(input); i++)//цикл по i от нуля до длины введенной строки
sum += CharToInt(input[i]) *pow(sinp, strlen(input)-i-1);
return sum;//вернуть сумму
}
/*перевод в четверичную систему счисления*/
void convertX(int input, int sout)//функция перевода
{
while (input!=0)//пока введенный массив не равен нулю
{
  printf("%d", input%sout);//выводим на экран остаток от деления введенного числа на
  input/=sout;              //четверичную систему счисления типа int
}
}

int main(int argc, char* argv[])
{
int sinp=3;//троичная система счисления
int sout=4;//четверичная система счисления

printf("Vvedite chislo v troichnoy systeme: ");
char input[32]="";
scanf("%s", &input);//ввод числа как массива символов
                     //s - вводим строку
printf("\nKonechnoe chislo v chetverichnoy systeme:");

printf("\n\n=");

convertX(ConvertToDec(input, sinp), sout);//конечный перевод

getch();

return 0;
}
//---------------------------------------------------------------------------


И все вроде уже понятно, вот только не могу разобраться в самой первой функции:

Код:
int CharToInt(char alpha)//символ в число. символьная переменная альфа
{
for (int i = 'A'; i<'J'; i++)//цикл по i от А до J
if (alpha == i)//если симв. переменная равна текущему i
return i - 65 + 10; //вернуть i, равное - 65 + 10
return alpha - 48;//вернуть значение  - альфа - 48
}

Скажите пожалуйста, зачем здесь нужен такой цикл и почему возвращать нужно именно такие значения? Спасибо.
PS И еще... конечное число выводится задом наперед... можно ли это исправить?

 
 
 
 Re: Помогите разобраться с кодом
Сообщение13.12.2008, 17:47 
Strider5000 писал(а):
Код:
int CharToInt(char alpha)//символ в число. символьная переменная альфа
{
for (int i = 'A'; i<'J'; i++)//цикл по i от А до J
if (alpha == i)//если симв. переменная равна текущему i
return i - 65 + 10; //вернуть i, равное - 65 + 10
return alpha - 48;//вернуть значение  - альфа - 48
}

Скажите пожалуйста, зачем здесь нужен такой цикл и почему возвращать нужно именно такие значения? Спасибо.


Типичный «индусский код». Нормально было бы написать:
Код:
int CharToInt(char alpha) {
  if(alpha >= 'A' && alpha <= 'J') return alpha + 10 - 'A';
  if(alpha >= '0' && alpha <= '9') return alpha - '0';
  throw bad_something();
}

Если компилятор приличный, то можно написать:
Код:
int CharToInt(char alpha) {
  switch(alpha) {
    case 'A'...'J': return alpha + 10 - 'A';
    case '0'...'9': return alpha - '0';
    default: throw bad_something();
  }
}
Если это C, то вместо 'throw' надо как-то по-другому обработать сиуацию ошибочного аргумента.

 
 
 
 Re: Помогите разобраться с кодом
Сообщение14.12.2008, 18:51 
вздымщик Цыпа писал(а):

Если компилятор приличный, то можно написать:
Код:
int CharToInt(char alpha) {
  switch(alpha) {
    case 'A'...'J': return alpha + 10 - 'A';
    case '0'...'9': return alpha - '0';
    default: throw bad_something();
  }
}
Если это C, то вместо 'throw' надо как-то по-другому обработать сиуацию ошибочного аргумента.

Большое спасибо за ответ, но хотелось бы знать, для чего вообще используется данный фрагмент кода в программе?

 
 
 
 
Сообщение14.12.2008, 19:52 
вздымщик Цыпа писал(а):
Если компилятор приличный, то можно написать:
Код:
int CharToInt(char alpha) {
  switch(alpha) {
    case 'A'...'J': return alpha + 10 - 'A';
    case '0'...'9': return alpha - '0';
    default: throw bad_something();
  }
}

Хрена себе... Это какие же компиляторы позволяют такое вытворять в switch? Очень удобно, не спорю - более того, мне недавно именно это и было нужно - код типа
Код:
if (a < 39) {}
else if (a < 45) {}
else if...

требует доп. проц. времени, а размножать однотипный код в switch - займет слишком много памяти. Как реализуется switch, подобный написанному Вами - размножением кода, или условными переходами, Вы не знаете?

Strider5000 писал(а):
Большое спасибо за ответ, но хотелось бы знать, для чего вообще используется данный фрагмент кода в программе?

Обычный перевод шестнадцатеричного чила, выраженного в символьном виде (ASCII коды символов 0...9, A...F), в двоичное число типа Int.

Добавлено спустя 4 минуты 8 секунд:

вздымщик Цыпа, кстати, Вы break не забыли после первого case поставить? Или в Вашем компиляторе это уже не обязательно - следующий case не выполнится, если предыдущий выполнялся?

 
 
 
 
Сообщение14.12.2008, 20:16 
e2e4 писал(а):
Strider5000 писал(а):
хотелось бы знать, для чего вообще используется данный фрагмент кода в программе?
Обычный перевод шестнадцатеричного чила, выраженного в символьном виде (ASCII коды символов 0...9, A...F), в двоичное число типа Int.

Здесь есть и необычное - перевод символов 'A'...'J' в целые 10...19.
Обычно ограничиваются переводом 'A'...'F' в целые 10...15.

Strider5000, читайте название функции: CharToInt преобразует символ (Char) в (To) целое (Int).

 
 
 
 
Сообщение14.12.2008, 20:21 
e2e4 в сообщении #167615 писал(а):
вздымщик Цыпа, кстати, Вы break не забыли после первого case поставить? Или в Вашем компиляторе это уже не обязательно - следующий case не выполнится, если предыдущий выполнялся?
Дык там же аж целые return'ы стоят ...

 
 
 
 
Сообщение14.12.2008, 20:38 
Yuri Gendelman писал(а):
Здесь есть и необычное - перевод символов 'A'...'J' в целые 10...19.
Обычно ограничиваются переводом 'A'...'F' в целые 10...15.

Не вникал, читал через строчку, извините.

AD писал(а):
Дык там же аж целые return'ы стоят ...

Кстати да... Опять не заметил :).

 
 
 
 
Сообщение14.12.2008, 21:07 
e2e4 в сообщении #167615 писал(а):
Хрена себе... Это какие же компиляторы позволяют такое вытворять в switch?
gcc. Еще Intel-овский из желания быть совместимым с gcc позволяет это и не только.
e2e4 в сообщении #167615 писал(а):
Как реализуется switch, подобный написанному Вами - размножением кода, или условными переходами, Вы не знаете?
gcc компилирует подобные вещи по-разному, в зависимости от покрытия значениями области определения переменной, по которой 'switch', от опций компиляции и от собственной версии, естественно. Иногда это несколько сравнений, а иногда джамп по табличке.
Yuri Gendelman в сообщении #167639 писал(а):
Здесь есть и необычное - перевод символов 'A'...'J' в целые 10...19.
Обычно ограничиваются переводом 'A'...'F' в целые 10...15.
Ничего необычного. 20-ричная система счисления ничем не хуже 10-ичной :)

 
 
 
 
Сообщение14.12.2008, 22:25 
Всем большое спасибо за дискуссию!
В заключении хотелось бы узнать, как можно организовать вывод результата должным образом? А то вывод цифр числа результата работает задом наперед... Есть ли у кого-нибудь идеи по этому поводу?

 
 
 
 
Сообщение14.12.2008, 22:45 
вздымщик Цыпа писал(а):
Ничего необычного. 20-ричная система счисления ничем не хуже 10-ичной :)
Не возражаю, если иметь в виду ксеноматематику. Тут еще и сама программа - перевод из 3-ичной в 4-ичную систему. Надо бы проверить, откуда прилетел автор кода.

 
 
 
 
Сообщение14.12.2008, 23:20 
Strider5000 в сообщении #167693 писал(а):
В заключении хотелось бы узнать, как можно организовать вывод результата должным образом? А то вывод цифр числа результата работает задом наперед... Есть ли у кого-нибудь идеи по этому поводу?

Да уж, глянул на эту функцию. Песня подбитого программиста :lol: Чего стоит только вычисление 'strlen(input)' два раза за каждый шаг цикла...
Код:
/*функция перевода в десятичиную систему исчисления*/
int ConvertToDec(char input[32], int sinp)//перевод в десятичную систему
{                //sinp - троичная система счисления
                 //input[32] - начальное число - массив
int sum = 0; //общая сумма равна нулю
for (int i = 0; i<strlen(input); i++)//цикл по i от нуля до длины введенной строки
sum += CharToInt(input[i]) *pow(sinp, strlen(input)-i-1);
return sum;//вернуть сумму
}


Нормально было бы написать так:
Код:
int ConvertToDec(char const *input, unsigned int sinp) {
    unsigned int sum = 0;
    while(*input) {
        unsigned int tmp = sum * sinp + CharToInt(*(input++));
        if(tmp / sinp != sum)
          throw bad_something(); // уродливая, но простая проверка на переполнение
        tmp = sum;
    }
    return sum;
}


А задом наперед оно выводится из-за ошибки в функции 'void convertX(...)', там выводятся разряды начиная с младшего. Может оно так и задумано было? :)

 
 
 
 
Сообщение16.12.2008, 10:59 
вздымщик Цыпа писал(а):
e2e4 в сообщении #167615 писал(а):
Хрена себе... Это какие же компиляторы позволяют такое вытворять в switch?
gcc. Еще Intel-овский из желания быть совместимым с gcc позволяет это и не только.
e2e4 в сообщении #167615 писал(а):
Как реализуется switch, подобный написанному Вами - размножением кода, или условными переходами, Вы не знаете?
gcc компилирует подобные вещи по-разному, в зависимости от покрытия значениями области определения переменной, по которой 'switch', от опций компиляции и от собственной версии, естественно. Иногда это несколько сравнений, а иногда джамп по табличке.

Спасибо за информацию!

 
 
 
 
Сообщение16.12.2008, 21:03 
Я бы сам хотел знать, откуда прилетел автор кода, но это мне увы, не известно)
Код не моей руки, я просто пытаюсь в этом изобретении человеческой мысли разобраться)

 
 
 [ Сообщений: 13 ] 


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group