Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.50/4: Рейтинг темы: голосов - 4, средняя оценка - 4.50
Alexey104
1 / 1 / 0
Регистрация: 26.10.2014
Сообщений: 101
#1

Строки (strings) в C++

26.10.2014, 23:36. Просмотров 673. Ответов 5
Метки нет (Все метки)

Здравствуйте, уважаемые программисты!

Прошу помочь нубу-новичку разобраться с некоторыми нюансами программирования на C++. Сишку учу с нуля по книжкам(прямо рэп какой-то!). В данный момент изучаю строки(strings). Насколько я понял, строка в C++ представляет собой массив из ячеек, хранящих значения типа char, то есть, строка есть ни что иное, как массив символов. Для объявления строки используем следующий синтаксис:
C++
1
char StringName[n] = "SomeChars";
Например:
C++
1
char String[7] = "Hello!";
В данном случае String - название строки, Hello! - содержимое строки, а цифра в скобках [7] - количество символов строки(ячеек массива) с учётом завершающего нулевого символа. Если строку объявить так:
C++
1
char String[6] = "Hello!";
, то компилятор (g++ под Linux) говорит, что "initializer-string for array of chars is too long", то есть, в объявленном массиве не хватает одной ячейки для записи последнего(нулевого) символа. Однако, если выполнить следующий код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <string.h>
 
using namespace std;
 
int main()
{
  char String1[7] = "Hello!";
  cout << "String1[0] is: " << String1[0] << "\n";
  cout << "String1[1] is: " << String1[1] << "\n";
  cout << "String1[2] is: " << String1[2] << "\n";
  cout << "String1[3] is: " << String1[3] << "\n";
  cout << "String1[4] is: " << String1[4] << "\n";
  cout << "String1[5] is: " << String1[5] << "\n";
  cout << "String1[6] is: " << String1[6] << "\n\n";
  char String2[2];
  strncpy(String2, String1, 7);
  cout << "String2[0] is: " << String2[0] << "\n";
  cout << "String2[1] is: " << String2[1] << "\n";
  cout << "String2[2] is: " << String2[2] << "\n";
  cout << "String2[3] is: " << String2[3] << "\n";
  cout << "String2[4] is: " << String2[4] << "\n";
  cout << "String2[5] is: " << String2[5] << "\n";
  cout << "String2[6] is: " << String2[6] << "\n\n";
  return 0;
}
, то программа компилируется без всяких предупреждений об ошибках, несмотря на то, что в строке кода 17 значение строки, содержащей 7 символов(String1) копируется в строку, объявленную в строке кода 16 как строка, содержащая лишь 2 символа(String2). Результат выполнения программы следующий:

String1[0] is: H
String1[1] is: e
String1[2] is: l
String1[3] is: l
String1[4] is: o
String1[5] is: !
String1[6] is:

String2[0] is: H
String2[1] is: e
String2[2] is: l
String2[3] is: l
String2[4] is: o
String2[5] is: !
String2[6] is:

Вопрос:
правильно ли я понял, что несмотря на успешную компиляцию и корректную на первый взгляд работу программы, в массив String2 в строке кода 17 записалось лишь два первых символа(H, e) массива String1, а остальные символы(l, l, o, !, /0) записались за пределами массива String1, что является грубейшей ошибкой, а для правильной работы программы необходимо изменить строку кода 16 следующим образом:
C++
1
char String2[7];
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
26.10.2014, 23:36
Ответы с готовыми решениями:

Strings
По воле случая я со строками не дружу, и с ними вообще не сталкиваюсь. Меня...

Соединение Strings
Как обьеденить 2 строки char* в одну чтобы в последущем использовать в...

How to do this? Array of strings
1.George Washington (1789-1797) 2.John Adams (1797-1801) 3.Thomas Jefferson...

BST of strings
Задание реализовать для binary search tree string-ов функции add, find, print....

Самописная Extract strings
Вызывает завершение работы программы следующий проблематичный для мну код. ...

5
alsav22
5441 / 4836 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
26.10.2014, 23:51 #2
Цитата Сообщение от Alexey104 Посмотреть сообщение
Вопрос:
правильно ли я понял, что несмотря на успешную компиляцию и корректную на первый взгляд работу программы, в массив String2 в строке кода 17 записалось лишь два первых символа(H, e) массива String1, а остальные символы(l, l, o, !, /0) записались за пределами массива String1, что является грубейшей ошибкой, а для правильной работы программы необходимо изменить строку кода 16 следующим образом:
Правильно.

