Как присвоить строке новое значение в C++?
В строке string[]=»zaqzaqzaq»; ошибка, красным выделены квадратные скобки, курсор между ними и ошибка: [Error] expected primary-expression before ‘]’ token Как правильно присвоить строке символов новое значение?
Отслеживать
задан 10 фев 2018 в 14:09
257 1 1 золотой знак 3 3 серебряных знака 15 15 бронзовых знаков
int main() , а не просто main() .
10 фев 2018 в 15:20
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
Если вы пишете на C++, то зачем вам char? Используйте готовый объект типа string:
#include using namespace std; main()
Отслеживать
ответ дан 10 фев 2018 в 14:19
Mark Tiukov Mark Tiukov
140 1 1 золотой знак 1 1 серебряный знак 13 13 бронзовых знаков
Очень неудачное имя для переменной вы выбрали.
10 фев 2018 в 14:37
C++ НЕ поддерживает int по-умолчанию
– user227465
10 фев 2018 в 15:00
@GreenDragon: Как впрочем и С его уже давно не поддерживает.
10 фев 2018 в 15:18
@zed , да, пожалуй для начинающих это не очень удачное название переменной. Спасибо за указание! 😉
10 фев 2018 в 16:03
насколько я понел речь шла о инициализации массива, а не как получать строку
char string[] = "qazqazqaz"; char s[] = "zaqzaqzaq"; strcpy(string, s); cout
Отслеживать
ответ дан 10 фев 2018 в 14:39
AR Hovsepyan AR Hovsepyan
15.9k 3 3 золотых знака 14 14 серебряных знаков 30 30 бронзовых знаков
А если новая строка будет длиннее?
10 фев 2018 в 14:47
@zed это уже другой вопрос
10 фев 2018 в 14:55
Поскольку вы рассмотрели лишь крайний случай, когда обе строки имеют одинаковый размер, ваш ответ по сути бесполезен. Вопрос же в том, как динамически присваивать строке другое значение, которое может и не совпадать по длине.
10 фев 2018 в 15:02
@ zed, я читать умею, но не нашел в вопросе даже намека на ваше утверждение. Просто простой ответ на простой вопрос - не вижу надобности обсуждать дальше. Даже неинтересно. То что у вас есть знания по С строкам, я уже понел
10 фев 2018 в 15:10
Самая последняя строка в вопросе: Как правильно присвоить строке символов новое значение? И раз там не сказано, что надо присвоить строку того же самого размера, то стоит воспринимать вопрос в общем.
22.5 – Присваивание и обмен значениями для объектов std::string
Самый простой способ присвоить значение строке – использовать перегруженную функцию operator= . Существует также функция-член assign() , которая дублирует некоторые из этих возможностей.
string& string::operator= (const string& str)
string& string::assign (const string& str)
string& string::operator= (const char* str)
string& string::assign (const char* str)
string& string::operator= (char c)
Эти функции присваивают строке значения различных типов. Они возвращают *this , чтобы их можно было объединить в «цепочку».
Обратите внимание, что нет функции assign() , которая принимает один символ char .
string sString; // Присваиваем строковое значение sString = string("One"); cout
One Two Three Four 5 Six Six
Функция-член assign() также имеет несколько других вариантов:
string& string::assign (const string& str, size_type index, size_type len)
Присваивает подстроку str , начиная с позиции index , и длиной len .
- Выдает исключение out_of_range , если индекс выходит за границы строки.
- Возвращает *this , чтобы можно было объединить в «цепочку».
const string sSource("abcdefg"); string sDest; // присваиваем подстроку из источника, начиная с индекса 2, длиной 4 sDest.assign(sSource, 2, 4); cout
cdef
string& string::assign (const char* chars, size_type len)
Присваивает len символов из массива символов в стиле C.
- Выдает исключение length_error , если результат превышает максимальное количество символов
- Возвращает *this , чтобы можно было объединить в «цепочку».
string sDest; sDest.assign("abcdefg", 4); cout
abcd
Эта функция потенциально опасна, и ее использование не рекомендуется.
string& string::assign (size_type len, char c)
Присваивает len вхождений символа c .
- Выдает исключение length_error , если результат превышает максимальное количество символов
- Возвращает *this , чтобы можно было объединить в «цепочку».
string sDest; sDest.assign(4, 'g'); cout
gggg
Обмен значениями
Если у вас есть две строки, и вы хотите поменять их значения местами, вы можете использовать две функции с именем swap() .
void string::swap (string &str)
void swap (string &str1, string &str2)
Обе функции меняют местами значения двух строк. Функция-член меняет местами значения *this и str , глобальная функция меняет местами значения str1 и str2 .
Эти функции эффективны и должны использоваться вместо присваиваний для выполнения обмена значений строк.
string sStr1("red"); string sStr2("blue"); cout
red blue blue red red blue
Теги
Сохранить или поделиться
На сайте работает сервис комментирования DISQUS, который позволяет вам оставлять комментарии на множестве сайтов, имея лишь один аккаунт на Disqus.com.
В случае комментирования в качестве гостя (без регистрации на disqus.com) для публикации комментария требуется время на премодерацию.
Присоединяйтесь к нам во ВКонтакте!
- Антенны и распространение радиоволн
- Беспроводная связь
- Высокочастотная техника
- Волоконно-оптические линии связи (ВОЛС)
- Измерительная техника
- Исполнительные механизмы и драйверы
- САПР
- Спутниковая связь
- Схемотехника
- Телевидение
- Цифровая электроника
- Технологии и инструменты
- Электронные компоненты
- А что внутри?
- Прочее (радиоэлектроника)
- Алгоритмы и структуры данных
- Базы данных
- Веб-разработка
- Мультимедиа (разработка ПО)
- Нейронные сети
- Паттерны проектирования
- Связь
- Системы сборки ПО
- Языки программирования
- Компьютерные сети
- Операционные системы
- Верстка
- Системы контроля версий
- История технологий
- Мультимедиа
- Новости телекома
- Нормативная документация
- Охрана труда
- Полезные программы
- Просто интересно
- Экономика телекоммуникаций и электронной промышленности
- Экономика и инвестиции
Мы в соцсетях
Особенности работы со строками в языке Си
Неформатированные ввод из стандартного потока и вывод в стандартный поток
С помощью функции printf() можно легко вывести на экран строку, содержащую пробелы:
printf("%s", "Hello world");
Ввести строку с пробелами уже сложнее. Для scanf() любой символ пустого пространства является сигналом завершения ввода очередных данных, если только не производится считывание самого символа. Чтобы ввести строку произвольной длины, содержащую пробелы в неизвестных местах, приходится использовать шаблон:
scanf("%[^'\n']", str);
Также на помощь может прийти функция getchar() , осуществляющая посимвольный ввод данных:
#include int main() { char str[20], i; for (i = 0; (str[i] = getchar()) != '\n'; i++); str[i] = '\0'; printf("%s\n", str); }
В заголовке цикла getchar() возвращает символ, далее записываемый в очередную ячейку массива. После этого элемент массива сравнивается с символом '\n'. Если они равны, то цикл завершается. После цикла символ '\n' в массиве "затирается" символом '\0'. В условии цикла должна быть также предусмотрена проверка на выход за пределы массива; чтобы не усложнять пример, опущена.
Однако в языке программирования C работать со строками можно проще. С помощью функций стандартной библиотеки gets() и puts() получают строку из стандартного потока и выводят в стандартный поток. Буква s в конце слов gets и puts является сокращением от слова string (строка).
В качестве параметров обе функции принимают указатель на массив символов (либо имя массива, либо указатель).
Функция gets() помещает полученные с ввода символы в указанный в качестве аргумента массив. При этом символ перехода на новую строку, который завершает ее работу, игнорируется.
Функция puts() выводит строку на экран и при этом сама добавляет символ перехода на новую строку. Простейший пример использования этих функций выглядит так:
#include int main() { char str[100]; gets(str); puts(str); }
При компиляции данной программы появляется предупреждение об опасности использования gets (но программа скомпилируется и будет работать). Вместо нее рекомендуют использовать функцию fgets . Однако последней кроме указателя на строку также надо передать лимит количества считываемых символов и из какого потока ввода поступают данные. В данном случае ‒ из стандартного ‒ stdin :
#include #define N 100 int main() { char str[N]; fgets(str, N, stdin); puts(str); }
При этом в строку помещается и символ перехода на новую строку ‒ '\n'. И только после него символ конца строки ‒ '\0'. Если переход не нужен, от него можно избавиться так:
str[strcspn(str, "\n" )] = '\0';
Итак, если вы работаете со строками, а не другими типами данных, при этом нет необходимости выполнять их посимвольную обработку, то может быть удобнее пользоваться функциями puts и fgets .
Массив символов и указатель на строку
Как мы знаем, строка представляет собой массив символов, последний элемент которого является нулевым символом по таблице ASCII, обозначаемым '\0'. При работе со строками также как с численными массивами можно использовать указатели. Мы можем объявить в программе массив символов, записать туда строку, потом присвоить указателю адрес на первый или любой другой элемент этого массива и работать со строкой через указатель:
char name[30]; char *p; printf("Введите имя и фамилию: "); fgets(name, sizeof(name), stdin); printf("Имя: "); for (p = name; *p != ' '; p++) putchar(*p); printf("\nФамилия: "); puts(p + 1);
В заголовке цикла указателю сначала присваивается адрес первого элемента массива, его значение увеличивается до тех пор, пока не встретится пробел. В итоге указатель указывает на пробел, и мы можем получить с его помощью вторую часть строки.
Иногда в программах можно видеть такое объявление и определение переменной-указателя:
char *strP = "Hello World!";
Строку, которая была присвоена не массиву, а указателю, также можно получить, обратившись по указателю:
puts(strP);
Но давайте посмотрим, что же все-таки происходит, и чем такая строка, присвоенная указателю, отличается от строки, присвоенной массиву.
Когда в программе определяются данные и объявляются переменные, то под них отводится память. При этом данные, которые не были присвоены переменным, поменять в процессе выполнения программы уже нельзя.
Что происходит в примере? В программе вводится строковый объект, который по сути является строковой константой (литералом). Ссылка на первый элемент этой строки присваивается указателю. Мы можем менять значение указателя сколько угодно, переходить к любому из элементов константного массива символов или даже начать ссылаться на совершенно другую строку. Но вот поменять значение элементов строки не можем. Это можно доказать таким кодом:
char *strP; // работает, но строку нельзя изменить strP = "This is a literal"; puts(strP); printf("%c\n",strP[3]); strP[3] = 'z'; // не получится
В последней строке кода возникнет ошибка (при выполнении программы), т.к. совершается попытка изменить строку-константу.
Тем более нельзя делать так:
char *strP; // ошибка сегментирования scanf("%s",strP);
В данном случае память не была выделена под массив символов, который мы пытаемся получить функцией scanf() ; память была выделена только под указатель. Поэтому записать строку просто некуда. Другое дело, если память была выделена с помощью объявления массива, после чего указателю был присвоен адрес на этот массив:
char str[12]; char *strP; strP = str; // память резервируется под массив ранее gets(strP); puts(strP);
Итак, если вам требуется в программе неизменяемый массив символов, то можете определить его через указатель.
Передача строки в функцию
Передача строки в функцию ничем не отличается от передачи туда массива чисел:
char name[30]; char *p; printf("Введите имя и фамилию: "); fgets(name, sizeof(name), stdin); printf("Имя: "); for (p = name; *p != ' '; p++) putchar(*p); printf("\nФамилия: "); puts(p + 1);
В этом примере функция change принимает в качестве аргумента указатель на символ. В теле функции значение указателя инкрементируется, указывая на следующий символ массива. В теле цикла инкрементируется значение, которое находится по адресу, который содержит указатель.
Объявите в программе три массива символов. Данные для двух из них получите с помощью вызовов функции fgets() . Третий массив должен содержать результат конкатенации (соединения) двух введенных строк. Напишите функцию, которая выполняет конкатенацию строк.
Массив строк и массив указателей
Рассмотрим более сложный пример. Допустим, у нас есть набор строк. Требуется выполнить сортировку строк по возрастанию по признаку длины: сначала вывести самые короткие строки, затем более длинные.
Набор строк можно представить как двумерный массив, т.е. массив, состоящий из одномерных массивов, где каждый одномерный массив — это строка символов:
char str[][10] = {"Hello", "World", ". ", "&&&"};
Представьте себе, что значит выполнить сортировку строк. Это значит, надо поменять местами содержимое множества ячеек памяти. Это достаточно трудоемкая для компьютера работа, особенно если строк очень много. Однако можно поступить по-иному. Достаточно создать массив указателей, каждый элемент которого будет указывать на соответствующую ему строку первого массива. Далее выполнить сортировку указателей, что несомненно быстрее. Конечно, сам массив строк отсортирован не будет, однако благодаря указателям у нас будет хранится отсортированный "срез" массива:

#include #include #define N 6 #define M 30 void sortlen(char *s[]); int main() { char strings[N][M]; char *p[N]; for (int i = 0; i N; i++) { fgets(strings[i], M, stdin); p[i] = &strings[i][0]; } printf("\n"); sortlen(p); for (int i = 0; i N; i++) { printf("%s", p[i]); } } // **s == *s[] - массив указателей void sortlen(char **s) { int i, j; char *str; for (i = 0; i N-1; i++) for (j = 0; j N-i-1; j++) if (strlen(s[j]) > strlen(s[j+1])) { str = s[j]; s[j] = s[j+1]; s[j+1] = str; } }
Примечания к программе:
- Функция strlen объявлена в заголовочном файле string.h . Она возвращает длину строки без учета завершающего нулевого символа.
- Сортировка выполняется методом пузырька: если длина строки, на которую ссылается следующий указатель массива s , меньше длины строки под текущим указателем, то значения указателей меняются.
- Выражение p[i] = &strings[i][0] означает, что элементу массива указателей присваивается ссылка на первый символ каждой строки.
Напишите программу, которая сортирует строки по алфавиту. Для упрощения задачи пусть сортировка выполняется только по первым буквам строк (если первые буквы слов одинаковы, то вторые и последующие символы проверять не надо).
Курс с решением задач:
pdf-версия
Как присвоить значение строке в c
Подобно тому, как все математические функции "лежат" в библиотеке math.h, функции для работы со строками объединены в библиотеке string.h
Вопрос: КАК узнать длину строки?
Для того, чтобы точно знать, сколько выделить памяти для хранения строки, часто нам нужно получить длину конкретной строки. Разного рода функции иногда предлагают не просто ввести строку, а указать какое количество символов из неё мы хотели бы использовать. Чаще всего мы хотим ввести всю строку, поэтому есть смысл не считать вручную, а просто измерить длину строки и подставить в функцию.
#include
#include
void main()
char *str = "машина";
>
Функция strlen() возвращает количество символов в строке. Например для строки "машина" она вернёт число 6.
Вопрос: Как сложить две строки?
Помните мы писали программу, которая c нами здоровалась? Там была строка:
И умная программка добавляла в конец ваше имя.
А если мы хотим сложить две строки, которые заранее не известны? Для этого в программировании применяется операция "склеивания" - конкатенции (знаю - жуткое слово!), которая позволяет просто сложить две строки вместе и получить одну. В языке СИ такой операции нет, но зато в библиотеке string.h есть специальная функция strncat(), которая позволяет склеивать исходную строку с подстрокой.
void main()
char kuda[20];
char *otkuda="Федерация";
strcpy(kuda, "Российская "); //копирование в строку kuda
strncat(kuda, otkuda, strlen(otkuda)); //склеиваем две строки, результат - в строке kuda
cout
Функция strcpy(to, from) копирует строку from в строку to. Кстати, это ещё один из способов присвоения строке значения. Функция strncat объединяет две строки, дописывая в конец строки kuda строку otkuda. Этот процесс можно сравнить с локомотивом, в конец которого на товарной станции прицепляют ещё один вагончик. Для каждого нового вагона нам понадобится функция strncat.
Обратите внимание, что у функции strncat три аргумента. Функция гибка и позволяет скопировать не всю строку, а только её часть. Если мы точно знаем сколько символов в строке otkuda, можно третьим аргументом задать число, но проще всего измерить длину строки с помощью известной нам уже функции strlen().
Вопрос: КАК из строки сделать число?
Для чего это нужно? Часто программа получает данные от пользователя в виде строки. Например, данные полученные из текстовых полей Windows - всегда строковые. И даже если пользователь ввёл число, оно всё равно будет представлено, как строка. Чтобы подставить это число в форумулу, вам придётся его конвертировать в строку.
void main()
int n;
char *str="123456"; //объявляем строку
n=atoi(str); //конвертируем в число
В некоторых классах Windows есть методы, позволяющие сразу получать целые числа из текстовых полей, но метода, позволяющего сразу считывать числа с плавающей запятой, нет, поэтому в любом случае вам понадобится конвертирование. Для преобразования строки в число с плавающей запятой существует функция atof(char *str), которая по своему применению аналогична.
В этом примере мы используем новую для нас библиотеку "stdlib.h" - в данной библиотеке содержится большинство функций конвертирования, а также множество других функций самого разного назначения. Это библиотека очень широкого профиля.
После получения строки из поля ввода, конвертирования в число, подстановки в формулу, или куда-то ещё, ответ зачастую придётся выводить в какое-нибудь окно. Естественно, напрямую число в окно мы не сможем - оно нас просто не поймёт, и заставит выполнять обратное преобразование - теперь уже из числа в строку.
Иногда ответ должен сопровождаться каким-то текстом, например: "U = 127,24 v ". Для создания такого дружественного интерфейса удобнее использовать не саму операцию конвертирования, а записать в один буфер и число и текст.
Функция sprintf аналогична функции printf, с той лишь разницей, что вывод информации осуществляется не в какое-то устройство вывода, а в буфер данных. Используя эту функцию, мы сможем комбинировать различные типы данных в любой последовательности.
void main()
char buffer[25]; //строка, длиной 25 символов
const double f=127.24; //число с плавающей точкой
sprintf(buffer, "U = %3.2f V\n", f);
Однако, если нам необходимо просто преобразовать число в строку, можно использовать функцию конвертирования, описанную в следующем разделе.
Вопрос: КАК из числа сделать строку?
#include
void main()
<
int number = 123456;
char *string;
itoa(number, string, 10); //число 10 заботится о добавлении минуса отрицательными числам
printf("Число = %d Строка = %s", number, string);
>
Конвертирование - очень важная задача, и в математических программах без неё никуда. Если ваша программа что-то считает, получая данные от пользователя, вы будете использовать конвертирование постоянно.
Вопрос: КАК что-то найти в строке?
Иногда нам нужно проверить строку на наличие в ней какого-нибудь символа. Например, если пользователь вводит свой E-mail хорошо бы проверить, есть ли в нём символ "at", который в России чаще называют собакой @? Кроме того, в каждом адресе электронной почты есть по крайней мере одна точка.
Следующая программа последовательно проверяет наличие в строке знака "@" и точки.
void main()
char *ptr;
printf("Введите E-mail: ");
scanf("%s", email);
ptr = (char *)memchr(email, '@', strlen(email));
ptr = (char *)memchr(email, '.', strlen(email));
printf("\n%s не является E-mail адресом", email);
>
else printf("\nE-mail адрес: %s успешно введён!", email);
Переменная flag - своеобразный выключатель, который имеет два состояния "истина" и "ложь". Такие переменные программисты часто так и называют "флагами" или "флажками". Они обозначают состояние. Первоначально переменная flag = 0. Но если программа не обнаруживает в строке знака "@" или точки, значение flag поменяется на 1. Условий может быть и больше (например, мы могли бы проверить, есть ли какие-то символы до знака "@" и находится ли точка после знака @, а не до него), однако работать они будут по тому же принципу.
В конце программы проверяется значение переменной flag, и если она изменила своё значение, E-mail адрес признаётся некорректным.
При разработки больших программ подобные проверки необходимо производить буквально на каждом шагу, они делают программу более надёжной и отказоустойчивой, страхуя нас от недопустимого типа данных. Согласитесь, если мы попытаемся отправить письмо на некорректный адрес, приятного в этом будет мало! Однако во избежание увеличения кода, мы заключим процедуру проверки адреса в маленькую проверочную функцию вида:
int IsEmail(char *email)
которая будет возвращать 0, если E-mail адрес был введён недостаточно корректно.
Часто производители программного обеспечения требуют регистрации и предлагают пользователю заполнить форму, в которой в том числе есть просьба указать электронный адрес. Знать ваш E-mail адрес производителю жизненно важно, чтобы впоследствии заваливать вас своей рекламой. Поэтому если вы введёте свой адрес неправильно или вообще проигнорируете эту просьбу, электронная форма откажется вас регистрировать.
Функция поиска в строке незаменима при работе с файлами (а храним мы данные именно в них - лучшего пока ничего не придумали). Есть и другие применения поиска: когда программа предлагает пользователю сохранить файл, с которым он работал, необходимо ввести его имя. Однако пользователи попадаются с совершенно разным профессиональным уровнем: кто-то вводит имена файлов с расширениями: "picture.bmp" , а кто-то и не знает, что такое расширение. Нужно предусмотреть оба случая, и в случае, если пользователь просто ввёл имя: "моя картинка. " добавить к этому имени расширение. Пример решения этой проблемы приведён ниже.
#include
#include
#include
void main()
char *ptr;
printf("Введите имя файла: ");
scanf("%s", filename);
ptr = (char *)memchr(filename, '.w', strlen(filename));
strncat(filename, ".bmp", 4);
>
printf("\nИмя файла: %s", filename);
Вопрос: КАК сравнить две строки?
Часто, когда вы получаете от пользователя не числовые данные, а строковые, вам надо сравнить строку с уже имеющимся эталоном. Допустим, вы хотите, чтобы пользователь зарегистрировал свою версию вашей программы и ввёл пароль. Для этого и нужна функция сравнения строк strncmp(). Она возвращает ноль, если строки одинаковы.
Следующая ниже программа вполе функциональна. Она ни за что не пропустит построннего на ваш компьютер. При желании, вы можете включить её в файл autoexec.bat. Доступ посторонним будет закрыт навеки! (Конечно если вы всё ещё пользуетесь Windows 98).
char *password="BUSH"; //наш пароль
char enter[256]; //строка, которую будет вводить пользователь
do printf("Введите пароль: ");
scanf("%s", enter);
//сравниваем две строки по всей длине
ptr = strncmp(enter, password, strlen(password));
//если строки одинаковы
if (ptr == 0)
printf("Доступ открыт");
return(0);
>
else printf("Введён неверный пароль!");
>
>while(ptr!=0); //цикл повторяется, пока ptr не будет =0.
return 0;
>
Конечно в реальности никто не будет прописывать пароль в коде программы, иначе мало-мальски грамотный хаккер запросто его оттуда "достанет". Настоящие программы генерируют пароль из имени пользователя, таким образом, чтобы пароли никогда не повторялись. Также популярна онлайн регистрация, при которой пользователь получает пароль, регистрируясь на сайте фирмы. Получив такой пароль, программа преобразует его по сложному алгоритму и проверяет на соответствие какому-то правилу - например сумма кодов символов должна всегда быть равна 100 (или что-то в этом роде). Дружеский совет - никогда не давайте "говорящие" пароли, как в данном примере. Такие пароли разгадываются элементарно, путём простого перебора символов. Хороший пароль должен содержать цифры и буквенные символы разного регистра, также неплохо было бы включить в него специальные символы. В результате должно получиться нечто вроде: "$&weh!60Om17rv".
Подытожим. Мы освоили достаточно операций для работы со строками. Их хватит на первый и на второй случай. Если же вам понадобится что-то большее, читайте описания функций библиотеки string.h. В справочной системе.