невозможно вернуть корректную переменную в функцию переменного тока - PullRequest
0 голосов
/ 22 февраля 2019

Я хочу, чтобы эта программа отслеживала количество циклов, в течение которых пользователь вводит значение, программа работает хорошо, но функция cycler() не возвращает соответствующее значение.Буду благодарен всем, кто мне здесь поможет.

#include <stdio.h>
#include <stdlib.h>

int cycle=0;

int main()
{
    startProgram(0);//If status is 1, the program will exit
    return 0;
}

void startProgram(int status) {
    if (status == 0) {

        printf("Enter a value\n");
        int input;
        scanf("%d",&input);
        printf("input is: %d\n",input);

        /*
           Here is where i need help!!!!!!!!!!
           When the cycler() is called, i want it to pass in the value of current cycle,
           The value of cycle has first been initialized to 0  
        */
        int cycle = cycler(cycle); 

        printf("Cycle Number : %d\n",cycle);

        resetProgram(input);

    } else {
        printf("Exiting");
    }
}

int cycler(int x){
    int ret = x++;
    return ret;
}

void resetProgram(int status){
    if ((status > 0) && (status < 12)) {
        startProgram(0);
    } else {
        printf("\nExit\n");
    }
}

Ответы [ 5 ]

0 голосов
/ 22 февраля 2019

Трудно ответить на ваш вопрос, не зная точно, какой результат вы ожидаете, но я думаю, вы хотите, чтобы "номер цикла" увеличивался при каждом вызове.Если это так, то вам нужен какой-то способ отслеживания предыдущего значения переменной.Есть несколько способов сделать это, но трудно прописать «правильный» способ, когда в структуре самого кода есть некоторые явные ошибки.

Большая ошибка здесь - это «взаимная рекурсия»который был упомянут в одном из комментариев.Представьте, что у вас есть две функции, например

void a()
{
    // do something
    b();
}

void b()
{
    // do something
    a();
}

Здесь вы можете видеть, что a вызывает b, а b вызывает a.Эта программа будет повторяться вечно.Проблема в том, что каждый раз, когда функция вызывается в C, в оперативной памяти выделяется немного памяти, чтобы отслеживать, в какой функции вы находитесь. Поскольку ни a, ни b не разрешено завершать, или,более формально, к «return», эта память никогда не освобождается.Эта программа в конечном счете исчерпает память и вылетает(На самом деле это может не произойти из-за того, что называется «встраивание», но это только потому, что это надуманный пример.)

Лучший способ сделать это в C - использовать while или forloop.

void a()
{
    // do something
}

void b()
{
    // do something
}

int main()
{
    while(1)
    {
        a()
        b()
    }
}

while Циклы будут повторяться до тех пор, пока значение в скобках не равно 0.Так как значение (1) никогда не будет 0, эта структура будет зацикливаться вечно, и у нее не будет той же проблемы с взаимной рекурсией, поскольку a и b оба могут завершаться, и, следовательно, их памятьбудет освобожден после каждого вызова.

Таким образом, чтобы решить проблему, о которой вы действительно спрашивали, можно ввести static переменных, как это было предложено (правильно) в другом ответе, или можно было бы реструктурировать их код, не требуя их,Я предпочитаю следующий подход, где startProgram() вызывается только один раз, и поэтому нет необходимости, чтобы cycle был статическим.

void startProgram()
{
    int statusIsGood = 1;
    int cycle = 1;

    while(statusIsGood)
    {
        int input;

        scanf("%d", &input);

        statusIsGood = getStatus(input);

        printf("Cycle count: %d", cycle);

        // In practice, it makes more sense to simply do
        // cycle++; and get rid of `nextCycle()` all together
        cycle = nextCycle();
    }
}

int nextCycle(int cycle)
{
    return cycle + 1;
}

int getStatus(int input)
{
    if (input <= 0 || input >= 12)
        return 1;
    else
        return 0;
}
0 голосов
/ 22 февраля 2019

Объявление int cycle снова в startProgram() вызывает проблемы

#include <stdio.h>
#include <stdlib.h>

int cycle=0;
void resetProgram(int status);
int cycler(int *x){
    return *x+1;
}

void startProgram(int status) {
    if (status == 0) {

        printf("Enter a value\n");
        int input;
        scanf("%d",&input);
        printf("input is: %d\n",input);

        /*
           Here is where i need help!!!!!!!!!!
           When the cycler() is called, i want it to pass in the value of current cycle,
           The value of cycle has first been initialized to 0  
        */
        //in your code you declared cycle again local variable was given priority
        cycle = cycler(&cycle); 

        printf("Cycle Number : %d\n",cycle);

        resetProgram(input);

    } else {
        printf("Exiting");
    }
}

void resetProgram(int status){
    if ((status > 0) && (status < 12)) {
        startProgram(0);
    } else {
        printf("\nExit\n");
    }
}




int main()
{
    startProgram(0);//If status is 1, the program will exit
    return 0;
}
0 голосов
/ 22 февраля 2019

вместо x++ в cycler() do ++x.

Проблема с int ret = x++; заключается в том, что он возвращает значение x до его увеличения.и затем возвращается ret с тем же значением (которое не увеличивается).

Предположим, x равно 0.0 - начальное значение cycle.

После того, как выражение int ret = x++; x увеличится до 1, но ret будет присвоено 0 (все еще старое значение), и будет возвращено это 0.

Вышеуказанное событие будет происходить каждый раз.

Есть еще одна проблема: вы определили cycle 2 раза: глобально и локально.Я думаю, что вы должны удалить int до int cycle = cycler(cycle);

0 голосов
/ 22 февраля 2019

Возможно, вы имеете в виду Counter вместо Cycler.Это обычная структура данных, которая подсчитывает возникновение чего-либо.Вы можете просто использовать переменную int для этого, но я бы лучше определил структуру для нее.Это позволяет вам иметь счетчик «черного ящика», который имеет только несколько определенных операций.В этом случае это будет «считать» и «получить», чтобы увидеть текущее значение счетчика.

Код для этого:

typedef struct {
    int value;
} Counter;

void counter_init(Counter *ctr) {
    ctr->value = 0;
}

void counter_up(Counter *ctr) {
    ctr->value++;
}

int counter_get(const Counter *ctr) {
    return ctr->value;
}

Это может выглядеть какмного кода, но оно того стоит.Приятно то, что вы больше не объявляете переменную int (которая в принципе может использоваться для чего-либо: вычисления, подсчет, ID, дескриптор файла), но переменную Counter, и в этом определении уже указывается точное назначение этой переменной.

Counter ctr;
counter_init(&ctr);

while (fgetc(stdin) != EOF) {
    counter_up(&ctr);
}

printf("You entered %d bytes.\n", counter_get(&ctr));

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

Обычная int версия кода:

int ctr = 0;

while (fgetc(stdin) != EOF) {
    ctr++;
}

printf("You entered %d bytes.\n", ctr);

Разница в том, что если вы передадите этот счетчиквокруг, так что другая функция может изменить его, параметр этой функции int *ctr, а тип int * не выражает много.Это может быть указатель на одно целое или массив целых чисел.Наличие параметра Counter *ctr делает намерение очень ясным.

Стоит ли ситуация, когда такие издержки при определении пользовательского типа данных являются выбором, который вы должны сделать.Для каждой ситуации индивидуально.

0 голосов
/ 22 февраля 2019

Поскольку вы уже объявили cycle как глобальную переменную, лучший способ вести подсчет количества циклов - это cycle++.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...