1

Тема: Запис різниці двох стеків у третій.

Добрий день, виконуючи завдання: Створити два стеки, записавши в них цілі числа. Записати в третій стек числа, що рівні
різницям відповідних значень з першого і другого стеків. Вивести на друк вміст усіх трьох стеків (Враховуючи ще вимоги, які надав викладач: Введення інформації у вихідний стек двома (для чисел - трьома) способами: - Читання з текстового файлу; - Введення за клавіатури; - для числових рандомні значення;) виникла така проблема, я зовсім не розумію як організувати введення даних до третього стека. Тобто, спочатку я роблю різницю значень (віднімання) чисел з двох стеків, а потом вже записую у третій? Начебто функцію я написала, але не думаю, що вона буде працювати так, як мені потрібно. Поясніть будь ласка, як це буде правильно зробити

Мій код:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define FILENAME "Stack.txt" //мій текстовий файл
#define FILEEE "StackTwo.txt"
typedef struct//для стеку масив
{
    int msize; //макс размер
    int top; //отслеживать размер стэка
    int *elem;
}Stack;

Stack * st = NULL; //проконтролювати стеки
Stack * st2 = NULL;
Stack * st3 = NULL;

Stack * create(int cap) //виділяю пам'ять
{
    st = (Stack *)malloc(sizeof(Stack));
    if (st == NULL)
    {
        printf("\nЕлементи не знайдені..\n");
    }
    st->msize = cap; //розмір стека
    st->top = -1;
    st->elem = (int *)malloc(st->msize * sizeof(int));
    return st;
}
int isEmpty(Stack *st) //stack порожній чи ні?? 
{
    return st->top == -1;
}
int isFull(Stack *st) 
{
    return st->top == st->msize - 1;
}
void push(Stack *st, int element) //додаю елемент з клавіатури
{
    if (isFull(st))
    {
        printf("\nСтек заповнено..\n");
        return;
    }
    st->elem[++st->top] = element; // +elem і індекс збільшую
}
void random(Stack * st, int cap) //рандом
{
    int i, num;
    srand(time(NULL)); 
    for (i = 0; i < cap; i++) 
    {
        num = rand() % 10; 
        push(st, num);
    }
}
void pushStackFile(Stack * st) //запис в текстовий файл перший стек 
{
    FILE * fp = fopen("Stack.txt", "a");
    if (!fp) 
    {
        printf("\nНе вийшло відкрити файл..\n");
        return;
    }
    int elem;
    while (fscanf(fp, "%d", &elem) != EOF) 
    {
        push(st, elem);
    }
    fclose(fp);
}
void saveStackFile(Stack * st) //зберігаю
{
    FILE * fp = fopen("Stack.txt", "w"); 
    if (!fp)
    {
        printf("\nНе вийшло відкрити файл..\n");
        return;
    }
    int i;
    for(i = 0; i <= st -> top; i++)
    { 
        fprintf(fp, "%d\t", st->elem[i]); 
    }    
    fclose(fp);
}
void pushStackFILE(Stack * st2) //запис в текстовий файл ДЛЯ ДРУГОГО СТЕКА
{
    FILE * fp = fopen("StackTwo.txt", "a");
    if (!fp) 
    {
        printf("\nНе вийшло відкрити файл..\n");
        return;
    }
    int elem;
    while (fscanf(fp, "%d", &elem) != EOF) 
    {
        push(st2, elem);
    }
    fclose(fp);
}
void saveStackFILE(Stack * st2) //сохраняю ДЛЯ ВТОРОГО СТЕКА
{
    FILE * fp = fopen("StackTwo.txt", "w"); 
    if (!fp)
    {
        printf("\nНе вийшло відкрити файл..\n");
        return;
    }
    int i;
    for(i = 0; i <= st2 -> top; i++)
    { 
        fprintf(fp, "%d\t", st2->elem[i]); 
    }    
    fclose(fp);
}
int pop(Stack * st) //витягнути
{
    if(isEmpty(st))
    {
        printf("\nСтек порожній...\n");
        return;
    }
    if (st->top > 0) 
    {
        return st->elem[--st->top];
    }
    return -1;
}
void print(Stack * st) //Друк елементів
{
    int i;
    printf("\n------------\n");
    printf("\nСтек: ");    
    if(isEmpty(st))
    {
        printf("\nСтек порожній...\n");
    }
    else
    {
        for(i = st->top; i >= 0; i--)
        {
            printf("%d ", st->elem[i]);
        }
    }
    printf("\n------------");
    printf("\n\n");
}
void diff(Stack * st, Stack * st2, Stack * st3) //=начебто різниця.. але..
{
    int diff;
    while (!isEmpty(st) && !isEmpty(st2)) 
    {
        diff = pop(st) - pop(st2);
        push(st3, diff); 
    }
    while (!isEmpty(st)) 
    {
        push(st3, pop(st));
    }
    while (!isEmpty(st2)) 
    {
        push(st3, -1 * pop(st2)); 
    }
}
void menu() //Вибір між (стеками)
{
    int ch, cap;
    system("cls");
    while(1)
    {
        printf("\n------------------------\n");
        printf("------------------------\n");
        printf("Виберіть стек, який бажаєте заповнити\n");
        printf("|1| - Перший стек\n|2| - Другий стек\n|3| - Третій стек\n|0| - Завершення роботи програми\n");
        printf("\nВаш вибір --> ");
        scanf("%d", &ch);
        system("cls");
        switch(ch)
        {
            case 1:
                menu_stackone();
                break;
            case 2:
                menu_stacktwo();
                break;
            case 3:
                diff(st, st2, st3);
                printf("\nПерший");
                print(st);
                printf("\nДругий");
                print(st2);
                printf("\nТретій");
                print(st3);
                break;    
            case 0:
                exit(0);
                break;
            default:
                printf("\nМеню перегляньте спочатку..\n");
                break;        
        }
    }
}
void menu_stackone() //Меню першого стека
{
    int ch, element, cap;
    char filename[35];
    printf("Введіть розмір стеку:  ");
    scanf("%d", &cap);
    Stack * st = create(cap);
    system("cls");
    while(1)
    {
        printf("\n------------------------\n");
        printf("------------------------\n");
        printf("Яким чином здійснити введення інформації у вихідний стек?\n");
        printf("|1| - Читання з текстового файлу\n|2| - Введення з клавіатури\n|3| - Рандомні значення\n|4| - Вихід із пункту\n");
        printf("\nВаш вибір --> ");
        scanf("%d", &ch);
        system("cls");
        switch(ch)
        {
            case 1:
                printf("\nВведіть елемент: ");
                scanf("%d", &element);
                push(&st, element); //Заштовхую елемент у стек
                saveStackFile(&st); //записую у текстовий файл
                pushStackFile(&st); //зберігаю
                system("C:\\Windows\\System32\\notepad.exe Stack.txt"); //ДРУК!
                break;
            case 2:
                printf("\nВведіть елемент: ");
                scanf("%d", &element); //ввожу 
                push(st, element); 
                print(st);
                break;
            case 3:
                printf("\nЗаповнюю стек рандомними значеннями...\n");
                random(st, cap);
                print(st);
                break;    
            case 4:
                return menu();
                break;    
            default:
                printf("\nВи звісно можете щось клацнути, але програма не тільки для цього\n");    
                break;    
                
        }
    }
}
void menu_stacktwo() //меню для другого стека
{
    int ch, element, cap;
    printf("Введіть розмір стеку:  ");
    scanf("%d", &cap);
    Stack * st2 = create(cap);
    system("cls");
    while(1)
    {
        printf("\n------------------------------\n");
        printf("------------------------------\n");
        printf("Яким чином здійснити введення інформації у вихідний стек?\n");
        printf("|1| - Читання з текстового файлу\n|2| - Введення з клавіатури\n|3| - Рандомні значення\n|4| - Вихід із пункту\n");
        printf("\nВаш вибір --> ");
        scanf("%d", &ch);
        system("cls");
        switch(ch)
        {
            case 1:
                printf("\nВведіть елемент: ");
                scanf("%d", &element);
                push(&st2, element); //заштовхую элемент в стек
                saveStackFILE(&st2); //записую у текстовий файл
                pushStackFILE(&st2); //зберігаю
                system("C:\\Windows\\System32\\notepad.exe StackTwo.txt"); //друкк!
                break;
            case 2:
                printf("\nВведіть елемент: ");
                scanf("%d", &element); //ввожу лемент
                push(st2, element); 
                print(st2);
                break;
            case 3:
                printf("\nЗаповнюю стек рандомними значеннями...\n");
                random(st2, cap);
                print(st2);
                break;
            case 4:
                return menu();
                break;    
            default:
                printf("\nВи звісно можете щось клацнути, але програма не тільки для цього\n");    
                break;    
        }
    }
}

