Я только что сделал то, что кажется распространенной ошибкой новичка :
Сначала мы прочитали один из множества уроков , который выглядит так:
#include
int main() {
using namespace std;
ifstream inf("file.txt");
// (...)
}
Во-вторых мы пытаемся использовать нечто похожее в нашем коде, которое выглядит примерно так:
#include
int main() {
using namespace std;
std::string file = "file.txt"; // Or get the name of the file
// from a function that returns std::string.
ifstream inf(file);
// (...)
}
В-третьих, Разработчик новичка озадачен каким-то загадочным сообщением об ошибке компилятора.
Проблема в том, что ifstream принимает const * char
в качестве аргумента конструктора.
Решение состоит в том, чтобы преобразовать std :: string в const * char .
Теперь реальная проблема заключается в том, что для новичка, file.txt или Подобные примеры, приведенные почти во всех уроках, очень похожи на std :: string.
Итак, «мой текст» это std :: string, c-string или * char или это зависит от контекста?
Можете ли вы привести примеры того, как «мой текст» будет интерпретироваться по-разному в зависимости от контекста?
Решение состоит в том, чтобы преобразовать std :: string в const * char .
Теперь реальная проблема заключается в том, что для новичка, file.txt или Подобные примеры, приведенные почти во всех уроках, очень похожи на std :: string.
Итак, «мой текст» это std :: string, c-string или * char или это зависит от контекста?
Можете ли вы привести примеры того, как «мой текст» будет интерпретироваться по-разному в зависимости от контекста?
Решение состоит в том, чтобы преобразовать std :: string в const * char .
Теперь реальная проблема заключается в том, что для новичка, file.txt или Подобные примеры, приведенные почти во всех уроках, очень похожи на std :: string.
Итак, «мой текст» это std :: string, c-string или * char или это зависит от контекста?
Можете ли вы привести примеры того, как «мой текст» будет интерпретироваться по-разному в зависимости от контекста?
или это зависит от контекста?
Можете ли вы привести примеры того, как «мой текст» будет интерпретироваться по-разному в зависимости от контекста?
или это зависит от контекста?
Можете ли вы привести примеры того, как «мой текст» будет интерпретироваться по-разному в зависимости от контекста?
[Редактировать: я думал, что приведенный выше пример сделал бы это очевидным, но, тем не менее, я должен был быть более точным: я имею в виду тип любой строки, заключенной в двойные кавычки, т.е. «myfilename.txt», а не значение слова «строка».]
Спасибо.
Итак, "строка" - это std :: string, c-string или * char, или это зависит от контекста?
const char *
(или const char []
, чтобы быть точный). «Строка C» обычно относится к этому, особенно к массиву символов с нулевым ограничителем. std :: string
- это вспомогательный класс, который превращает необработанную строку в объект. Используя это, вы можете избежать необходимости самостоятельно выполнять (беспорядочную) арифметику указателей и перераспределение памяти. char *
(или const char *
). char *
в std :: string
, потому что у последнего есть конструктор для этого. std :: string
в const char *
с помощью метода c_str ()
. Спасибо Clark Gaebel за указание на const
ness, а также jalf и GMan за упоминание, что это на самом деле массив.
std::string file = "file.txt";
Правая часть =
содержит (необработанный) строковый литерал (например, байтовую строку с завершающим нулем). Его эффективный тип - массив const char
.
=
здесь - хитрый пони: никакого назначения не происходит. Класс std :: string
имеет конструктор, который принимает указатель на char в качестве аргумента, и он вызывается для создания временного std :: string
и используется для копирования-конструкции (с использованием ctor копирования std :: string
) объект файл
типа std :: string
.
Однако компилятор может исключить объект копирования и напрямую создать экземпляр файла.
Однако обратите внимание, что std: string
- это не то же самое, что строка в стиле C с завершающим нулем. Это даже не обязательно должно быть завершено нулем.
ifstream inf("file.txt");
Класс std :: ifstream
имеет ctor, который принимает const char *
, а переданный ему строковый литерал распадается до указателя на первый элемент строки.
Следует помнить следующее: std :: string
обеспечивает (почти бесшовное) преобразование из строк в стиле C. Вам нужно найти подпись функции, чтобы узнать, передаете ли вы const char *
или std :: string
(последнее из-за неявных преобразований).
Для использования правильной формулировки (как указано в стандарте языка C ++) строка является одной из разновидностей std :: basic_string (включая std :: string) из главы 21.3 «Строковые классы» (как в C ++ 0x N3092), в то время как аргумент конструктора ifstream - NTBS (последовательность байтов с завершающим нулем)
Чтобы процитировать, C ++ 0x N3092 27.9.1.4 / 2.
basic_filebuf * open (const char * s, ios_base :: openmode mode);
...
открывает файл, если возможно, с именем NTBS s
Стандартная библиотека C ++ предоставляет класс std :: string для управления и представления последовательностей символов. Он инкапсулирует управление памятью и большую часть времени реализуется как C-строка; но это деталь реализации. Он также предоставляет процедуры управления для общих задач.
Тип std :: string всегда будет таким (например, у него нет оператора преобразования в char *, поэтому у вас есть метод c_str ()), но он может быть инициализирован или назначен C -строка (символ *).
С другой стороны, если у вас есть функция, которая принимает в качестве параметра std :: string или const std :: string &, вы можете передать ей c-строку (char *), и компилятор построит std :: string на месте для вас. Это было бы разной интерпретацией в зависимости от контекста, как вы это выразились.
"myString"
является строковым литералом и имеет тип const char[9]
, массив из 9 констант char
. Обратите внимание, что в нем достаточно места для нулевого терминатора. Итак, "Привет"
является const char[3]
и так далее.
Это почти всегда верно, без двусмысленности. Однако при необходимости const char[9]
распадается на const char*
, указывающий на его первый элемент. И std::string
имеет неявный конструктор, который принимает символ const*
. Поэтому, хотя он всегда начинается как массив char, он может стать другими типами, если вам это нужно.
Обратите внимание, что строковые литералы обладают уникальным свойством, что const char[N]
также может распадаться на char*
, но это поведение устарело. Если вы попытаетесь изменить базовую строку таким образом, вы получите неопределенное поведение. Это просто не очень хорошая идея.
Как можно чаще это должно означать std :: string
(или альтернативу, например wxString
, QString
и т. Д., Если вы используете фреймворк, который предоставляет это. Иногда у вас нет реального выбора, кроме как использовать последовательность байтов с завершающим NUL, но обычно вы хотите избежать этого, когда это возможно.
В конечном итоге, просто нет четкой, однозначной терминологии. Такова жизнь.
Итак, является ли «строка»
std::string
, c-строкой илиchar*
, или это зависит от контекста?
Это полностью зависит от контекста. :-) Добро пожаловать в C++.
Строка C — это строка с завершающим нулем, которая почти всегда совпадает с char*
.
В зависимости от используемых вами платформ и фреймворков может быть еще больше значений слова «строка» (например, оно также используется для обозначения QString
в Qt или CString.
в МФЦ).