交换函数中的分段错误

时间:2015-10-01 14:04:50

标签: c++

我正忙着为我的学习写一行代码。 我已经完成了很多任务,但我仍然遇到同样的问题。 在交换功能上,当输入的字符(字和字2)不在主字典中时,我会继续遇到分段错误。串。 有人可以向我解释导致问题的原因以及我如何解决问题?对不起,如果有什么不清楚,我刚刚开始学习c ++。

发生分段错误的代码:

  void swapWords(char **dict, char *word, char *word2)
{
    int i; 
    int d;
    int x;
    int y;
    char *tmp;


    while (1){  
        for(i = 0; i < MAX_NUMBER_OF_WORDS; i++)
        { 
            if(strcmp(word, dict[i]) != 0)
            {    
                if(i == MAX_NUMBER_OF_WORDS -1)
                {
                    printf("Cannot swap words. Atleast one word missing in the dictionary.\n");
                    goto error;
                }
            }
            else
            {
                x = i;
                break;  
            }

        }
        for(d = 0; d < MAX_NUMBER_OF_WORDS; d++)
        { 
            if(strcmp(word2, dict[d]) != 0)
            {    
                if(d == MAX_NUMBER_OF_WORDS -1)
                {
                    printf("Cannot swap words. Atleast one word missing in the dictionary.\n");
                    goto error;
                }
            }
            else
            {
                y = d;
                break;
            }

        }

        tmp = dict[x];
        dict[x] = dict[y];
        dict[y] = tmp;
        error: break;
    }
}

整个代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>

#define MAX_NUMBER_OF_WORDS 10

void swapWords(char **dict, char *word, char *word2)
{
    int i; 
    int d;
    int x;
    int y;
    char *tmp;


    while (1){  
        for(i = 0; i < MAX_NUMBER_OF_WORDS; i++)
        { 
            if(strcmp(word, dict[i]) != 0)
            {    
                if(i == MAX_NUMBER_OF_WORDS -1)
                {
                    printf("Cannot swap words. Atleast one word missing in the dictionary.\n");
                    goto error;
                }
            }
            else
            {
                x = i;
                break;  
            }

        }
        for(d = 0; d < MAX_NUMBER_OF_WORDS; d++)
        { 
            if(strcmp(word2, dict[d]) != 0)
            {    
                if(d == MAX_NUMBER_OF_WORDS -1)
                {
                    printf("Cannot swap words. Atleast one word missing in the dictionary.\n");
                    goto error;
                }
            }
            else
            {
                y = d;
                break;
            }

        }

        tmp = dict[x];
        dict[x] = dict[y];
        dict[y] = tmp;
        error: break;
    }
}

void removeWord(char **dict, char *word)
{
    int i;
    int d;
    for(i = 0; i < MAX_NUMBER_OF_WORDS; i++)
    { 
        if(strcmp(dict[i], word) == 0)
        {   dict[i] = NULL;
            for(d = i+1; d < MAX_NUMBER_OF_WORDS; d++)
            { if(dict[d] == NULL)
                { dict[i] = dict[d-1];
                    dict[d-1] = NULL;
                    break;
                }

            }
            break;
        }
    }
}

void printDict(char **dict)
{
    int i = 0;

    if(dict[0] == NULL)
    {
        printf("The dictionary is empty.\n");
    }
    else{
    while (dict[i] != NULL)
    {
        printf("- %s\n", dict[i]);
        i++;
    }
    }
}

void addWord(char **dict, char *word)
{
    int d;
    char *word1;

            for(d = 0; d < MAX_NUMBER_OF_WORDS; d++)
            {
                if (dict[d] == NULL)
                {           
                word1 = (char*) malloc(sizeof(char)*(strlen(word) + 1));
                strcpy(word1, word);
                dict[d] = word1;

                break;
                }
            }
}
int numberOfWordsInDict(char **dict)
{
    int i = 0;
    int d;

    for (d = 0; d < MAX_NUMBER_OF_WORDS; d++){
    if(dict[d] != NULL)
    {
        i++;
    }
}

    return i;
}

int main()
{
    char *dict[MAX_NUMBER_OF_WORDS] = {};
    char word[36];
    char word2[36];
    char c;
    int i;
    while(printf("Command (a/p/r/s/q): "))
    {
    scanf(" %c", &c);
    switch (c){
    case 'p':   printDict(dict);
                break;
    case 'a':   printf("Enter a word: ");
                scanf("%s", word);
                addWord(dict, word);
                break;
    case 'n':   i = numberOfWordsInDict(dict);
                printf("%d\n", i);
                break;
    case 'r':   printf("Remove a word: ");
                scanf("%s", word);
                removeWord(dict, word);
                break;
    case 's':   printf("Swap two words:\n");
                printf("Enter first word: ");
                scanf("%s", word);
                printf("Enter second word: ");
                scanf("%s", word2);
                swapWords(dict, word, word2);
                break;
    case 'q':   return 0;
            }
        }
}

3 个答案:

答案 0 :(得分:1)

很可能这里发生了分段错误:

if(strcmp(word, dict[i]) != 0)

事实上很可能是我&gt;变得比dict的大小大,如果你的dict有3个元素并且你试图访问第4个你正在访问一个未知区域或ram,这会导致分段错误。 解决方案是确保你的for循环停止在字典的最后一个元素,并在上面的注释中提出了解决方案πάνταῥεῖ。

答案 1 :(得分:1)

如果你自己发现了实际的错误,那么你作为一名学生的学习将是最有帮助的,尽管Marco和πάνταῥεῖ可能是正确的。但是,这里有几点要考虑,因为这绝对不是你作为程序员的最后一个段错误问题(我本月至少有20个)。

分段错误几乎总是由尝试修改或读取内存的代码引起的,该代码无权读取或修改。程序启动时,会给它一块内存(RAM)来处理。出于安全原因,不允许任何程序使用该块之外的内存。还有其他限制。

作为一般规则,如果您尝试在数组末尾读取内存,则很可能会出现段错误,或者在其他情况下会出现乱码数据。关于它的官方字实际上来自C,C ++的母语,因为访问数组末尾会导致“未定义的行为”。或者,正如曾经在USENET上所说的那样,“编译器让恶魔飞出你的鼻子是合法的”。这种行为完全不可预测。值得庆幸的是,这种未定义的行为通常是一个段错误。

顺便说一句,如果您尝试访问未初始化的数组,可能会发生类似的奇怪现象。

现在,由于您是通过循环访问数组的元素,另一个可能的原因是您的循环继续超出您的想象。有时修改代码是有帮助的,这样就可以在每次迭代时打印出循环的迭代器(在你的情况下为i)。如果循环超出应有的范围,这可以帮助您捕获。

简而言之,请检查......

  1. 在尝试读取或写入之前,我是否初始化了所有数组 他们?
  2. 我的循环是否在我预期的位置开始和停止?检查 “一个一个”的错误(即从1开始而不是0),无限 循环(忘记增加迭代器或停止条件是 从来没有真实)和其他逻辑错误。
  3. 我是否尝试读取/写过数组的末尾?
  4. 如果我正在使用C字符串,我是否忘记了NULL终结符?
  5. 除了你应该学习如何使用的调试器之外,像 valgrind 这样的工具有助于找到内存错误的原因。通常,它可以指向您发生段错误的确切代码行。

答案 2 :(得分:1)

我已经弄明白自己问题出现在strcmp中了。我知道自己找出问题是最好的学习方法,我尝试过,但我无法弄清楚为什么它会返回一个seg故障。由于这是我的第五个任务,我只是想知道数组和指针是如何工作的。我假设数组已经初始化为'NULL',因为我已经在addWord函数中将指针与'NULL'进行比较。假设这对我来说非常愚蠢。我可能不会自己解决这个问题,但它仍然是我不会忘记的事情。