Часовой пояс: UTC + 3 часа




Начать новую тему Новая тема / Ответить на тему Ответить  Сообщений: 1730 • Страница 51 из 87<  1 ... 48  49  50  51  52  53  54 ... 87  >
  Пред. тема | След. тема 
В случае проблем с отображением форума, отключите блокировщик рекламы
Автор Сообщение
 

Member
Статус: Не в сети
Регистрация: 01.05.2007
Откуда: Тель-Авив
Фото: 1
Provider
Тогда извиняюсь. Уж сильно стало похоже на домашнее задание.
Хороший учебник, к сожалению, огласить не могу. Когда-то в детстве читал какую-то книгу, объясняющую синтаксис С чуть ли не в комиксах. За давностью лет автора не помню, но другой столь легкой для понимания литературы с тех пор не встречал.
Да. Так есть вопросы по алгоритму или реализации?



Партнер
 

Member
Статус: Не в сети
Регистрация: 19.12.2005
Откуда: НН
Фото: 69
Herod В общем то до меня так и не дошли твои мысли, но я все же попробовал собрать это:
Код:
#include <stdio.h>

int main(int argc, char *argv[], char *env[])
{
    int radius, x, y;

    if(argc == 1)
        sscanf(argv[1], "%d", &radius);
    else
    {
        printf("#");
        return 1;
    }

    for(y=0; y<radius*2; y++)
    for(x=0; x<radius*2; x++ )
    int rx=x-radius, ry=y-radius;
    if((rx*rx+ry*ry)==radius*radius)
    printf("*");
    else
    printf(" ");
}

Алгорит работы не ясен ни разу.
Компилиривать это откзывается:
Код:
5.c(17): error: a dependent statement may not be a declaration
      int rx=x-radius, ry=y-radius;
      ^

compilation aborted for 5.c (code 2)

Плюс ко всему не понимаю как сюда прикрутить дефолтовое значение (размер) круга... В общем бяда :(


 

Member
Статус: Не в сети
Регистрация: 01.05.2007
Откуда: Тель-Авив
Фото: 1
Provider, поехали:
Функция main() принимает 3 аргумента: кол-во аргументов в командной строке, аргументы командной строки, буфер с переменными окружения.
if( argc == 1 ) проверяет, что нам передали параметр. И ругается диезом, если его нам не дали.
Параметр преобразуется в число при помощи sscanf - работает также как и scanf, но берет ввод из строки вместо клавиатуры. Таким образом мы получили диаметр круга.
Если же мы хотим рисовать круг с дефолтовым радиусом если юзер его не ввел - вместо ругани (printf("#"); return 1) можно присвоить нашей переменной значение радиуса по умолчанию.

Алгоритм работы:
простейшая формула круга: x^2 + y^2 = r^2.
предполагается, что центр круга находится в точке (0,0)
Мы идем по квадрату, который начинается в точке (-r, -r) и заканчивается в точке (r, r). Понятно, что наш круг вписан в этот квадрат.
Для каждой точки квадрата мы проверяем, соответствует ли она условию формулы круга. Если да, то рисуем символ. Иначе - пробел.
Поскольку экран начинается в точке (0,0), а нас интересуют отрицательные значения тоже - мы заводим переменные rx и ry. Для упрощения вычислений.

Насчет ошибки компиляции.
После каждого из for надо открыть фигурную скобку.
И заодно вставить перенос строки после каждой отрисованной линии.
Код:
    for(y=0; y<radius*2; y++) {
        for(x=0; x<radius*2; x++ ) {
            int rx=x-radius, ry=y-radius;
            if((rx*rx+ry*ry)==radius*radius)
                printf("*");
            else
                printf(" ");
        }
        printf( "\n" );
    }


 

Member
Статус: Не в сети
Регистрация: 19.12.2005
Откуда: НН
Фото: 69
Herod Спасибо за раъяснения! :beer:
Herod писал(а):
После каждого из for надо открыть фигурную скобку.

Никогда такого не видел. Зачем это? Впрочем с этими скобками компилятор тоже ругается, мол если есть открывающая, то должна быть и зкрывающая скобка :insane:
Добавлено спустя 2 минуты, 40 секунд
Herod писал(а):
помощи sscanf - работает также как и scanf

А зачем тут собственно scanf? Нельзя ли использовать argc, как я это делал ранее?


 

Member
Статус: Не в сети
Регистрация: 01.05.2007
Откуда: Тель-Авив
Фото: 1
Provider писал(а):
Никогда такого не видел. Зачем это? Впрочем с этими скобками компилятор тоже ругается, мол если есть открывающая, то должна быть и зкрывающая скобка

Дык закрывающие скобки там есть. Перед и после printf("\n")
А иначе компилятор не будет знать, что крутить в цикле.

Provider писал(а):
А зачем тут собственно scanf? Нельзя ли использовать argc, как я это делал ранее?

argc - КОЛИЧЕСТВО аргументов. Сами аргументы сидят в argv[]. В виде текстовых строк. Потому и sscanf - чтобы преобразовать строку в число.


 

Member
Статус: Не в сети
Регистрация: 19.12.2005
Откуда: НН
Фото: 69
Herod писал(а):
argc - КОЛИЧЕСТВО аргументов

Вечно я их путаю, argv[] конечно же...
Код:
#include <stdio.h>

int main(int argc, char *argv[], char *env[])
{
    int radius, x, y;

    if(argc == 1)
        sscanf(argv[1], "%d", &radius);
    else
    {
        printf("#");
        return 1;
    }

    for(y=0; y<radius*2; y++) {
        for(x=0; x<radius*2; x++ ) {
            int rx=x-radius, ry=y-radius;
            if((rx*rx+ry*ry)==radius*radius)
                printf("*");
            else
                printf(" ");
    }
    printf("\n");
}
}

Добавил в конце еще одну скобку и все скомпиоировалось, но не работает, рисует только один # и все :(


 

Member
Статус: Не в сети
Регистрация: 01.05.2007
Откуда: Тель-Авив
Фото: 1
Каюсь. Первый аргумент - это само имя файла.
Поэтому if( argc == 2 )
Только что проверил. Работает.


 

Member
Статус: Не в сети
Регистрация: 19.12.2005
Откуда: НН
Фото: 69
Herod Работает, но как-то странно. При значении 5:
Код:
     *
  *     *
 *       *


*


 *       *
  *     *

Так и должно быть?


 

Member
Статус: Не в сети
Регистрация: 01.05.2007
Откуда: Тель-Авив
Фото: 1
Provider
Да, потому что звездочка рисуется только при точном выполнении условия x^2 + y^2 = r^2
По идее, строчку "if((rx*rx+ry*ry)==radius*radius)"
можно заменить на "if(abs((rx*rx+ry*ry)-radius*radius) <= 5)"
Пятерку подобрать опытным путем. Ну или творить это дело в графике.

ЗЫ. второй способ - считать пару иксов, исходя из той же формулы.
То есть, x = sqrt( r^2 - y^2 ). Тогда можно бежать только по y (оставив только внешний цикл), а x вычислять и лепить нужное кол-во пробелов. Не забывая, что у этого уравнения есть два икса с противоположными знаками.
Добавлено спустя 8 минут, 18 секунд
Код для второго способа:
Код:
#include <stdio.h>
#include <math.h>

int main(int argc, char *argv[], char *env[])
{
    int radius, x, y;

    if(argc == 2)
        sscanf(argv[1], "%d", &radius);
    else
    {
        printf("#");
        return 1;
    }

    for( y = 0; y < radius * 2; y++ ) {
   int   ry = y - radius;
   int   rx = sqrt( radius * radius - ry * ry );
   int   i;
   printf( "%02d.  ", y );

   for( i = 0; i < radius - rx; i++ )
      printf( " " );

   printf( "*" );

   for( i = 0; i < rx * 2; i++ )
      printf( " " );   

   printf( "*" );
   
       printf("\n");
    }
}


ушел исполнять гражданский долг...


 

Member
Статус: Не в сети
Регистрация: 19.12.2005
Откуда: НН
Фото: 69
Herod Хммм, как фисе сложно... стало лучше. Почему он рисуется сплющенным по бокам? и не полностью?
Т.е. это можно побороть только 2ым способом?


 

Member
Статус: Не в сети
Регистрация: 01.05.2007
Откуда: Тель-Авив
Фото: 1
Provider,
Насчет неполностью - это надо переходить ко второму способу.
А сплющенный - потому что символы в текстовом режиме сплющенные.


 

Member
Статус: Не в сети
Регистрация: 19.12.2005
Откуда: НН
Фото: 69
Herod писал(а):
Насчет неполностью - это надо переходить ко второму способу.

Я решил это несколько проще:
for(y=0; y<=radius*2; y++) {
for(x=0; x<=radius*2; x++ ) {
;)


 

Advanced member
Статус: Не в сети
Регистрация: 09.03.2004
Откуда: Кишинёв
Provider писал(а):
Почему он рисуется сплющенным по бокам?

Потому что в текстовом режиме высота символа в два раза превышает его ширину. Нахождение координат (x,y) легко искать из уравнения окружности в [url=http://ru.wikipedia.org/wiki/Полярная_система_координат]полярной системе координат[/url]:
x = Округл(R*2*sin(fi)),
y = Округл(R*cos(fi)).
Двойка при синусе это как раз избавление от сплющивания. Достаточно пробежаться значением fi от 0 до 2Пи(шаг подобрать экспериментально), да не забыть сместить точку центра окружности(например в 40,12). R можно взять к примеру 10.


 

Member
Статус: Не в сети
Регистрация: 01.05.2007
Откуда: Тель-Авив
Фото: 1
mein писал(а):
Достаточно пробежаться значением fi от 0 до 2Пи

Это довольно неприятно делать, потому что:
1. текстовый режим
2. тут пытались не выходить за пределы ANSI


 

Junior
Статус: Не в сети
Регистрация: 09.01.2007
Откуда: Москва
Пардон, что влезаю в беседу, смещение при рисовании можно вычислять путём умножения Х на offset, где offset

double offset = 80/25 * 3/4; // последнее зависит от монитора, возможно, нужно поставить 4/5, 10/16 и т.д.

_________________
http://readandlook.livejournal.com


 

Advanced member
Статус: Не в сети
Регистрация: 09.03.2004
Откуда: Кишинёв
Herod писал(а):
Это довольно неприятно делать, потому что:
1. текстовый режим
2. тут пытались не выходить за пределы ANSI

а чем текстовый режим так неугодил? И за пределы ANSI уходить необязательно.

Вот набросал пример:
Код:
#include <math.h>
#include <stdio.h>
#include <memory.h>


const int RX = 120; /* разрешение консоли: X */
const int RY = 60; /* разрешение консоли: Y */
const int DX = 60; /* координаты центра круга: X */
const int DY = 30; /* координаты центра круга: Y */
const double R = 25.0; /* радиус */
const double AR = 1.5; /* соотношение высоты символа к ширине */
const double dfi = 0.01; /* шаг угла */

int main()
{
    double fi;
    int x, y;
    char buf[RX][RY];
    memset(buf, 0, RX * RY);

    for( fi = 0.0; fi <= 2 * M_PI; fi += dfi )
    {
        x = DX + round( R * AR * sin(fi) );
        y = DY - round( R * 1 * cos(fi) );
        buf[x][y] = 1;
    }

    printf("\n");
    for( y = 0; y < RY; y++ )
        for( x = 0; x < RX; x++ )
            buf[x][y] ? printf("*") : printf(" ");

    return 0;
}


Чтобы корректно работало разрешение консоли должно(!) быть тоже что и в программе. Также нужно следить за радиусом и координатами центра, т.к. проверок лишних нет.

зы: вывод можно было организовать и по другому, но тут главное суть.


 

Member
Статус: Не в сети
Регистрация: 19.12.2005
Откуда: НН
Фото: 69
Продолжаю борьбу с кругом... Решел сделать его "круглее", т.е. второй способ Herod, но получается он немного кривоватым. Гляньте, плиз, может ошибки есть или нужно че-нить изменить:
Код:
#include <stdio.h>

int main(int argc, char *argv[], char *env[])
{

    int radius, y,s,s0,s1;
    float x0,x1,x2,x3, rx, ry, d,curvature=1.5;

    if(argc == 2)
        sscanf(argv[1], "%d", &radius);
    else
    {
        radius=20;
    }

    rx=radius;
    ry=radius/curvature;
    x1=radius;
    x3=radius;
    for(y=ry; y>=-ry; y--)
    {
        d=sqrt(ry*ry-y*y)*curvature;
        x0=rx-d;
        x2=rx+d;
        if(x0<x1)
        {
            for(s=0; s<x0; s++)
                printf(" ");
            s0=x0;
            s1=x1;
            for(s=s0; s<s1; s++)
                printf("#");
            for(s=x1; s<x3; s++)
                printf(" ");
            for(s=x3; s<x2; s++)
              printf("#");
        }
        else if(x1<x0)
        {
            for(s=0; s<x1; s++)
                printf(" ");
            for(s=x1; s<x0; s++)
                printf("#");
            for(s=x0; s<x2; s++)
                printf(" ");
            for(s=x2; s<x3; s++)
                printf("#");
        }
        printf("\t%f\t%f\t%f\t%f\t%d\t%d\n",x0,x1,x2,x3,s0,s1);
        x1=x0;
        x3=x2;
    }
}


 

Member
Статус: Не в сети
Регистрация: 15.02.2009
Откуда: Лангепас
Есть класический алгоритм Брезенхема. На его основе сделал алгоритм эллипса. Его достоинство (Брезенхема, а не эллипса) - нет умножений, делений. Одни сдвиги и +-.
Подойдёт и для псевдографики, но нужно или менять видеорежим, или переделывать его в эллипс (высота и ширина символа неодинаковы).
К, сожалению, реализация на ASMе. ;-) . Если прочитаеш ASM, могу выслать исходники всей библиотечки. Извини, Это было в далёкие студенческие, а сейчас работоспособный аналог на С/С++ времени нет, да и забыл многое :-( Когда-то, даже математические выкладки были - утеряны...


 

Junior
Статус: Не в сети
Регистрация: 15.05.2007
Вопрос может немного не в тему, но прошу отнестись с пониманием. Начал изучать програмирование в институте:) По программе идет обучение в С.
Из различных источников я понял, что язык довольно старый, но зачОтный. Проникся:)
Единственно, что напрягает писать к пояснения к командам, что я имею ввиду:
If-цикл если
While- выполнять пока
и пр.
Очень лень писать, сразу оговорюсь что многие команды понятны для тех кто знаком с английским, но все таки. Может быть кто-нибудь занимался?
Буду благодарет если кто скинет текстовый файл или ссылочку. Также интересует подобный перечень синтаксических команд для java и С++.
Заранее благодарен:)

_________________
Лучше меньше, да лучше


 

Member
Статус: Не в сети
Регистрация: 08.05.2006
Откуда: СПБ
Xelios13 во первых с каих пор if это цикл?это просто если
во вторых если хорошо знаком с англиским то можно и справочку почитать там описание команд

_________________
Мы все знаем, что Linux — это круто… он выполняет бесконечные циклы за 5 секунд.
* Линус Торвальдс


Показать сообщения за:  Поле сортировки  
Начать новую тему Новая тема / Ответить на тему Ответить  Сообщений: 1730 • Страница 51 из 87<  1 ... 48  49  50  51  52  53  54 ... 87  >
-

Часовой пояс: UTC + 3 часа


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

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


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

Перейти:  
Создано на основе phpBB® Forum Software © phpBB Group
Русская поддержка phpBB | Kolobok smiles © Aiwan