【问题标题】:Runtime error while swapping characters交换字符时出现运行时错误
【发布时间】:2011-10-26 17:26:30
【问题描述】:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void swap(char* c1,char* c2)  
{
    char temp=*c1;   
    *c1=*c2;  
    *c2=temp;  
}

void permutate( char str[], int index)    
{
    int i = 0;
    static lastChar = 0;

    if( index == strlen(str) )
    { // We have a permutation so print it
        printf("%s\n",str);
        return;
    }

    for( i = index; i < strlen(str); i++ )
    {
        if( lastChar == str[i] ) {
            continue;
        }   
        else {
            lastChar = str[i];
        }
        swap( str+index, str+i ); // It doesn't matter how you swap.
        permutate( str, index + 1 );
        swap( str+index, str+i );
    }
 }

 int main(int argc,char** argv)
 {
    permutate("abcdefgh",0);
    return 0;
 }

`

运行此程序时出现分段错误。当我自己运行交换功能时,它工作正常。

【问题讨论】:

  • 这个代码真的太可怕了。从头再写一遍!永远不要为此目的使用静态变量,将其作为指针参数传递。永远不要在循环中调用 strlen ,它每次都会计算长度,并且这个操作会为每个字符重复,这使得计算复杂性很可怕。算法本身是错误的,并且用于计算某些东西的函数中的 printf 很糟糕,您必须始终将输出的表示与逻辑分开!如果我是你的老师,我会禁止你进入课堂 :) 我没有投反对票,因为我知道学习可能很困难。
  • 好的。其实我没有写这段代码,只是从一个网站上拿来学习如何为一个字符串生成所有排列。我同意你所说的,在 for 循环中使用 strlen() 是可怕的。甚至我也不明白为什么要这样使用静态变量。就像我说的,我自己对这个程序不是很了解,所以我没有做太多修改。
  • 不理解的复制粘贴更惨。计算它的算法非常简单。但是,下次您发布新问题时,您还应该发布有关代码应该做什么的所有细节,而不仅仅是代码本身。如果你正在学习 C,我建议你尝试自己解决这个问题,你会学到更多,当然你可以做得更好!
  • 分段错误意味着您正在尝试读取或写入不属于您的进程的内存部分,这意味着您的代码存在错误,导致您的程序访问无效的内存区域。事实上,正如我所说,代码包含很多错误和坏事。
  • 将 strlen() 放入循环中是一种典型的做法。任何足够聪明的编译器都会将长度计算代码放在循环之前(几乎总是作为内联函数)

标签: c segmentation-fault


【解决方案1】:

看看这个函数调用:

permutate("abcdefgh",0);

您正在尝试修改字符串文字。这些是只读的,它是段错误的来源。

【讨论】:

    【解决方案2】:

    有更好的方法来进行随机排列。这是我在网上找到的一个例子。我冒昧地对代码进行了一些注释来解释发生了什么。

    /* this function generates an array containing a permutation of the numbers 0..n-1 */ int * rpermute(int n) { /* first, create an array */ int *a = malloc(n*sizeof(int)); int k; /* fill it in with the numbers 0..n-1 */ for (k = 0; k < n; k++) a[k] = k; /* loop backward through the array */ for (k = n-1; k > 0; k--) { /* swap the k'th element with any element that comes before it (or itself) */ int j = rand() % (k+1); int temp = a[j]; a[j] = a[k]; a[k] = temp; } return a; }

    这意味着您只需遍历数组两次:一次构建它,一次置换它。此外,每个排列都有相同的发生概率,如果您想做诸如洗牌或打乱单词之类的事情,这就是目标。

    编辑:请记住,本例中的函数分配了一个数组,但您也可以轻松地将数组作为参数传递。

    EDIT2:正在格式化!啊..总是忘记那些'

    【讨论】:

      猜你喜欢
      • 2013-06-05
      • 1970-01-01
      • 1970-01-01
      • 2016-07-23
      • 1970-01-01
      • 1970-01-01
      • 2019-10-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多