Рисовать случайных 1 и 0


Мне было интересно, если кто-нибудь, будьте так добры, взгляните на этот код я написал для практики. Скажи мне, что я делаю не так, где я могу оптимизировать, что-нибудь.

Что этот код делает (в терминале) нарисовать кучу случайных 1 и 0, но я добавил эффект вроде решетки. Основная часть этого я получил помощь здесь.

#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>

int main (int argc, char *argv[]){      //check for whitch effect to print
    switch(*argv[1]){
        case '1': lattus();break;
        case '2': normal();break;
        default: printf("1 = lattus effect | 2 = static effect\n");break;
    }
}

char *randstring (char *buffer, int length){        //genertate a random number
    int i = length;
    while(--i >= 0) {
        buffer[i] = (rand() % 2) ? '1' : '0';
    }
    buffer[length] = 0;
    return buffer;
}

int normal(){           // normal drawing of 1's and 0's
    struct winsize w;
    ioctl(0, TIOCGWINSZ, &w);
    int width = w.ws_col;
    int height = w.ws_row;      //get terminal width and height
    char buffer[width*height + 1];  //create a buffer big enough to hold one draw to the screen
    int i = 25;
    while(i-- >= 0) {
        printf("%s\n", randstring(buffer, width*height));   //draw to screen
        usleep(90000);
    }
    system("clear");        //clear screen
}

int lattus (void){
    struct winsize w;
    ioctl(0, TIOCGWINSZ, &w);
    int width = w.ws_col;       //get the terminal width
    char buffer1[width + 1];    //create 3 buffers for each segment
    char buffer2[width + 1];    //each big enough to hold the width of the terminal
    char buffer3[width + 1];
    int first = 1;          //how many before the space
    int second = width - 8;     //how many in the middle of the space
    int third = 1;          //how many at the end of the space
    int i = 1000;           //draw 1000 lines
    int on = 0;         //switch for growing and shrinking
    while(i-- >= 0){
        usleep(9000);
        if(first == 1 && third == 1 && second == width - 8 | second == width - 9){  //is it at min?
            if(second % 2 == 0){        //is it an even number (had problems with buffer if it was odd)
                second = second - 2;
            }else{
                second = second - 3;
            }
            first ++;
            third ++;
            on = 0;     //keep growing
        }else if(first == (width - 8) / 2 && third == (width - 8) / 2 && second == 2){  //untill it gets to max
            if(second % 2 == 0){
                second = second + 2;
            }else{
                second = second + 1;
            }
            third --;
            first --;
            on = 1;     //start shrinking
        }else if(on == 0){  //else if suppost to grow, grow
            second = second - 2;
            third ++;
            first ++;
        }else if(on == 1){  //else if suppost to shrink shrink
            second = second + 2;
            third --;
            first --;
        }else{
            break;
        }
        printf("%s   %s   %s\n", randstring(buffer1, first), randstring(buffer2, second), randstring(buffer3, third));  //print it out
    }
    system("clear"); //clear screen
}


457
12
задан 21 июня 2009 в 11:06 Источник Поделиться
Комментарии
4 ответа

Несколько советов:

Во-первых, переменной длины массивов разрешается только в C99:

char buffer1[width + 1];

Если код должен быть строго в формате ANSI C, то можно было бы сделать указатель на массив и использовать функции, как Танос или с памятью выделить память для массива:

char* buffer = malloc(sizeof(char) * (width + 1));

(Потом, при необходимости, буфер будет инициализирован, или с памятью используется вместо того, чтобы инициализировать и выделить сразу.)

Во-вторых, читабельность кода:

if(second % 2 == 0){
second = second - 2;
}else{
second = second - 3;
}

Может быть лучше написать так:

if (second % 2 == 0) {
second = second - 2;
} else {
second = second - 3;
}

Это может выглядеть как придирки, но это делает его проще для людей, чтобы читать ваш код и понять, что происходит. Кодирование-это форма коммуникации, а также-сделать его проще для других, чтобы читать, и другие смогут лучше понять, что вы пытаетесь достичь.

Этот переключатель заявление может быть также улучшилось:

switch(*argv[1]){
case '1': lattice();break;
case '2': normal();break;
default: printf("1 = lattice effect | 2 = static effect\n");break;
}

К:

switch(*argv[1]) {
case '1':
lattice();
break;
case '2':
normal();
break;
default:
printf("1 = lattice effect | 2 = static effect\n");
}

Кроме того, добавлять разрывы строк между отдельными блоками заявление, в котором выполняют одну задачу может улучшить читаемость.

Там, кажется, обильное использование во время петли, но я не вижу ни одного за цикл - для петель, возможно, более полезны для проведения "контр"-виды деятельности, такие как выполнение повторений в течение определенного количества итераций:

int i;
for (i = 0; i < 100; i++) {
/* Action to perform 100 times */
}

Базовая структура для цикла выглядит следующим образом:

for (initial-condition; loop-condition; expression-on-each-iteration) {
/* Action to perform on each iteration. */
}

(Примечание: название условия не являются официальными именами, я их выдумал, чтобы описать, что они для.)

В первоначальном состоянии это делать, когда за первый цикл начинается. Много раз, это используется для инициализации переменной счетчика некоторое значение. Например, я настроен на 0.

В цикле условие - это выражение, которое вычисляется в начале каждой итерации, который определяет, будет ли цикл должен продолжаться. Если выражение истинно, то цикл выполняется, а если ложно, то цикл завершается.

На выражение-на каждой итерации - это то, что совершается в начале каждой итерации цикла, если итерации пройдет. Обычно, эта часть используется для приращения счетчика используется для управления циклом.

14
ответ дан 21 июня 2009 в 11:06 Источник Поделиться

Я хотел бы предложить, чтобы проверить, если АГДС действительно 1 или больше, прежде чем пытаться ссылаться на него в переменной argv[1]

int main (int argc, char *argv[])
{
if(argc != 1)
{
printf("1 = lattice effect | 2 = static effect\n");
return 1;
}
switch(*argv[1]) {

У меня плохие воспоминания снят указатели :-)

11
ответ дан 21 июня 2009 в 11:06 Источник Поделиться

Стандарт ANSI С89 требует процедур, которые должны быть объявлены прежде чем они используются. Какой компилятор вы используете? ССЗ, по крайней мере, будет жаловаться на это. Если вы используете GCC и стремясь к С89 совместимости попробуйте использовать параметры компилятора "-стены -Анси-педантичный", чтобы сделать компилятор более подробно.

Если вы переместите ваш "основной" процедуры в нижней части кода, Вы сможете решить эту проблему. Кроме того, можно предоставить подписи для lattuce и нормальным выше главной, как так

int lattus (void);

Глядя на эту линию

 if(first == 1 && third == 1 && second == width - 8 | second == width - 9){      //is it at min?

Должно быть логическое или после -8?

 if(first == 1 && third == 1 && second == width - 8 || second == width - 9){      //is it at min?

Некоторые скобки вокруг булевых операторов будет там понятнее.

Вы используете c++-стиле // комментарии, которые не поддерживаются С89. Они могут быть переписаны так:

 if(first == 1 && third == 1 && second == width - 8 || second == width - 9){      /* is it at min? */

3
ответ дан 21 июня 2009 в 02:06 Источник Поделиться

Кроме того, избегайте системы(). Это зло. Вместо системы("чистые"), предоставить свой собственный. Использовать

write (1, "\033[2J", 4);

2
ответ дан 21 июня 2009 в 02:06 Источник Поделиться