2014 dxdy logo

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

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




Начать новую тему Ответить на тему
 
 Помогите разобраться с кодом
Сообщение13.12.2008, 17:12 


22/09/08
20
Иваново
Здраствуйте. Необходимо было разобраться в коде программы по переводу из троичной системы счисления в четверичную.
Вот код:

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

#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 


12/09/08

2262
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 


22/09/08
20
Иваново
вздымщик Цыпа писал(а):

Если компилятор приличный, то можно написать:
Код:
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 


21/03/06
1545
Москва
вздымщик Цыпа писал(а):
Если компилятор приличный, то можно написать:
Код:
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 
Заслуженный участник


15/05/05
3445
USA
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 
Экс-модератор


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

 Профиль  
                  
 
 
Сообщение14.12.2008, 20:38 


21/03/06
1545
Москва
Yuri Gendelman писал(а):
Здесь есть и необычное - перевод символов 'A'...'J' в целые 10...19.
Обычно ограничиваются переводом 'A'...'F' в целые 10...15.

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

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

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

 Профиль  
                  
 
 
Сообщение14.12.2008, 21:07 


12/09/08

2262
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 


22/09/08
20
Иваново
Всем большое спасибо за дискуссию!
В заключении хотелось бы узнать, как можно организовать вывод результата должным образом? А то вывод цифр числа результата работает задом наперед... Есть ли у кого-нибудь идеи по этому поводу?

 Профиль  
                  
 
 
Сообщение14.12.2008, 22:45 
Заслуженный участник


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

 Профиль  
                  
 
 
Сообщение14.12.2008, 23:20 


12/09/08

2262
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 


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

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

 Профиль  
                  
 
 
Сообщение16.12.2008, 21:03 


22/09/08
20
Иваново
Я бы сам хотел знать, откуда прилетел автор кода, но это мне увы, не известно)
Код не моей руки, я просто пытаюсь в этом изобретении человеческой мысли разобраться)

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 13 ] 

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group