Добавлено через 1 минуту
Цитата Сообщение от Alexey104 Посмотреть сообщение
Насколько я понял, строка в C++ представляет собой массив из ячеек, хранящих значения типа char, то есть, строка есть ни что иное, как массив символов
Это Си-строки: массив char с '\0' в конце. В С++ есть класс string - это совсем другое: http://www.cplusplus.com/reference/string/string/
1
Andrej
И целого heap'а мало
94 / 55 / 17
Регистрация: 31.07.2014
Сообщений: 291
27.10.2014, 00:16 #3
Alexey104, тебе пока не нужны сишные строки.
Используй std::string и будет счастье.
Конечно, в плане просветления о том как пробежаться по массиву массивов массивов на них натренируешься;
но сколько копий сломаешь о heap corruption.
Например, выделишь память в куче, малось запишешь не свой кусок. Итого программа падает не сразу, а через некоторое время. Часы медитаций в дебаге и над valgrind. Недосып и, в итоге, переход на std::string.
А ещё лучше сразу перейди на питон, и желательно третий. Ну вот вряд ли тебе плюсы в жизни пригодятся.

Не по теме:

это такое моё нытьё

1
Alexey104
1 / 1 / 0
Регистрация: 26.10.2014
Сообщений: 101
27.10.2014, 04:26  [ТС] #4
Во-первых, всем спасибо за участие в моей теме!
Цитата Сообщение от Andrej Посмотреть сообщение
тебе пока не нужны сишные строки.
Используй std::string и будет счастье.
Я просто прохожу главу за главой по книжке и, как ты правильно сказал, чисто "для просветления" пишу всякие бесполезные коды, не имеющие практического применения, просто чтобы въехать, как это всё работает. В данный момент изучаю тему "массивы символов". Насколько практично использовать сишные строки, меня пока мало волнует, главное - въехать в тему на уровне молекул, а потом уже выбирать, что практичнее.
Что касается питона, то я совсем не против(и даже за) его изучить(или ещё чего), но я уже начал в плюсах, достаточно много красноглазил, переварил кучу информации, насиловал свой мозг классами, ссылками, указателями, массивами, функциями, операторами, кучами и стеками, - не зря же я это всё делал! Когда изучу плюсы, с радостью изучу что-нибудь ещё, если, конечно, мозгов хватит.

А по теме хотел бы задать ещё один вопрос:
Правильно ли я понял, что функция strncpy не копирует из исходной строки символ '\0', а сама добавляет его после копирования? То есть в строке 17 кода, указанного выше, говорится не "скопировать из строки String1 в строку String2 символы 'H', 'e', 'l', 'l', 'o', '!', '/0'", а "скопировать из строки String1 в строку String2 символы 'H', 'e', 'l', 'l', 'o', '!' и добавить в конце символ '\0'"? Если это верно, значит в строке 16 кода можно изменить 3-й аргумент функции на 6 вместо 7, и это будет корректно? Я имею-в-виду сделать так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <string.h>
 
using namespace std;
 
int main()
{
  char String1[7] = "Hello!";
  cout << "String1[0] is: " << String1[0] << "\n";
  cout << "String1[1] is: " << String1[1] << "\n";
  cout << "String1[2] is: " << String1[2] << "\n";
  cout << "String1[3] is: " << String1[3] << "\n";
  cout << "String1[4] is: " << String1[4] << "\n";
  cout << "String1[5] is: " << String1[5] << "\n";
  cout << "String1[6] is: " << String1[6] << "\n\n";
  char String2[7];
  strncpy(String2, String1, 6);
  cout << "String2[0] is: " << String2[0] << "\n";
  cout << "String2[1] is: " << String2[1] << "\n";
  cout << "String2[2] is: " << String2[2] << "\n";
  cout << "String2[3] is: " << String2[3] << "\n";
  cout << "String2[4] is: " << String2[4] << "\n";
  cout << "String2[5] is: " << String2[5] << "\n";
  cout << "String2[6] is: " << String2[6] << "\n\n";
  return 0;
}
В строке кода 17 копируем из строки String1 в строку String2 6 символов 'H', 'e', 'l', 'l', 'o', '!', а 7-й символ('\0') функция strncpy добавит сама, правильно?
0
alsav22
5441 / 4836 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
27.10.2014, 04:49 #5
Цитата Сообщение от Alexey104 Посмотреть сообщение
В строке кода 17 копируем из строки String1 в строку String2 6 символов 'H', 'e', 'l', 'l', 'o', '!', а 7-й символ('\0') функция strncpy добавит сама, правильно?
http://www.cplusplus.com/reference/cstring/strncpy/
Отладчиком умеете пользоваться? Читаете, пробуете, смотрите: когда и что добавляется.
0
Alexey104
1 / 1 / 0
Регистрация: 26.10.2014
Сообщений: 101
27.10.2014, 18:03  [ТС] #6
alsav22,
с отладчиком я пока, как обезьяна с гранатой, а вот за ссылки спасибо - всё чётко по теме расписано. Сейчас разбираюсь с GDB, а по данной теме вопросов больше не имею.

Благодарю за участие!
0
27.10.2014, 18:03
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.10.2014, 18:03

STL set of sets of strings
Вот такая колбаса(I use VS10): std::set&lt;std::set&lt;std::string&gt;&gt; s; ...

Парочка примитивных неясностей о массивах и C-strings
Когда я пишу: char * arr = new char; Выделяется память размером 7 байт под...

Create an array of strings, find and delete duplicate lines and sort rows in the aray
Write a program, the following operations: a) Create an array of strings. b)...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru