【发布时间】:2018-02-04 14:59:24
【问题描述】:
我提前道歉,因为我在之前的帖子中问过同样的问题,但正如有人正确指出的那样,我没有发布真正的代码。因此,我再次问同样的问题,试图比以前更清楚。
作为练习,我正在创建一个操作字符串的程序。特别是,我想删除包含在 2 '*' 之间的部分字符串。我必须强调我已经成功地创建了具有库字符串功能的相同程序;实际上,问题涉及使用 char 指针对给定字符串的操作。我将发布完整的代码并深入讨论。
#include <iostream>
#include <string>
using namespace std;
int main() {
string frase;
getline (cin, frase); // Takes as input the phrase
int size = frase.size();
cout << frase[0]; // <- this line is not even processed (I've used it to test the problem) However, if I put it before the first if, it will be sent in output.
char* pa1 = NULL; // The pointer which will "point" to the first *
char* pa2 = NULL; // The pointer which will "point" to the second *
bool stop = false; // When the pointers find 2 asterisk, stop = true
for(int i = 0; i < size - 1 || stop == true; i++){ // FOR LOOP n.1
if(frase[i] == '*'){
if(*pa1 == '*'){
pa2 = &frase[i];
stop = true;
}
pa1 = &frase[i];
}
}
// I've debugged the program and find that the problem is before this line, probably
// linked to the address of pointers. I will explain later what I mean.
// I've came up with this conclusion after trying to ignore part of the program and processing it in another file.
// However, I'm not fully sure with this result, since the problem regards the visualization of the content of the pointers.
if(pa2 == NULL){ // if it's a null pointer, this means that second asterisk has not been found.
if(pa1 == NULL){// if also this is a null pointer, there is no asterisk at all
cout << "Non ci sono asterischi. Non verrà eliminata nessuna parola.\n\n";
}
cout << "C'è un solo asterisco. Verrà eliminato unicamente l'asterisco.\n\n";
for(; pa1 < &frase[size - 1]; pa1++){ // FOR LOOP n.2
*pa1 = *(pa1 + 1);
}
}
else{
for(; pa1 < pa2 + 1; pa1++){ // this removes asterisk and
//the phrase between them, by overwriting the existing characters. FOR LOOP n.3
*pa1 = *(pa1 + 1);
}
}
cout << "La frase dopo l'eliminazione è:\n" << frase;
return 0;
}
在发布之前,我努力了解问题的性质。我看到了一个意想不到的行为:如果我初始化指向内存地址的指针,例如:
pa1 = &frase[i];
其中不包含任何星号,然后,(感谢for循环n.1中的'if'条件)在将其地址更改为第一个星号后,我尝试将其可视化(忽略其余代码)通过编写:
cout << *pa1;
程序不会崩溃并输出星号。但是,对 pa2 执行相同操作并创建带有 2 个星号的短语会导致程序崩溃。将指针 pa1 初始化为 'NULL' 并执行相同的过程会导致程序崩溃。
然后我想出了 2 个假设:
1 - 可能我无法使用 char 指针管理字符串对象,即使我只是管理给定字符串的 字符 .但是,如果我将指针初始化为字符串的现有地址,我可以很容易地显示短语的字符。
2 - 问题与我也在处理空字符有关,例如“空格”等。因此,问题出在for循环n.2或n.3(参考代码)。
我知道我可以用 char[] 数组来处理问题,并且我知道用字符串函数来处理这个问题会更好,但我想要解决这个问题是为了充分理解字符串对象和字符指针之间的相关性。所以我只是寻求帮助以在此代码中找到错误;我不想要一个新代码(因为这对你来说是浪费时间,而且这意味着以某种方式利用你,即使我们正在谈论一个独立的练习)。我希望我清楚地解释了这个问题。提前谢谢你。
编辑:我忘了指出,我也认为问题可能与大小有关,以字节为单位的 int 值,而我将其视为字符串中的槽数包含一个字符。我认为这些信息会很有用,但我不确定它的出席率。
编辑 2:@lilscent 解决了与引用空指针相关的问题。我已经更改了代码并将pa1指针和pa2指针初始化为
pa1 = &frase[0];
pa2 = nullptr;
编辑 3:按照建议,我删除了布尔变量,并在第一个循环中使用了 break。我还更改了最后一个 for 循环,因为代码现在可以工作,但没有做它应该做的事情。我还编辑了第二个循环添加和其他:
if(pa2 == nullptr){
if(pa1 == &frase[0]){
cout << "Non ci sono asterischi. Non verrà eliminata nessuna parola.\n\n";
}
else{
cout << "C'è un solo asterisco. Verrà eliminato unicamente l'asterisco.\n\n";
for(; pa1 < &frase[size - 1]; pa1++){
*pa1 = *(pa1 + 1);
}
*pa1 = ' ';
}
}
编辑 4:现在程序完全可以运行了。我已经编辑了最后一个循环:
else{
*pa2 = ' ';
pa2+= 2;
for(; pa1 < pa2 + 1 && pa2 < &frase[size]; pa1++, pa2++){
*pa1 = *pa2;
*pa2 = ' ';
}
*pa2 = ' ';
}
感谢您的帮助和所有建议!我保留了代码以帮助其他人解决相同类型的问题。
最终编辑:请参阅 NikosC. 的帖子。他修改了部分程序,提高了效率,解决了大部分问题。再次感谢!
【问题讨论】:
-
在新程序中优先使用
nullptr而不是NULL。 -
什么是
size?请确保您发布的代码可以编译。 -
你正在取消引用一个空指针:
if(*pa1 == '*') -
不要调试消息,而是使用真正的调试器。一步步跟踪执行,观察局部变量。
-
@King - 您还应该考虑到
std::string具有find and erase 的功能,可以帮助您在没有循环的情况下进行编辑。