Как сделать строку пустой c

Обновлено: 05.07.2024

Я был удивлен, увидев пример строки, инициализированной нулем, а затем добавив к ней что-то в производственной среде. Он просто плакал неправильно.

Я был уверен, что это вызвало бы исключение из нулевого объекта, но этот очень сокращенный пример также работает:

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

Может кто-нибудь объяснить, почему это работает без ошибок?

Последующий:

На основании ответа Leppie я использовал Reflector, чтобы увидеть, что внутри строки. Concat. Теперь действительно очевидно, почему это преобразование имеет место (вообще нет магии):

ОТВЕТЫ

Ответ 1

Оператор + для строк является только сокращением для string.Concat , который просто превращает аргументы null в пустые строки перед конкатенацией.

Update:

Обобщенная версия string.Concat:

Ответ 2

Соответствующая цитата должна быть ECMA-334 §14.7.4:

Конкатенация строк:

Двоичный оператор + выполняет конкатенацию строк, когда один или оба операнда имеют тип string . Если операнд строки конкатенация null , замещается пустая строка. В противном случае любой операнд без строки преобразуется в его строковое представление посредством вызывая виртуальный метод ToString , унаследованный от типа object . Если ToString возвращает null , заменяется пустая строка.

Ответ 3

Оператор binary + выполняет конкатенацию строк, когда один или оба операнды имеют тип string. Если операнд конкатенации строк null, заменяется пустая строка. В противном случае любая строка аргумент преобразуется в его строковое представление, вызывая виртуальный метод ToString, унаследованный от объекта типа. Если ToString возвращает null, заменяется пустая строка.

БлогNot. Лекции по C/C++: строки класса string

Лекции по C/C++: строки класса string

В современном стандарте C++ определен класс с функциями и свойствами (переменными) для организации работы со строками (в классическом языке C строк как таковых нет, есть лишь массивы символов char ):

Для работы со строками также нужно подключить стандартный namespace :

В противном случае придётся везде указывать описатель класса std::string вместо string .

Ниже приводится пример программы, работающей со string (в старых си-совместимых компиляторах не работает!):

  • инициализация массивом символов (строкой встроенного типа) или другим объектом типа string . Встроенный тип не обладает второй возможностью;
  • копирование одной строки в другую. Для встроенного типа приходится использовать функцию strcpy() ;
  • доступ к отдельным символам строки для чтения и записи. Во встроенном массиве для этого применяется операция взятия индекса или косвенная адресация с помощью указателя;
  • сравнение двух строк на равенство. Для встроенного типа используются функции семейства strcmp() ;
  • конкатенация (сцепление) двух строк, дающая результат либо как третью строку, либо вместо одной из исходных. Для встроенного типа применяется функция strcat() , однако чтобы получить результат в новой строке, необходимо последовательно задействовать функции strcpy() и strcat() , а также позаботиться о выделении памяти;
  • встроенные средства определения длины строки (функции-члены класса size() и l ength() ). Узнать длину строки встроенного типа можно только вычислением с помощью функции strlen() ;
  • возможность узнать, пуста ли строка.

Рассмотрим эти базовые возможности более подробно.

Инициализация строк при описании и длина строки (не включая завершающий нуль-терминатор):

Строка может быть задана и пустой:

Для проверки того, пуста ли строка, можно сравнить ее длину с 0:

или применить метод empty() , возвращающий true для пустой строки и false для непустой:

Третья форма создания строки инициализирует объект типа string другим объектом того же типа:

Строка st3 инициализируется строкой st . Как мы можем убедиться, что эти строки совпадают? Воспользуемся оператором сравнения ( == ):

Как скопировать одну строку в другую? С помощью обычной операции присваивания:

Для сцепления строк используется операция сложения ( + ) или операция сложения с присваиванием ( += ). Пусть даны две строки:

Мы можем получить третью строку, состоящую из конкатенации первых двух, таким образом:

Если же мы хотим добавить s2 в конец s1 , мы должны написать:

Операция сложения может сцеплять объекты класса string не только между собой, но и со строками встроенного типа. Можно переписать пример, приведенный выше, так, чтобы специальные символы и знаки препинания представлялись встроенным типом char * , а значимые слова – объектами класса string :

