Как вернуться к основной функции из функции void zmianaWierszy (...)? - PullRequest
0 голосов
/ 05 апреля 2019

Мой код не возвращается из функции zamianaWierszy ниже:

#include"stdio.h"
#include"string.h"
#include"stdlib.h"

void zamianaWierszy(int pierwszy, int drugi,char*tabstat[]) {
    char*pamietajPierwszy;

    size_t rozmiarTab = strlen(*tabstat);
    pamietajPierwszy = tabstat[pierwszy - 1];
    tabstat[pierwszy - 1] = tabstat[drugi - 1];
    tabstat[drugi - 1] = pamietajPierwszy;

    for (int i = 0; i < rozmiarTab; i++) {
        puts(tabstat[i]);
    }
}

int main()
{
    int pierwszy, drugi, pusty;

    char *tabstat[] = {
        (char*)"abcde",
        (char*)"fghi",
        (char*)"jklmn",
        (char*)"koder"
    };
    printf("Podaj wybrane wiersze,które chcesz przestawić:");
    scanf("%d %d", &pierwszy, &drugi);
    zamianaWierszy(pierwszy, drugi, tabstat);

    printf("Podaj po którym wierszu chcesz wstawić pusty wiersz:");
    scanf("%d", &pusty);
    pustyWiersz(pusty, tabstat);
    return 0;
}    

Я не вижу вывод printf("Podaj po którym wierszu chcesz wstawić pusty wiersz:") в основном.

Ответы [ 2 ]

1 голос
/ 05 апреля 2019

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

  • Проверьте результат сканирования или вы можете иметь инициализированные значения для pierwszy и drugi
  • Если pierwszy равно 0 или отрицательно, это перезапишет кадр стека функции вызывающей стороны: tabstat[pierwszy - 1] = ...
  • Если drugi равно 0 или отрицательно, это перезапишет кадр стека функции вызывающей стороны: tabstat[drugi - 1] = ...
  • rozmiarTab будет содержать размер первой строки (5) вместо количества строк в tabstat, как и должно быть.Итак, ваш цикл for будет обращаться к дополнительному элементу вне диапазона.Тем не менее, это может привести к печати мусора или сбоя, но вряд ли повлияет на адрес возврата вашей функции.

При перезаписи фрейма стека вызывающего абонента вы, скорее всего, перезапишите адрес возврата вашей функции, и неткаждый знает, где ваша функция может вернуться к ... :)

Итак, вам нужно проверить возвращаемое значение scanf и значения pierwszy и drugi и зафиксировать значение rozmiarTab.

0 голосов
/ 05 апреля 2019

Ваша программа имеет неопределенное поведение , поскольку она обращается к массиву tabstat сверх его размера в функции zamianaWierszy(). Неопределенное поведение включает в себя то, что оно может выполняться некорректно (либо аварийно завершать работу, либо молча генерировать неверные результаты), либо случайно выполнять то, что задумал программист.

Посмотрите на это утверждение zamianaWierszy():

size_t rozmiarTab = strlen(*tabstat);

*tabstat - указатель на первую строку массива tabstat, которая является строковым литералом "abcde".strlen() вернет 5 (размер строки без учета завершающего нулевого символа).Цикл for повторяется 5 раз (от 0 до 4 th index):

for (int i = 0; i < rozmiarTab; i++) {
    puts(tabstat[i]);    // <===========
}

Здесь цикл for завершается доступом к tabstat[4] и действительный индекс массива tabstat от 0 до 3 (4 элементов).В Си вы должны быть очень осторожны при использовании массива в вашей программе и следить за тем, чтобы не обращаться к массиву сверх его размера.

Если вы хотите выполнить итерацию для всех элементов tabstat в функции zamianaWierszy(),вы должны передать его размер в качестве аргумента, потому что когда вы передаете массив функции, он затухает в указателе.

Вы должны сделать:

void zamianaWierszy(int pierwszy, int drugi, char*tabstat[], size_t tabstat_sz); //declaration

// From the main(), you should call zamianaWierszy() like this
int main() {
    int pierwszy, drugi;

    char *tabstat[] = {
               "abcde",
               "fghi",
               "jklmn",
               "koder"
    };
    ......
    ......
    scanf("%d %d", &pierwszy, &drugi);
    // Make sure to validate the input from user
    ......
    ......
    zamianaWierszy(pierwszy, drugi, tabstat, sizeof(tabstat)/sizeof(tabstat[0]));
    ......
    ......
}

void zamianaWierszy(int pierwszy, int drugi, char*tabstat[], size_t tabstat_sz) {
    char*pamietajPierwszy;

    size_t rozmiarTab = tabstat_sz;   // No need of rozmiarTab variable, you can directly use tabstat_sz
    pamietajPierwszy = tabstat[pierwszy - 1];
    tabstat[pierwszy - 1] = tabstat[drugi - 1];
    tabstat[drugi - 1] = pamietajPierwszy;

    for (int i = 0; i < rozmiarTab; i++) {
        puts(tabstat[i]);
    }
}

Кроме того, вы должны проверить scanf() возврат и должен проверить ввод пользователя перед их использованием.Случаи типа - что, если пользователь дал ввод как 100 и 200 для pierwszy и drugi.Их использование приведет к неопределенному поведению, поскольку размер tabstat равен 4.

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