【问题标题】:character array in bubble sort冒泡排序中的字符数组
【发布时间】:2018-02-05 20:24:43
【问题描述】:

我编写了以下代码来获取二维字符数组中的排序字符串

#include <stdio.h>
#include <string.h>

void swap(char *,char *);

void main() {
    char a[20][20];
    int Pass = 0, i = 0, j = 0, n;

    printf("\nHow many elements you want to sort ? >> ");
    scanf("%d", &n);
    printf("\n\nEnter the elements to be sorted :\n");
    for (i = 0; i < n; i++)
        scanf("%s", a[i]);
    for (Pass = 1; Pass < n; Pass++) {
        for (j = 0; j < n - Pass; j++)
            if (strcmp(a[j], a[j + 1]) < 0)
                swap(a[j], a[j + 1]);
        printf("\n\nPass = %d\n", Pass);
        for (i = 0; i < n; i++)
            printf(" %s  ", a[i]);  
    }   
}

void swap(char *a, char *b) {
    char *t;
    *t = *a;
    *a = *b;
    *b = *t;
}

但是,我得到的输出是

How many elements you want to sort ? >> 5
Enter the elements to be sorted :
1 2 3 4 5
Pass = 1
2   3   4   5   1  
Pass = 2
3   4   5   2   1  
Pass = 3
4   5   3   2   1  
Pass = 4
Segmentation fault (core dumped)

为什么会遇到分段错误? (如果我使用整数数组而不是字符数组,相同的代码可以正常工作)

【问题讨论】:

  • main 必须返回 int
  • 您的swap 函数错误。 1) char *t; *t=*a; :使用未初始化的变量。 2)应该交换的是一个数组而不是一个指针(或一个char)。
  • 节省时间,启用所有编译器警告:char *t; *t=*a; 应该在初始化之前警告t
  • 感谢@BLUEPIXY 指出,我通过 't=(char)malloc(20);' 为 t 分配了内存它奏效了

标签: c string char bubble-sort


【解决方案1】:

您在 swap 方法中弄乱了您的指针。目前你正在做:

void swap(char *a,char *b)
{
    char *t;
    *t=*a;
    *a=*b;
    *b=*t;
}

*t = *a 这一行似乎很可能是 SEGV 的候选对象,因为 t 是一个未初始化的字符指针。我通过 gdb 运行了你的代码,gdb 也说了同样的话:

Reading symbols from a.out...done.
(gdb) run
Starting program: /home/rohan/Documents/src/a.out 

How many elements you want to sort ? >> 5


Enter the elements to be sorted :
1 2 3 4 5

Program received signal SIGSEGV, Segmentation fault.
0x0000555555554a21 in swap (a=0x7fffffffdce0 "1", b=0x7fffffffdcf4 "2") at testBubble.c:26
26      *t=*a;
(gdb) 

你不需要 t 作为指针变量。它只是交换所需的临时变量。所以像这样改变你的方法,在我的例子中修复了分段错误:

void swap(char *a,char *b)
{
    char t;
    t=*a;
    *a=*b;
    *b=t;
}

【讨论】:

    【解决方案2】:

    入口点main应该定义为

    int main()
    

    或(带参数)

    int main(int argc, char* argv[])
    

    但可能会或可能不会返回一些值。


    在函数swap 中,您正在访问导致undefined behavior 的未初始化指针。不需要使用指针。使用普通的char

    void swap(char *a,char *b)
    {
        char t;
        t=*a;
        *a=*b;
        *b=t;
    }
    

    为了避免缓冲区溢出,你应该告诉scanf()从输入缓冲区扫描多少字符

    scanf("%19s",a[i]);
    

    并检查扫描是否成功。

    现在您应该得到正确的结果。 Here is fixed code.

    【讨论】:

    • C 规范不同意您的可接受main() 签名的有限样本,因为定义了其他实现,而不是 UB,签名是可能的。
    • 感谢您的信息。曾经有人告诉我void main 有 UB,因为那是我生活在谎言中。
    • @FilipKočica 大多数时候void main() 无论如何都会工作。这里的问题显然是未初始化的指针。
    • @FilipKočica 了解更多详情:int main() vs void main()
    【解决方案3】:

    交换函数不正确:您正在取消引用未初始化的指针t,导致未定义的行为:在您的情况下是分段错误。

    您应该将t 定义为char

    void swap(char *a, char *b) {
        char t;
        t = *a;
        *a = *b;
        *b = t;
    }
    

    但这仅适用于具有单个字符的单词。

    要交换最多 19 个字节的字,请使用:

    void swap(char *a, char *b) {
        char t[20];
        strcpy(t, a);
        strcpy(a, b);
        strcpy(b, t);
    }
    

    并在main 函数中添加一些额外的测试和保护以避免未定义的行为:

    int main(void) {
        char a[20][20];
        int Pass = 0, i = 0, j = 0, n;
    
        printf("\nHow many elements you want to sort ? >> ");
        if (scanf("%d", &n) != 1 || n < 0 || n > 20)
            return 1;
        printf("\n\nEnter the elements to be sorted :\n");
        for (i = 0; i < n; i++) {
            if (scanf("%19s", a[i]) != 1)
                return 1;
        }
        for (Pass = 1; Pass < n; Pass++) {
            for (j = 0; j < n - Pass; j++) {
                if (strcmp(a[j], a[j + 1]) < 0)
                    swap(a[j], a[j + 1]);
            }
            printf("\nPass = %d\n", Pass);
            for (i = 0; i < n; i++)
                printf(" %s", a[i]);
            printf("\n"); 
        }
        return 0;  
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-02
      • 2016-05-29
      • 2016-02-10
      • 1970-01-01
      • 2013-09-28
      相关资源
      最近更新 更多