C ++字符串操作给我带来奇怪/不一致/错误的结果

时间:2014-08-03 15:57:14

标签: c++ string

我正在尝试读取一个应该是以下形式的序列: 变量 运算符 变量 运算符 变量。 。 。依此类推,其中'变量'包含A,B或C,'运算符'是四个基本运算符之一+ - / *,如果符合给定形式则只打印有效,如果符合,则无效没有。此外,条件是序列必须以单个变量开始,并由操作员遵循(中间允许空格)。

我已经编写了一些代码来获取字符串输入,并且只有一个名为'check'的函数来查看它是否返回false,使程序打印为'Invalid'。这是我的主要功能:

using namespace std;
int main() {
    string m;
    cout<<"Please enter a sequence: "<<endl;
    getline(cin,m);
    bool allow = check(m);
    if(allow == true){
        cout<<"\n\nCorrect format "<<endl;
    }
    else{
        cout<<"\n\nIncorrect format \n"<<endl;
    }
    system("PAUSE");
    return 0;
}

这是我的检查功能:

bool check(string mi){
    int c=0; //using c as an index,
    mi.append("0"); //append a 0 as a signal to when the string ends
    while(c < mi.length()){
        if(mi.at(c)=='0'){}
        else if(isblank(mi.at(c))){} //So it will accept spaces between the input
        else if(mi.at(c) == 'A' ||mi.at(c) == 'B' ||mi.at(c) == 'C'){ 
            //The sequence must start with a variable...
            c +=1;    //increment to start at the next character...
            while(c < mi.length()){ //This whole loop is to check if the next 
                                //significant character is one of the operators
                if(isblank(mi.at(c))){} 
                else if(mi.at(c) !='+' ||mi.at(c) != '-' ||mi.at(c) != '/' || mi.at(c) != '*' || mi.at(c) !='0'){
                    cout<<"\n(Log)  Character at "<<c<<" was not an operator? Value: "<<mi.at(c);
                    //Why does it always come here even if the value was an operator?
                    return false;
                }
                c++;    
            }
        }
        c++;
    }
    return true; //Assume true if there are no errors...
}

即使我输入了正确的序列,比如说A + B + C,它仍然是无效的。我已经将问题追溯到上面的特定代码行。为什么这样做?

4 个答案:

答案 0 :(得分:3)

因为你的布尔逻辑不正确。

表达式:

mi.at(c) !='+' || mi.at(c) != '-' || mi.at(c) != '/' || mi.at(c) != '*' || mi.at(c) !='0'

每次评估为真。例如,如果mi.at(c)是&#39; - &#39;,那么mi.at(c)!=&#39; +&#39;评估为真,你进入你不想进入的那部分代码。同样,如果i.at(c)是&#39; +&#39;那么mi.at(c)!=&#39; - &#39;评估为真,再次将条件评估为真。

我相信你想把你的布尔或者(||)改为布尔和&#39;(&amp;&amp;)。

对于一些未经请求的建议,我个人建议花点时间将问题视为状态机。这将使您能够以可支持和可扩展的方式清理和思考它正在做什么。我不是一个c ++编码器,但这里是我如何在c作为状态机来处理它。您应该能够将其翻译为c ++:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

main() {

    char* VARS   = "ABC";
    char* OPS   = "+-/*";
    char  c     = EOF;
    int   state = 0;

    while (((c = getchar()) != EOF) && (state < 3)) {

        // move on to next character if we have a blank or end-of-line

        if (c == ' ' || c == '\n')
            continue;

        // test to see if the character is a var or op

        int isvars = (strchr(VARS, c) != NULL);
        int isops  = (strchr(OPS,  c) != NULL);

        // based upon character type and current state, determine next state

        if (!isvars && !isops) // character is neither a valid var nor op
            state = 3;
        else if (isvars) // character is a var
            if ((state == 0) || (state == 2))
                state = 1;
            else if (state == 1)
                state = 3;
        else if (isops) // character is an op
            if ((state == 0) || (state == 2))
                state = 3;
            else if (state == 1)
                state = 2;

    }

    puts((state > 1) ? "bad" : "good");

} 

并且,这是将其编译为&#39; varop&#39;:

后的结果
$ echo "" | ./varop
good
$ echo "A" | ./varop
good
$ echo "+" | ./varop
bad
$ echo "A+" | ./varop
bad
$ echo "AA" | ./varop
bad
$ echo "A+" | ./varop
bad
$ echo "A+A" | ./varop
good
$ echo "A++" | ./varop
bad
$ echo "A + B" | ./varop
good
$ echo "   A + B" | ./varop
good
$ echo "D" | ./varop
bad
$ echo "%" | ./varop
bad

答案 1 :(得分:2)

你的问题在哪里是正确的,但问题是你的基本逻辑。由于您使用||而非&&,这意味着您的语句始终评估为true(即'+'将在第一个条件下评估为false ,但在检查不-时将评估为true。您需要做的是将罪魁祸首行中的||运算符替换为&&,并且您的检查函数应该按预期运行。

另外,作为样式注释,在检查功能的第8行,而不是c += 1,您应该使用c++来保持一致性。

答案 2 :(得分:2)

试试这个,它会编译并提供所需的输出。但是,它仍然没有强制要求操作符后跟一个字符。但我想你可以搞清楚。

using namespace std;

为了提供帮助,我创建了一系列可能的运算符以及一个检查字符是否为运算符的函数。

unsigned char operators[] = { '+','-','/','*' };


bool isOperator(const unsigned char &m) {
    for (int n = 0; n < 4; n++) if (m == operators[n]) return true;
    return false;
}

在你的检查中只需要一个循环,for循环更加方便。注意逻辑,当角色是A或B或C或空白时我会继续。

bool check(string mi){
    for (int c = 0; c < mi.size(); c++) {
        cout << mi.at(c);
        if (isblank(mi.at(c))) continue;
        if (mi.at(c) == 'A' || mi.at(c) == 'B' || mi.at(c) == 'C') continue;
        if (!isOperator(mi.at(c))) {
            cout<<"\n(Log)  Character at " << c <<" was not an operator? Value: "<<mi.at(c);
            return false;
        }
    }
    return true; //Assume true if there are no errors...
}

int main() {
    string m;
    cout<<"Please enter a sequence: "<<endl;
    getline(cin,m);

    cout << "\n\n" << string(check(m) ? "Correct":"Incorrect") << " format." << endl;

    system("PAUSE");
    return 0;
}

输出:

Please enter a sequence:
A+B+C
A+B+C

Correct format.
Press any key to continue . . .

答案 3 :(得分:0)

我建议您使用std::istringstream并使用std::copy将单独的组件转换为std::vector个字符。然后迭代向量来检查只有有效的组件是很简单的。

为了帮助您使用std::copy将组件放入向量中,建议您阅读std::istream_iteratorstd::back_inserter