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

标签 c++ unix memory

我一直在为学校编写一个 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 的引用传递,而不是通过 值(value)。可以说,这是过早的优化,但确实如此 无处不在,任何其他事情都会让人想知道为什么。

  • 函数中未更改的值应声明为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;
}

函数process需要 std::istream&作为论据,其中 允许它读取 std::cin或打开 std::istream .

关于c++ - 在 C++ 程序中读取命令行参数时出现内存错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28397198/

相关文章:

linux - 如何从命令行访问 Unix 域套接字?

c++ - 如何比较 time_t 和 std::filesystem::file_time_type

linux - Bash 脚本解析 HTML 文件

linux - 在写入文件期间拒绝写入权限

java - Java中的字符串是如何分配内存的?

iphone - 当我在 Swift 中销毁我的对象时,它不会释放我的 RAM 内存

c++ - 我可以使用 C++03 标准库功能模拟一个空的 lambda 吗?

c++ - C++程序中的变量名存放在哪里?

c++ - Multimap 与运算符不匹配==

C#访问内存映射文件