int main ()
{
    system("chcp 1251");
    menu();
    return 0;
}

2 Востаннє редагувалося koala (05.05.2023 13:59:46)

Re: Запис різниці двох стеків у третій.

Ніяк це правильно зробити не можна. У стеку за визначенням можна мати доступ лише до одного елемента (верхнього). Тобто прочитати стек означає його знищити. А в умові написано "числа, що рівні різницям відповідних значень з першого і другого стеків". У першому і другому стеках не буде значень, якщо сформувати третій стек за цією умовою. Ну і далі "вивести на друк вміст усіх трьох стеків" - так перший і другий уже порожні, нащо їх виводити? Максимум, що можна - це читати в проміжні структури (можливо, ті ж стеки) і потім відновлювати оригінальні стеки, але про це має бути сказано в умові. Ну, або можна організувати доступ до пам'яті стеків як НЕ стеків, але це має ще менше сенсу. Тобто або ви викинули з умови суттєві частини, або ваш викладач не розуміє, що таке стек, або він не вміє формулювати задачі.

У функції diff є дві проблеми. По-перше, ніде не сказано, що робити з "зайвими" елементами, і, скоріш за все, їх треба ігнорувати (або виводити повідомлення про помилку, якщо розміри різні); а по-друге, третій стек формується у протилежному напрямку, тобто якщо було (10,20,30) і (1,2,3), то в результаті має бути (9,18,27), а цей код дасть (27,18,9).

"Вивести на друк" - стандартне формулювання для виведення на пристрій користувача; починаючи з 70-х, це зазвичай монітор.

Частина коментарів іноземною мовою. Меню зроблене недбало, ви ніколи з підменю не повертаєтеся. Приберіть усі виклики menu(), окрім як із main.

Подякували: leofun011

3

Re: Запис різниці двох стеків у третій.

  1. Було б дуже файно замінити російські коментарі - українськими.

  2. Вам компілятор взагалі ніяких помилок не видав? Особливо на return з функції pop, яка очікує повернення int.

  3. Весь код в цілому дуже важко читати, зробіть хоча б якісь логічні розбиття.

  4. Різниця.. Ну, можна якось так це робити:

// псевдокод
int first_stack_size = size(first_stack); // get actuall size of the first stack
int second_stack_size = size(second_stack); // get actuall size of the second stack

int count = min(first_stack_size, second_stack_size);
for ( ; count > 0; --count) {
    int diff = pop(first_stack) - pop(second_stack);
    push(out_stack, diff);
}