在C++程序中读取命令行参数时出现内存错误

Getting memory fault when reading command line arguments in a C++ program

本文关键字:内存 错误 参数 取命令行 C++ 程序      更新时间:2023-10-16

我一直在为学校编写一个C++代码项目,该项目希望我从命令行参数读取文本文件并将其输出,并在任何文章 [a,an,the] 之后添加在命令行中声明的形容词。这是我第一次必须对任何项目使用命令行。

我已经设法从命令行获取并读取文本文件,但我的问题是当我想获取字符串作为函数 isArticle(( 的参数时,我在 UNIX shell 中不断收到以下消息:

./test-program1[38]: eval: line 1: 7704: Memory fault
0a1,4

我不怀疑问题出在isArticle()功能上,但这里是:

bool isArticle(string n)
{
    string article[]={"a","an","the","A","An","aN","AN","The","tHe","thE","THe","tHE","ThE","THE"};
    for(int i=0;i<sizeof(article);i++)
    {
        if(n.compare(article[i])==0)
            return true;
    }
    return false;
}

虽然它不完整,但这里有一些测试代码,我用它来查看 isArticle(( 函数是否正常工作:

int main(int argc, char *argv[])
{ 
    istream *br;
    ifstream file;
    if(argc == 1)
        br = &cin;
    else if(argc==3)
    {
        file.open(argv[2]);
        if(file.is_open())//put work here
        {
            br=&file;
            string word;
            string output[sizeof(file)];
            while(file>>word)
            {
                if(isArticle(word)==true)
                {
                    cout<<word;
                }
            }
        }
        else
        {
            usage(argv[2],"Cannot open "+string(argv[2]));
            return 1;
        }
    }
    else
    {
        usage(argv[1], "More than one filename was given");
        return 1;
    }
    return 0;
}

正如其他人已经指出的那样,sizeof没有给出数字数组中的元素;这样做的惯用方法是使用 std::end( article ) - std::begin( article ) . 在 C++11 之前,大多数有经验的C++程序员也会这样做,使用 从他们的工具包中beginend

整个isArticle功能是非常不合时宜的。 在C++11,整个函数将是单个库调用:

bool
isArticle( std::string const& word )
{
    static std::string const articles[] = {
        "a", "an", "the", "A", "An", "aN", "AN",
        "The", "tHe", "thE", "THe", "tHE", "ThE", "THE",
    };
    return std::any_of(
            std::begin( articles ), std::end( articles ),
            [=]( std::string const& target ) { return word == target; } );
}

在前面的C++中,我们会写:

return std::find( begin( articles ), end( articles ), word )
        != end( articles );

(使用我们常用工具包中的beginend(。 如果我们想要(对于教学原因(自己编写循环,这将是一些东西喜欢:

std::string::const_iterator current = std::begin( articles );
std::string::const_iterator end = std::end( articles );
while ( current != end && *current != word ) {
    ++ current;
}
return current != end;
与您的

直接问题无关的几点可能值得一提的是:

  • 类类型通常通过引用 const 传递,而不是通过价值。 这可以说是过早的优化,但事实确实如此无处不在,其他任何东西都让人想知道为什么。

  • 函数中未更改的值应声明为const static .

  • std::string支持==!=;如果你正在寻找平等,这就是你应该使用的。 compare函数真的应该仅用于词典排序。

  • 从循环中间返回是您通常想要的避免。 当然,当函数如此简单时,它真的不是重要,但这是一个坏习惯。

这只是与所讨论的功能有关。 在main,你也有sizeof的问题. 在这种情况下,看起来您是尝试使用它来确定文件中的字数。 那如果不实际读取文件,则无法完成。 您在这里需要的是 std::vector<std::string> ,而不是 C 样式数组(其大小必须为编译时已知(。

当然:if所需的类型是 bool . isArticle返回一个bool,因此不需要其他任何东西。 写作 isArtile( word ) == true强烈建议您不知道 bool类型是。 (提示:表达式的类型 isArtile( word ) == true也是bool

最后一个建议:如果程序没有参数,你什么都不要做。 我不认为这是意图。 通常的Unix 下的命令行进程解决方案(而且也很普遍在Windows下(是将所有实际工作放在一个函数中,然后写入像这样:

int
main( int argc, char** argv )
{
    if ( argc == 1 ) {
        process( std::cin );
    } else {
        for ( int i = 1; i != argc; ++ i ) {
            std::ifstream in( argv[i] );
            if ( ! in ) {
                //  Output error message and set global flag for
                //  return value...
            } else {
                process( in );
            }
        }
    }
    return globalFlagWithReturnValue;
}

函数processstd::istream&作为参数,这允许它读取std::cin或打开的std::istream

sizeof运算符不返回数组中的元素数。 它返回数组占用的内存空间。 char数组将具有与int数组不同的sizeof

对于数组,您可以通过以下方式在编译时确定元素的数量:

const unsigned int elements_in_array =
    sizeof(article) / sizeof(article[0]);