char指针有不同的值

时间:2018-06-15 22:35:11

标签: c++ arrays string pointers char

我写了这段代码。 seperateLine函数获取一个char指针,它指向一个字符串,如“S - > BaB”,并将其分配到“ - >”之前部分和“ - >”之后部分。但打印此结果会显示不同的字符串。

#include <iostream>
#include <string.h>
using namespace std;

char *seperateLine(char *line,int befOrAf){
    char before[50]="";
    char after[50]="";
    for(int i=0;i<strlen(line);i++){
        if(line[i]=='-' && line[i+1]=='>'){
            strncpy(before,line,i-1);
            strncpy(after, line+i+3, strlen(line)- i -3);
            break;
        }
    }
    cout<<"1 "<< before<<endl;
    cout<<"1 "<<after<<endl;
    if(befOrAf==0) return before;
    else return after;
}
int main()
{
    char grammer[10][100]={"","","S -> BaB","","","","","","",""};
    char *seperated = seperateLine(grammer[2],0);
    cout<<"2 "<<seperated<<endl;
    seperated = seperateLine(grammer[2],1);
    cout<<"2 "<<seperated<<endl;
    cout<< "3 "<<seperateLine(grammer[2],0) <<endl<<"3 "<<seperateLine(grammer[2],1);
    return 0;
}

输出是:

1 S
1 BaB
2 S
1 S
1 BaB
2 Ba@آH
1 S
1 BaB
1 S
1 BaB
3 S
3 j

如您所见,“S - > BaB”的第二部分在不同部分具有值“BaB”,“ba @ H”,“j”。为什么会这样?

1 个答案:

答案 0 :(得分:1)

问题的主要部分是beforeafterseperateLine范围内的自动变量。一旦自动变量超出范围,它就会被销毁。死了,但并不总是消失。也许用于存储它的内存将被重新分配给其他东西,也许它不会。也许看起来它有效,也许它没有。在这种情况下你很幸运:它肯定不起作用,甚至看起来都不行。

在变量被销毁后使用它是教科书Undefined Behaviour并遵循阿甘定律:你永远不会知道你会得到什么。

传递数组是一件混乱的事情。您可以动态分配它们并将它们作为原始或智能指针返回,但在C ++中,表示字符串的char数组的正确答案几乎总是“使用std::string”。通常会为强调嵌入一些选择咒骂。

因此,如果std::string可用于此作业,请使用&lt; expletive deleted&gt; std::string

其余问题与数组边界的松散数学有关。你需要在数组索引上用+1或-1来表示很多关心,以确保你不会偏离界限。如上所述,对数学不良可能性的最直接解决方案是使用&lt; expletive deleted&gt; std::string

#include <iostream>
#include <string> // changed headers string.h for c-style strings to string 
                  // for std::string 

std::string seperateLine(const std::string &line, // a reference to an immutable std::string
                         int befOrAf){
    const static std::string delimiter = " -> "; // helps reduce magic numbers and makes it 
                                                 // easier to change the token delimiter
    std::string before; // now a std::string
    std::string after; // also a std::string
    auto loc = line.find(delimiter); // uses std::string's find method to find the arrow
    if (loc != std::string::npos) // find returns npos if the arrow was not found
    {
        before = line.substr(0, loc); // using line's substr method to split the string
        after = line.substr(loc + delimiter.size()); // look ma! No magic number!
    }
    std::cout<<"1 "<< before<<std::endl;
    std::cout<<"1 "<<after<<std::endl;
    if(befOrAf==0) return before;
    else return after;
}
int main()
{
    // strings, strings and more strings.
    std::string grammer[10]={"","","S -> BaB","","","","","","",""};
    std::string seperated = seperateLine(grammer[2],0);
    std::cout <<"2 "<<seperated<<std::endl;
    seperated = seperateLine(grammer[2],1);
    std::cout <<"2 "<<seperated<<std::endl;
    std::cout << "3 "<<seperateLine(grammer[2],0) <<std::endl
              <<"3 "<<seperateLine(grammer[2],1);
    return 0;
}