强制g ++指示何时不包含库

时间:2019-02-03 21:39:03

标签: c++ compiler-errors g++

我是一名计算机科学专业的学生,​​现在正在上C ++课。

我正在使用VSCode和g ++作为编译器在Ubuntu上进行开发。

我从上次作业中扣除了点数,因为我忘记了包含字符串库,因此平地机出现了编译错误。

但是,在我的机器上,尽管不包括字符串库,但它仍然可以编译并运行而不会出现问题或警告。

似乎g ++捕获了此错误并包含了这个错误而没有告诉我?有什么方法可以强制g ++指示我忘记了字符串库?

这是我遇到此问题的代码:

#include <iostream>

using namespace std;

int main()
{
    string output = "";
    char inputChar;

    // ask for input while the inputChar is not '0'
    do
    {
        cout << "Enter a character: ";
        cin.get(inputChar);              // get input char from user
        cin.ignore(100, '\n');           // ignore the newline character
        switch( tolower(inputChar) )     // inputChar lowercase for simplified switch statement
        {
            // if inputChar is a vowel, capitalize and append to output string
            case 'a':
            case 'e':
            case 'i':
            case 'o':
            case 'u':
                output += toupper(inputChar);
                break;
            // if char is 0, exit switch without doing anything
            case '0':
                break;
            // all other characters are appended to string in lowercase
            default:
                output += tolower(inputChar);
                break;
        }
    } while (inputChar != '0');

    // print full output string and exit
    cout << "Your string: " << output << endl;


    return 0;
}

2 个答案:

答案 0 :(得分:2)

#include仅仅是对所包含文件内容的字面剪切和粘贴(扩展了宏,并插入了文件/行标记,以便可以跟踪源)。

当包含 iostream 时,如果它内部包含 string ,则表示您已传递了string。之所以认为这是不好的,是因为无法保证标准库标头会包含其他标头,因此您的代码不可移植,并且对所使用的标准库的版本依赖性很小。

如果您在代码中添加了 string 的包含,由于预处理程序可以防止重复的标头包含,因此它将被彻底抑制,以至于在输出中不会出现包含偶数的证据。 。编译器无法处理任何内容,并且如果没有误报,就无法可靠地提供您想要的警告。

例如:假设我们有一个带有主文件的.cpp文件,以及一个名为a.hpp的标头:

标题“ a.hpp”:

#pragma once

namespace A {
    void a_function() { }
}

标题“ b.hpp”

#pragma once
#include "a.hpp"

namespace B {
  void b_function() { }
}

和main.cpp现在看起来像这样:

#include "b.hpp" // only include b...

int main() { A::a_function(); } // ... but use something in a.hpp

这可以编译,但是没有警告。预处理后的输出如下所示:

# 1 "main.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "main.cpp"
# 1 "b.hpp" 1     
# 1 "a.hpp" 1
namespace A {
  void a_function() { }
}
# 3 "b.hpp" 2

namespace B {
    void b_function() { }
}
# 2 "main.cpp" 2

int main() { }

看起来很合理,我们可以看到a包含在B中,应该发出错误,对吧?

让我们修复它,然后重试:

#include "b.hpp"
#include "a.hpp"

int main() { }

再次预处理:

# 1 "main.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "main.cpp"
# 1 "b.hpp" 1     
# 1 "a.hpp" 1
namespace A {
  void a_function() { }
}
# 3 "b.hpp" 2

namespace B {
    void b_function() { }
}
# 2 "main.cpp" 2

int main() { }

100%与以前相同。 我们已解决问题,但预处理后的输出中没有任何提示。

除非预处理器提供了更多信息,否则编译器中的任何更改都无法满足您的请求。

答案 1 :(得分:0)

您的评分者似乎有一个自定义的include目录,并在g ++上使用了-nostdinc-nostdinc++选项,或者他们正在不同的OS或不同的编译器上编译代码。

起初,我认为这是缺少-Wall选项的,但是看来实际上标记为丢失的警告类仅适用于C或Objective-C,而不适用于C ++。您的代码可以在我的系统上编译,而g ++和clang ++都没有错误。这并不意味着我之前尝试另一个编译器的想法是错误的,只是对这个问题没有用。

模拟平地机正在使用的环境将需要大量工作。但是,当我花一些时间尝试这样做,只是为了理智地检查我的最后一个答案时,我意识到:如果您通过g++ -E运行代码,它将告诉您将要编译的所有有效代码,包括每个涉及的行来自哪里。您可以使用它来查看代码中包含的所有头文件,以便可以全部包含它们。

一方面,这种练习很烦人。另一方面,这并不像试图从您没有参考的平台上移植一些代码那样令人讨厌,并且作者没有做出任何努力来确保所有库都被阐明。另一方面,当尝试从非常不同的源系统中移植某些代码时,库的命名方式并不完全相同,因此,程序员这样做不一定会有所帮助-特别是因为编译器非常擅长抱怨缺少重要的头文件,您可以相当快地查找有问题的例程或类型的名称,以了解如何对系统进行处理。我认为最后我倾向于假设您的分级机可能是在一位学者的指导下工作的,该学者认为他们正在帮助学生塑造自己,以便能够处理他们将遇到的未知事物,而对未知事物却不怎么了解您很可能会遇到。那令人沮丧和悲伤,但有时生活也是如此。我们会尽我们所能,我们不会做我们不能做的事,但是直到尝试为止,我们可能不知道我们无法做的事。