Подобные выражения работают потому, что компилятор "знает", как автоматически преобразовывать объекты встроенного типа в объекты класса string . Возможно и простое присваивание встроенной строки объекту string :

Обратное преобразование при этом не работает. Попытка выполнить следующую инициализацию строки встроенного типа вызовет ошибку компиляции:

Чтобы осуществить такое преобразование, необходимо явно вызвать функцию-член с названием c_str() ("строка Си"):

Функция c_str() возвращает указатель на символьный массив, содержащий строку объекта string в том виде, в каком она находилась бы во встроенном строковом типе. Ключевое слово const здесь предотвращает "опасную" в современных визуальных средах возможность непосредственной модификации содержимого объекта через указатель.

К отдельным символам объекта типа string , как и встроенного типа, можно обращаться с помощью операции взятия индекса. Вот, например, фрагмент кода, заменяющего все точки символами подчеркивания:

Но лучше читать документацию по C++ и пользоваться его возможностями. Например, предыдущее действие мы могли бы выполнить вызовом одной-единственной функции replace() :

Правда, здесь использован не метод replace класса string , а одноимённый алгоритм:

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

Задание символов в строке

назначает символы строке

Доступ к отдельным символам

получение указанного символа с проверкой выхода индекса за границы

получение указанного символа

получение первого символа

получение последнего символа

возвращает указатель на первый символ строки

возвращает немодифицируемый массив символов С , содержащий символы строки

Исходный код примеров из этой статьи можете скачать из нашего github-репозитория.

Допустимо объявление строковых переменных через ключевое слово var :

Для объединения строк используется оператор +:

При работе со String следует помнить, что при переопределении значения переменной создается новый экземпляр строковой переменной в памяти. Поэтому, если вам нужно собрать строку из большого количества составляющих, то использование оператора + не самый лучший вариант. В этом случае будет происходить перерасход памяти: при выполнении операции объединения с присваиванием для очень большого количества подстрок, приложение может аварийно завершиться из-за того, что сборщик мусора не будет успевать удалять неиспользуемые объекты, а новые будут продолжать появляться с большой скоростью. Для решения этой задачи используйте StringBuilder , о нем будет рассказано в конце этого урока.

Создание и инициализация объекта класса String

Для дословного представления строки, для того чтобы проигнорировать управляющие последовательности, используйте префикс @ перед значением. Сравните вывод следующей конструкции:

Если требуется подготовить строковое значение с использованием набора переменных, то можно воспользоваться статическим методом Format класса String , либо префиксом $ :

Можно явно вызвать конструктор типа c передачей в него параметров. Самый простой вариант – это передать строку:

В качестве параметра может выступать массив Char элементов:

Ещё вариант – это указать элемент типа char и количество раз, которое его нужно повторить:

Для создания строки также можно использовать указатели на Char* и SByte* , но в данном уроке эта тема рассматриваться не будет.

Базовый API для работы со строками

В рамках данного раздела рассмотрим наиболее интересные и полезные методы и свойства класса String .

Объединение строк. Оператор +, методы Concat и Join

Сцеплять строки между собой можно с помощью оператора + , при этом, в результате объединения, будет создан новый объект:

В составе API , который предоставляет System . String , есть метод Concat , который может выполнять ту же работу:

Метод Concat позволяет объединить до четырех строк через прямое перечисление. Если нужно таким образом объединить больше строковых переменных и значений, то используйте оператор +. Полезным свойством Concat является то, что он может принять на вход массив элементов типа String и объединить их:

Для объединения элементов с указанием разделителя используется метод Join . В предыдущем примере, элементы в массиве sArr1 уже содержали пробел, это не всегда удобно, решим задачу объединения элементов, которые не содержат разделителей, с помощью Join :

В качестве разделителя можно использовать любую строку:

Поиск и извлечение элементов из строки. Оператор [], методы IndexOf, IndexOfAny, LastIndexOf, LastIndexOfAny, Substring

Для получения символа из строки с конкретной позиции можно использовать синтаксис подобный тому, что применяется при работе с массивами – через квадратные скобки []:

Для решения обратной задачи: поиск индекса первого (последнего) вхождения элемента или сроки в данной строке используются методы IndexOf , IndexOfAny и LastIndexOf , LastIndexOfAny .

В таблице ниже перечислены некоторые из предоставляемых System . String вариантов этих методов.

IndexOf(Char)

Возвращает индекс первого вхождения символа.

IndexOf(Char, Int32)

Возвращает индекс первого вхождения символа начиная с заданной позиции.

IndexOf(Char, Int32, Int32)

Возвращает индекс первого вхождения символа начиная с заданной позиции, проверяется указанное количество элементов.

IndexOf(String)
IndexOf(String, Int32)
IndexOf(String, Int32, Int32)

Назначение методов совпадает с перечисленными выше, но поиск выполняется для строки.

IndexOfAny(Char[])
IndexOfAny(Char[], Int32)
IndexOfAny(Char[], Int32, Int32)

Назначение методов совпадает с перечисленными выше, но выполняется поиск индекса первого вхождения любого из переданных в массиве элементов.

Last IndexOf([Char | String])
Last IndexOf ( [Char | String], Int32)
Last IndexOf ( [Char | String], Int32, Int32)

Возвращает индекс последнего вхождения символа или строки. Можно задавать индекс, с которого начинать поиск и количество проверяемых позиций. [Char | String] – означает Char или String

LastIndexOfAny(Char[])
LastIndexOfAny(Char[], Int32)
LastIndexOfAny(Char[], Int32, Int32)

Возвращает индекс последнего вхождения любого из переданных в массиве элементов.Можно задавать индекс с которого начинать поиск и количество проверяемых позиций

Для определения того, содержит ли данная строка указанную подстроку, а также для проверки равенства начала или конца строки заданному значению используйте методы: Contains , StartsWith и EndsWith .

Contains(Char)
Contains(String)

Возвращает True если строка содержит указанный символ или подстроки.

StartsWith(Char)
StartsWith(String)

Возвращает True если строка начинается с заданного символа или подстроки.

EndsWith(Char)
EndsWith(String)

Возвращает True если строка заканчивается на заданный символ или подстроку.

Задачу извлечения подстроки из данной строки решает метод SubString :

Substring(Int32)

Возвращает подстроку начиная с указанной позиции и до конца исходной строки.

Substring(Int32, Int32)

Возвращает подстроку начиная с указанной позиции с заданной длины.

Сравнение срок

Для сравнения строк можно использовать оператор сравнения ==, при этом будут сравниваться значения строковых переменных, а не их ссылки, как это делается для других ссылочных типов.

Для сравнения также можно использовать метод Equals , но это менее удобный вариант:

Модификация срок

Класс String предоставляет довольно большое количество инструментов для изменения строк.

Вставка строки в исходную в заданную позицию осуществляется с помощью метода Insert :

Для приведения строки к заданной длине с выравниванием по левому (правому) краю с заполнением недостающих символов пробелами используются методы PadLeft и PadRight :

Метод Remove удаляет подстроку из исходной строки. Возможны два варианта использования:

Remove(Int32)

Удаляет все символы начиная с заданного и до конца строки.

Remove(Int32, Int32)

Удаляет с указанной позиции заданное число символов.

Замена элементов строки производится с помощью метода Replace . Наиболее часто используемые варианты – это замена символа на символ и строки на подстроку:

Для преобразования строки к верхнему регистру используйте метод ToUpper() , к нижнему – ToLower() :

За удаление начальных и конечных символов отвечают методы, начинающиеся на Trim (см. таблицу ниже).

Удаляет символы пробелы из начала и конца строки.

Удаляет экземпляры символа из начала и конца строки.

Удаляет экземпляры символов из начала и конца строки.

TrimStart()
TrimStart(Char)
TrimStart(Char[])

Удаляет экземпляры символов из начала строки.

TrimEnd()
TrimEnd(Char)
TrimEnd(Char[])

Удаляет экземпляры символов из конца строки.

Методы и свойства общего назначения

Рассмотрим некоторые из полезных методов и свойств, которые не вошли в приведенные выше группы.

System.Length – возвращает длину строки:

System.Split() – разделяет заданную строку на подстроки, в качестве разделителя используется указанный через параметр символ (или группа символов):

System.Empty – возвращает пустую строку.

Форматирование строк

Под форматированием строк, в рамках данного раздела, понимается встраивание в строку различных элементом (число, дата и т.п.), представленных в заданном формате. Форматирование можно осуществлять с помощью метода ToString с передачей в него нужных описателей, метода Format , который, в качестве аргументов, получает строку со специальными вставками, определяющими представление элементов и непосредственно сами элементы.

Для начала рассмотрим на нескольких примерах работу с этими методоми:

Каждый элемент форматирования представляется следующим образом:

где index – это индекс элемента, которым будет замещена данная конструкция;

alignment – выравнивание;

formatString – формат.

Ниже приведены примеры использования элементов форматирования:

Представление чисел

Для представления чисел используются следующие описатели формата (список не полный, более детальную информацию можете найти в официальной документации):

Описатель формата

“C” или “c”

“D” или “d”

Представление целого числа.

“E” или “e”

Представление числа в экспоненциальном виде.

“F” или “f”

Представление числа в формате с плавающей точкой.

“P” или “p”

Представление процентов, выводит число умноженное на 100 со знаком процента.

В любом из представленных выше примеров мы создаем строку, при этом, в последнем случае, мы создаем пустую строку без символов. Так как строки относятся к ссылочным типам данных, то никто нам не запрещает присвоить строке значение null

Строки с регулярными и буквальными литералами

Отдельное внимание при создании строк также стоит уделить такому моменту, как создание строк, содержащих какие-либо служебные символы. Например, если вам необходимо присвоить строке значение, указывающее на путь к файлу: c:\Program Files\dotnet\dotnet.exe . Если вы попробуете присвоить строке это значение как есть, то ваша программа даже не будет скомпилирована, так как Visual Studio укажет вам на ошибку:

Все дело в том, что символ обратной косой черты \ используется в строках для указания так называемых escape-последовательностей и для того, чтобы создать строку, содержащую символ \ нам необходимо либо регулярный строковый литерал , либо буквальный литерал , как показано ниже:

Например, используя escape-последовательности, мы можем вывести в консоль таблицу:

В итоге, в консоли мы увидим вот такую красивую табличку:

Что касается использования буквального литерала в строках, то его удобно использовать для того, чтобы сделать строки, содержащие какие-либо служебные символы, более читабельными. Согласитесь, что такая строка:

выглядит более читабельной, чем вот такая:

Более того, так как буквальный литерал позволяет сохранять все символы в строке как есть, то, используя его, мы можем использовать в наших строках переносы, кавычки и прочие символы как есть, например:

В результате, в консоли мы увидим следующий текст:

Также стоит отметить, что к огда содержимое двух строк, например, s1 и s2 объединяется для формирования строки, то две исходные строки не изменяются. Например:

В примере выше оператор += создает новую строку, которая содержит объединенное содержимое двух строк. Этот новый объект присваивается переменной s1 , а исходный объект, который был присвоен s1 , освобождается для сборки мусора, так как ни одна переменная не ссылается на него.

В представленном примере может показаться, что в итоге, в консоли будет строка "Hello world" , однако, на самом деле в консоли мы увидим только "Hello " так как строка s2 остается неизменной.

Мне нужно знать, что, если строка в C была назначена полностью, возможно ли снова очистить эту строку? Я могу показать вам мой желаемый результат.

Пожалуйста, помогите мне.

4 ответа

Поскольку вы строите 4-буквенные строки, вам нужен массив размером 5. Строка должна заканчиваться на \0 Если нет, то это не строка, смотрите стандарт:

1 Строка - это непрерывная последовательность символов, оканчивающаяся первым нулевым символом и включающая его.

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

На ум приходит пара способов. Учитывая, что строки в C обычно заканчиваются нулем ASCII, проще всего было бы установить первый байт в ноль.

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

Если вы хотите стереть все символы в строке, вам нужно использовать цикл.

ИЛИ ЖЕ

Другим способом может быть использование memset() для установки всей строки в нули.

но это будет работать только для обнуления до первого символа NULL.

Читайте также: