无法理解导致此分段错误的原因(C ++中的C风格字符串)

时间:2017-02-09 23:42:39

标签: c++ string pointers

这个问题来自一本教科书:编程 - 使用C ++的原理和实践(第二版)作者:Bjarne Stroustrup。

注意:我已经解决了这个问题,问题来自于我对早期尝试解决方案失败的理解不足。我知道这是一个很长的问题,但我觉得理解这个概念很重要。

问题在于:

  

编写一个函数char * findx(const char * s,const char * x),它在s中找到第一次出现的C风格字符串x。

我可以很容易地查找解决方案(或改变声明函数的方式),但如果我觉得这个问题是练习的重点,那么我就这样做了。请随意更正我在此问题中所做的任何错误陈述。此外,请原谅我,如果这是一个过度复杂,但我真的不明白这一点。

对于初学者来说,这是我的函数以编译的方式编写,但在运行时导致段错误:

char* findx(const char* s, const char* x) {

  if (s==nullptr || x == nullptr) return nullptr;   //if no string, return nullptr
  int s_size = strlen(s);            
  int x_size = strlen(x);
  char* ptr_to_first_occ = nullptr;                 //initialize pointer to 1st occ

  for (int i = 0; i < (s_size-x_size); ++i) {       //end with the last char that 
                                                    //can hold string x to the end
    for (int j = i; j < x_size; ++j) {              //check if the first char match
        if (s[j] != x[j]) ptr_to_first_occ = nullptr; //if it doesn't, set to 0
                                                     //and move on
        else ptr_to_first_occ = (char*)(s) + i;      //set equal to first occ if ==
    }
  }
  if (ptr_to_first_occ) return ptr_to_first_occ;
  else return nullptr;
}

主要是:

const char* y = "Hey how are you?";
const char* t = "you";
char* p = nullptr;
p = findx(y, t);
cout << *p << endl;

这个编译的唯一原因是由于我将const char转换为char *,这不是正确的做事方式,但我很确定segfault不是由于我的解决方案包括演员。

我的目标是返回一个指向内存位置的指针,该内存位置包含字符串s中字符串x的第一个字符。问题是第一个字符本身包含在首先作为const传递的字符串中,因此指向它的指针的类型为const char ,而不是char ,因为我声明的指针。如果我想将ptr_to_first_occ声明为const char *,我就不能再为它分配正确的位置,因为它不可写。这让我完全改变了函数(我希望返回一个char *,我可能会以另一种方式快速地做)或使用强制转换。或者我可以改变这一部分:

    for (int i = 0; i < (s_size-x_size); ++i) {
       for (int j = i; j < x_size; ++j) {
           if (s[j] != x[j]) ptr_to_first_occ = nullptr;
           else {
               const char* ptr_to_first_occ = &s[i];
           }   
       }
    }     

问题是声明使得这个变量只存在于其他范围内,并且我不能在指针超出范围之前使用虚拟变量存储该const char *,因为我无法分配之前声明的const变量。

此时我意识到这一点:

for (int j = i; j < x_size; ++j) {...}

毫无意义,应该是:

for (int j = i; j < i + x_size; ++j) {...}

好吧,公平。我的功能现在是:

    char* findx(const char* s, const char* x) {
        if (s==nullptr || x == nullptr) return nullptr;
        int s_size = strlen(s);
        int x_size = strlen(x);
        char* ptr_to_first_occ = nullptr;

        for (int i = 0; i < (s_size-x_size); ++i) {
            for (int j = i; j < i+x_size; ++j) {
                if (s[j] != x[j]) ptr_to_first_occ = nullptr;
                else {
                    ptr_to_first_occ = (char*)&s[i];
                }
            }
        }
        if (ptr_to_first_occ) return ptr_to_first_occ;
        else return nullptr;
    }

编译,从逻辑上看似乎有效,但由于我怀疑的相同原因,我仍然会遇到段错误(Segmentation fault:11)。我现在将主要改为:

const char* y = "Hey how are you?";
const char* t = "you";
char* p = nullptr;
p = findx(y, t);
if (p) cout << *p << endl;

原来这没有打印,所以p必须保持为nullptr。无论如何,经过许多调试标志,以及一堆反复试验(阅读:以一种让它看起来像垃圾箱的方式重写函数)我清理了整个事情,并设法解决了问题:

    char* findx(const char* s, const char* x) {
        if (s==nullptr || x == nullptr) return nullptr;
        int s_size = strlen(s);
        int x_size = strlen(x);
        char* ptr_to_first_occ = nullptr;

        for (int i = 0; i < (s_size-x_size); ++i) {
            if (s[i] != x[0]) ptr_to_first_occ = nullptr;
            else {
                for (int k = 0; k < x_size; ++k) {
                    if (s[i+k] == x[k]) ptr_to_first_occ = (char*)&s[i];
                    else {
                        ptr_to_first_occ = nullptr;
                        break;
                    }
                }
            }
        }
        if (ptr_to_first_occ) return ptr_to_first_occ;
        else {
            return nullptr;
        }
    }

这意味着演员阵容与分段错误无关,而这基本上就是我的问题所在。我根本无法在我之前的代码中找出错误的原因。我想知道如何理解与内存位置相关的分段错误的原因,因为我对只读内存位置如何工作的理解是错误的。我试图做的是什么造成了我的错误?

0 个答案:

没有答案