我在这段代码中遇到了分段错误,无法理解为什么?

时间:2015-08-07 18:25:20

标签: c++

我正在尝试编写一个程序,它将程序作为输入,并在单独的行中打印出该程序中写的所有注释。

#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;


int main() {
    string str;

    while(getline(cin,str))    {
    int i;
       // cout<<str;

    for(i=0;str[i]!='/' && str[i+1] !='/';i++);
        //cout<<i;
    for(i;str[i]!='\n';i++) {
       // cout<<i;
        cout<<str[i];
    }
        cout<<endl;

    }
    return 0;
}

我在这段代码中遇到了分段错误,我无法理解为什么。这是hackerrank https://www.hackerrank.com/challenges/ide-identifying-comments/copy-from/12957153

中问题代码的一部分

3 个答案:

答案 0 :(得分:0)

在你的问题中评论你的代码是错误的。首先,您将getline返回的std :: string对象视为字符数组。其次,如果在输入字符串中找不到//\n,则for循环永远不会结束。显然它会崩溃。以下是修改后的代码。

#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;


int main() {
    string str;

    while(getline(cin,str))    {
    int i;
       // cout<<str;

    size_t len = str.length();
    const char *cstr = str.c_str();
    for(i=0; (cstr[i]!='/' && cstr[i+1] !='/' && i < len); i++)
        //cout<<i;
    for(; cstr[i]!='\n' && i < len;i++) {
       // cout<<i;
        cout<<cstr[i];
    }
        cout<<endl;

    }
    return 0;
}

答案 1 :(得分:0)

int main() {
    while(getline(cin,str)) {
        int i, len = str.size();

        //always make sure that you are not accessing
        //contents after your string has ended
        for(i=0; i < (len - 1) && !(str[i] == '/' && str[i+1] == '/'); i++);

        //note that i here might be the last alphabet
        //if there's no comment
        if(i < len && str[i] != '/')
            i++;


        //checking if str[i] != '\n' is not a good idea
        //as c++ stl strings are not temrinated by '\n'
        if(i < len) {
            for(; i < len; i++)
                cout << str[i];
            cout << endl;
        }
    }

    return 0;
}

另请注意,以下两个代码都不会在第4个字符处终止,c ++ stl字符串不会被这些字符终止。

string str = "hahahaha";
str[4] = '\n';
cout << str;

str[4] = '\0';
cout << str;

答案 2 :(得分:0)

这比以前的其他解决方案写起来要容易得多,而且可能要快得多。

#include <iostream>

int main()
{
    std::string str;

    while (std::getline(std::cin, str))
    {
        size_t loc = str.find("//");
        if (loc != str.npos)
        {
            std::cout << str.substr(loc + 2)<< std::endl;
        }
    }
    return 0;
}

这也是错误的。

这是一个漂亮,干净,简单的状态机版本。也非常接近最坏情况下的速度。事情是最接近正确的,即使它也是错的。

#include <iostream>
enum states
{
    seeking1,
    seeking2,
    comment
};

int main()
{
    std::string str;

    while (std::getline(std::cin, str))
    {
        states state = seeking1;
        for (char ch:str)
        {
            switch (state)
            {
                case seeking1:
                    if (ch == '/')
                    {
                        state = seeking2;
                    }
                    break;
                case seeking2:
                    if (ch == '/')
                    {
                        state = comment;
                    }
                    else
                    {
                        state = seeking1;
                    }
                    break;
                case comment:
                    std::cout << ch;
                    break;
            }
        }
        if (state == comment)
        {
            std::cout << std::endl;
        }
    }
    return 0;
}

为什么这些方法都错了?考虑一下

cout << "Hi there! I am \\Not A Comment!" << endl;`

您无法查看\\,还需要上下文。这就是为什么上面的状态机是更好的选择。可以修改它以至少处理处理字符串和块注释的状态。