如何从函数void zmianaWierszy(...)返回主函数?

时间:2019-04-05 11:46:37

标签: c string

我的代码没有从下面的函数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 个答案:

答案 0 :(得分:1)

您的代码有很多不正确的地方,主要是:

  • 检查scanf的结果,或者您可能已经为pierwszydrugi初始化了值
  • 如果pierwszy为0或负数,则将覆盖调用程序函数的堆栈框架:tabstat[pierwszy - 1] = ...
  • 如果drugi为0或负数,则将覆盖调用程序函数的堆栈框架:tabstat[drugi - 1] = ...
  • rozmiarTab将包含第一个字符串(5)的大小,而不是应该包含的tabstat中的字符串数。因此,您的for循环将访问其他超出范围的项。但是,这可能会打印出一些垃圾或崩溃,但不太可能影响函数的返回地址。

覆盖调用者堆栈框架时,您可能会覆盖函数的返回地址,并且没人知道函数可以返回到... ...

因此,您需要检查scanf的返回值以及pierwszydrugi的值,并固定rozmiarTab的值。

答案 1 :(得分:0)

您的程序具有undefined behavior,因为它正在访问数组tabstat,其大小超出了函数zamianaWierszy()的大小。 未定义的行为包括它可能执行不正确(崩溃或无声地生成不正确的结果),或者可能偶然地完全按照程序员的意图执行。

看一下zamianaWierszy()的声明:

size_t rozmiarTab = strlen(*tabstat);

*tabstat是指向数组tabstat的第一个字符串的指针,该数组为字符串文字"abcde"strlen()将返回5(字符串的大小,不包括终止的空字符)。 for循环迭代5次(04 th 索引):

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

在这里,for循环最终访问tabstat[4],数组tabstat的有效索引从034元素)。在C语言中,在程序中使用数组时应格外小心,并确保不要访问超出其大小的数组。

如果要迭代函数tabstatzamianaWierszy()的所有元素,则必须将其大小作为参数传递,因为将数组传递给函数时,它会衰减为指针。 / p>

您应该这样做:

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()返回值,并在使用它们之前验证用户输入。诸如此类的情况-如果用户为100200输入了pierwszydrugi作为输入,该怎么办?由于tabstat的大小为4,因此使用它们会导致不确定的行为。

相关问题