Заставить g ++ указать, когда библиотека не включена - PullRequest
0 голосов
/ 04 февраля 2019

Я студент по информатике, сейчас учусь на классе C ++.

Я работаю на Ubuntu с VSCode и g ++ в качестве моего компилятора.

У меня были очки, вычтенные из моего последнегоназначение, потому что я забыл включить библиотеку строк, поэтому у грейдера произошла ошибка компиляции.

Однако на моем компьютере, хотя библиотека строк не включена, она все равно компилируется и работает без проблем или предупреждений.

Кажется, что 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 голосов
/ 04 февраля 2019

Похоже, у вашего грейдера есть собственный каталог include, и он использует опции -nostdinc и -nostdinc++ на g ++ или компилирует код в другой ОС или с другим компилятором.

Сначала я думал, что это отсутствие опции -Wall, но кажется, что класс предупреждения, который на самом деле пропускает флаги, работает только для C или Objective-C, а не для C ++.Ваш код компилируется в моей системе без ошибок для g ++ и clang ++.Это не значит, что моя мысль о попытке другого компилятора была неправильной, просто бесполезной для этой проблемы.

Имитация среды, которую использует грейдер, была бы довольно трудоемкой.Но поскольку я потратил некоторое время, пытаясь сделать это просто для проверки моего последнего ответа, у меня возникло понимание: если вы пропустите свой код через g++ -E, он расскажет вам весь эффективный код, который будет скомпилирован, в том числе, где каждыйединственная вовлеченная линия прибывает из.Вы можете использовать это, чтобы увидеть все заголовочные файлы, включенные в ваш код, чтобы вы могли включить их все.

С одной стороны, это упражнение довольно раздражает.С другой стороны, это не так раздражает, как попытка портировать некоторый код с платформы, на которую вы не ссылаетесь, и автор не попытался убедиться, что все библиотеки были прописаны.С другой стороны, при попытке портировать некоторый код из совершенно другой исходной системы, библиотеки не все названы одинаково, и поэтому программисту это не обязательно поможет, особенно потому, что компиляторы довольно хорошижалуясь на отсутствующие файлы заголовков, которые имеют значение, и вы можете довольно быстро найти имена подпрограмм или типов, которые обсуждаются, чтобы выяснить, что делать с этим в вашей системе.Я думаю, в конце концов, я склонен предположить, что ваш грейдер, вероятно, работал по указанию академика, который думает, что он помогает воспитывать учеников в способности справляться с неизвестными, с которыми они столкнутся, не имея большого представления о том, что неизвестныевы, вероятно, столкнетесь.Это печально и грустно, но иногда так и бывает.Мы делаем то, что можем, мы не делаем то, что не можем, но мы можем не знать, что не можем сделать, пока не попробуем.

0 голосов
/ 04 февраля 2019

#include - это всего лишь буквальное вырезание и вставка содержимого включаемого файла (с развернутыми макросами и вставленными маркерами файлов / строк, чтобы можно было проследить источник).

Когда вы включаете iostream , если он внутренне включает string , то вы включаете строку транзитивно.Это считается плохим, потому что нет гарантии, что заголовки стандартной библиотеки будут включать другие заголовки, поэтому ваш код не переносим и имеет небольшую зависимость от версии используемой вами стандартной библиотеки.

Если выдобавьте в ваш код включение для string , так как препроцессор защищает от повторяющихся включений заголовков, оно будет настолько тщательно подавлено, что никаких доказательств того, что это включение вообще не будет присутствовать в его выходных данных.Компилятору не с чем работать, и он не может надежно выдать предупреждение, которое вы хотели бы получить без ложных срабатываний.

Например: допустим, у нас есть файл .cpp с main и заголовок 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% идентично предыдущему. Мы исправили проблему, но в предварительно обработанном выводе нет никаких указаний.

Если препроцессор не дал больше информации, никакие изменения в компиляторе не могли бы удовлетворить ваш запрос.

...