这个问题来自一本教科书:编程 - 使用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;
}
}
这意味着演员阵容与分段错误无关,而这基本上就是我的问题所在。我根本无法在我之前的代码中找出错误的原因。我想知道如何理解与内存位置相关的分段错误的原因,因为我对只读内存位置如何工作的理解是错误的。我试图做的是什么造成了我的错误?