eXeL@B —› Программирование —› Хочу обсудить один пример по C++ |
Посл.ответ | Сообщение |
|
Создано: 31 августа 2008 10:58 · Личное сообщение · #1 Наткнулся на одну книгу по C++/ Сам сейчас только в процессе изучения. Книга под DOS, поэтому проверять не стал исходники. Хочу обсудить пару листингов с теми кому интересно. 1. С первым мне все понятно. Пример находит все простые делители введенного числа. После просмотра листинга все сошлось. Все работает. Происходит нормальный выход из программы #include <iostream> #include <math.h> using namespace std; void get_all_divisors(int n); int get_lowest_divisor(int n); int main() { int n; while(1) { cout << "Enter a number (0 to quit): "; cin >> n; if (n == 0) break; get_all_divisors(n); cout << endl; } return 0; } // Get all divisors function; use a loop // to print all the divisors of n, by reiterative // calls to get_lowest_divisor void get_all_divisors(int n) { int i; while (1) { i = get_lowest_divisor(n); cout << i; if (i == n) // If lowest divisor == n break; // there are no more divisors, cout << ", "; // Else, print comma and get n = n/i; // lowest divisor of remaining } // quotient. } int get_lowest_divisor(int n) { int i; double sqrt_of_n = sqrt(static_cast<double>(n)); for (i = 2; i <= sqrt_of_n; i++) if (n % i == 0) // If i divides n evenly, return i; // return i. // If no divisor is found, return n itself. return n; } 2.Программа делает тоже самое-находит все простые делители. Немного беспорядочно их выдает, но не суть. А вот тут у меня возникли сомнения. Не ошибся ли автор книги. То, что я выделил жирным, а именно выход из программы, по-мойму не может быть осуществлен, т.к перед ним всегда будет вызвана рекурсивная функция get_divisors(n / i); в результате чего программа закончится последней инструкцией cout << n; ....Но, что будет дальше, когда выполнится эта инструкция ? Выхода то нет. Куда перейдет вообще управление программой. #include <math.h> using namespace std; void get_divisors(int n); int main() { int n; cout << "Enter a number and press ENTER: "; cin >> n; get_divisors(n); return 0; } // Get divisors function // This function prints all the divisors of n, // by finding the lowest divisor, i, and then // rerunning itself on n/i, the remaining quotient. void get_divisors(int n) { int i; double sqrt_of_n = sqrt((double) n); for (i = 2; i <= sqrt_of_n; i++) if (n % i == 0) { // If i divides n evenly, cout << i << ", "; // Print i, get_divisors(n / i); // Factor n/i, return; // and exit. } // If no divisor is found, then n is prime; // Print n and make no further calls. cout << n; } |
|
Создано: 31 августа 2008 11:03 · Личное сообщение · #2 То есть в самом конце программы надо переместить выход под конец. Как думаете. for (i = 2; i <= sqrt_of_n; i++) if (n % i == 0) { // If i divides n evenly, cout << i << ", "; // Print i, get_divisors(n / i); // Factor n/i, return; // and exit. ===========убрать и перенести в конец } // If no divisor is found, then n is prime; // Print n and make no further calls. cout << n; return; // and exit. ===========сюда } |
|
Создано: 31 августа 2008 13:03 · Личное сообщение · #3 jondos Ты конечно МОЗГ! or (i = 2; i <= sqrt_of_n; i++) if (n % i == 0) { // If i divides n evenly, cout << i << ", "; // Print i, get_divisors(n / i); // Factor n/i, return; // and exit. } Вишь этот код? тут цикл, который отработает и выйдет, т.к. функция рекурсивно вызывает саму себя и этот цикл так называемый якорь - то есть условие выхода ----- Лень - это подсознательная мудрость |
|
Создано: 01 сентября 2008 11:52 · Поправил: arnix · Личное сообщение · #4 Code:
не хватает одного "{", [наверно] должно быть Code:
|
|
Создано: 01 сентября 2008 20:37 · Личное сообщение · #5 Да это вообще кривой код )) На столько кривой, что работает без ошибок. Ошибка только одна - в комментарии. Не стоит читать его буквально. Он означает exit не из программы а из текущего вызова функции. Та как функция рекруссивна, в данном случе return одначает возврат на "уровень выше", а выход в main произойдет после цаута }. |
|
Создано: 22 сентября 2008 04:13 · Личное сообщение · #6 Спасибо. Теперь дошло. Доп скобок не надо никаких. Все правильно. Я просто не понимал, что рекурсивная функция умная такая. ---------------------------------------------------------------------- ------------------------------- Кстати, вот такой моментик есть. ............... x = get_a_string(p) char *get_a_string(char *start_addr, char *dest) { char *p = start_addr; .............. Правильно ли я понял, чта выделенная жирным инструкция просто передает указателю p свойства указателя start_addr. Ведь после принятия аргумента (char *start_addr, char *dest) указатель start_addr можно использовать в дальнейшем теле функции. Или все-таки какой-то смысл есть в char *p = start_addr |
|
Создано: 22 сентября 2008 07:51 · Личное сообщение · #7 >>char *p = start_addr; >>просто передает указателю p свойства указателя start_addr. Указатель это адрес .... и все... адрес это число.... если компилятор 32битный код генерирует то размер указателя 32бита... а то что у него есть доп. тэги компилятору что мол по этому адресу мы имеем память с типом char .. уже второе.... >>указатель start_addr можно использовать в дальнейшем теле функции. Или все-таки какой-то смысл >>есть в char *p = start_addr обычно так делают для того что бы всегда иметь изначальный указатель на память ... но и при этом иметь удобный способ работы с этой памятью не теряя начальный указатель.... то бишь... предположим что у нас оба указателя указывают на нуль терминированую строку... и нам надо скопировать из старт адрес её в dest Code:
При этом мы потеряли изначальные указатели на память start_addr и dest и соотвено скажем если память по указателю start_addr была выдела динамически и мы хотим иметь возможность в функции после копирования содержимого start_addr в dest её освободить ... то сделать мы этого не сможем то бишь надо было сохранить куда нибудь этот указатель перед работой с ним.... то бишь можно скажем вот так сделать было: Code:
п.с: если тебя не надо будет иметь начальный указатель в функции то и не вводи дополнительную переменную.... ... а если надо то создавай переменную .... все зависит от конкретной задачи... |
eXeL@B —› Программирование —› Хочу обсудить один пример по C++ |