Как вернуть string из функции c
Перейти к содержимому

Как вернуть string из функции c

  • автор:

C++: Возврат значений

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

void Greating() < std::cout int main()

Пользы от таких функций не очень много, так как результатом их работы невозможно воспользоваться внутри программы.

В этом уроки мы рассмотрим, как сделать наши функции полезными.

Возвращаемые значения

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

Чтобы вернуть значение вызывающей стороне, необходимы две вещи:

  • Функция должна указать, значение какого типа будет возвращено. Это делается путем установки типа возвращаемого значения функции, который является типом, определенным перед именем функции
  • Внутри функции, которая будет возвращать значение, используем инструкцию return . Это нужно, чтобы указать конкретное значение, возвращаемое вызывающей стороне. Конкретное значение, возвращаемое функцией, называется возвращаемым значением. Когда инструкция return выполняется, возвращаемое значение копируется из функции обратно в вызывающую функцию. Этот процесс называется возвратом по значению

Общий вид функции:

 имя функции(аргументы)

Рассмотрим простую функцию, которая возвращает строку. Также пример программы, которая ее вызывает:

#include #include // функция возвращает строку, поэтому тип возвращаемого значения std::string std::string GetDomain() < return "Hexlet"; >int main() < std::cout 

Выполнение начинается с верхней части main . В первой же инструкции происходит вызов функции GetDomain() . В результате она возвращает конкретное значение Hexlet обратно вызывающей стороне, которое затем выводится в консоль через std::cout.

Любой код после return не выполняется:

int sum()

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

#include std::string GetDomain() < std::string domain < "Hexlet" >; return domain; > 

Здесь мы не возвращаем переменную. Возвращается всегда значение, которое находится в этой переменной. Ниже пример с вычислениями:

int sum()

Здесь сначала будет произведено вычисление, а затем результат мы вернем из функции.

Отсутствие возвращаемого значения

Функции не обязаны возвращать значение. Чтобы сообщить компилятору, что функция не возвращает значение, используется тип возвращаемого значения void .

Посмотрим на функцию Greating() :

#include void Greating()

Эта функция имеет тип возвращаемого значения void . Это указывает на то, что она не возвращает значение вызывающей стороне.

Возврат значения из main

Теперь у нас есть концептуальные инструменты, чтобы понять, как работает функция main .

Когда программа выполняется, операционная система вызывает функцию main . Инструкции в main выполняются последовательно.

Также main возвращает целочисленное значение — обычно 0, и программа завершается. Значение, возвращаемое из main , называют кодом возврата. По нему судят об успешности выполнения программы.

Задание

Реализуйте функцию SayHurrayThreeTimes() , которая возвращает строку "hurray! hurray! hurray!".

Упражнение не проходит проверку — что делать? ��

Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:

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

В моей среде код работает, а здесь нет ��

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

Мой код отличается от решения учителя ��

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

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

Прочитал урок — ничего не понятно ��

Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.

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

Полезное

  • std::string
  • Завершение программы С++

Как вернуть string из функции c

Метод может возвращать значение, какой-либо результат. В примере выше были определены два метода, которые имели тип void . Методы с таким типом не возвращают никакого значения. Они просто выполняют некоторые действия.

Но методы также могут возвращать некоторое значение. Для этого применяется оператор return , после которого идет возвращаемое значение:

return возвращаемое значение;

Например, определим метод, который возвращает значение типа string :

string GetMessage()

Метод GetMessage имеет тип string , следовательно, он должен возвратить строку. Поэтому в теле метода используется оператор return , после которого указана возвращаемая строка.

При этом методы, которые в качестве возвращаемого типа имеют любой тип, кроме void , обязательно должны использовать оператор return для возвращения значения. Например, следующее определение метода некорректно:

string GetMessage()

Также между возвращаемым типом метода и возвращаемым значением после оператора return должно быть соответствие. Например, в следующем случае возвращаемый тип - string , но метод возвращает число (тип int), поэтому такое определение метода некорректно:

string GetMessage() < return 3; // Ошибка! Метод должен возвращать строку, а не число >

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

string GetMessage() < return "Hello"; >string message = GetMessage(); // получаем результат метода в переменную message Console.WriteLine(message); // Hello

Метод GetMessage() возвращает значение типа string . Поэтому мы можем присвоить это значение какой-нибудь переменной типа string: string message = GetMessage();

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

string GetMessage() < return "Hello"; >void PrintMessage(string message) < Console.WriteLine(message); >PrintMessage(GetMessage());

В вызове PrintMessage(GetMessage()) сначада вызывается метод GetMessage() и его результат передается параметру message метода PrintMessage

После оператора return также можно указывать сложные выражения или вызовы других методов, которые возвращают определенный результат. Например, определим метод, который возвращает сумму чисел:

int Sum(int x, int y) < return x + y; >int result = Sum(10, 15); // 25 Console.WriteLine(result); // 25 Console.WriteLine(Sum(5, 6)); // 11

Метод Sum() имеет тип int , следовательно, он должен возвратить значение типа int - целое число. Поэтому в теле метода используется оператор return , после которого указано возвращаемое число (в данном случае результат суммы переменных x и y).

Сокращенная версия методов с результатом

Также мы можем сокращать методы, которые возвращают значение:

string GetMessage()

аналогичен следующему методу:

string GetMessage() => "hello";

int Sum(int x, int y)

аналогичен следующему методу:

int Sum(int x, int y) => x + y;

Выход из метода

Оператор return не только возвращает значение, но и производит выход из метода. Поэтому он должен определяться после остальных инструкций. Например:

string GetHello()

С точки зрения синтаксиса данный метод корректен, однако его инструкция Console.WriteLine("After return") не имеет смысла - она никогда не выполнится, так как до ее выполнения оператор return возвратит значение и произведет выход из метода.

Однако мы можем использовать оператор return и в методах с типом void . В этом случае после оператора return не ставится никакого возвращаемого значения (ведь метод ничего не возвращает). Типичная ситуация - в зависимости от опеределенных условий произвести выход из метода:

void PrintPerson(string name, int age) < if(age >120 || age < 1) < Console.WriteLine("Недопустимый возраст"); return; >Console.WriteLine($"Имя: Возраст: "); > PrintPerson("Tom", 37); // Имя: Tom Возраст: 37 PrintPerson("Dunkan", 1234); // Недопустимый возраст

Здесь метод PrintPerson() в качестве параметров принимает имя и возраст пользователя. Однако в методе вначале мы проверяем, соответствует ли возраст некоторому диапазону (меньше 120 и больше 0). Если возраст находится вне этого диапазона, то выводим сообщение о недопустимом возрасте и с помощью оператора return выходим из метода. После этого метод заканчивает свою работу.

Однако если возраст корректен, то выводим информацию о пользователе на консоль. Консольный вывод:

Имя: Tom Возраст: 37 Недопустимый возраст

Как вернуть string из функции c

Здравствуйте, Аноним, Вы писали:

А>Всех с наступяющими праздниками.
А>Господа, есть следующая функция:
А>

А>////////////////////////////////////////////////////////////////////////// А>const std::string &CXxxDlg::GetMyStr() А> < А>static std::string stVar = "bla-bla-bla"; А>. А>. А> return stVar; А>> А>. А>std::string st = GetMyStr(); А>. А>

А>Вопрос: Корректно ли возвращать так std::string? Сколько будет "жить" эта stVar.

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

CXxxDlg::GetMyStr(string& o_str)

Re[2]: Возврат std::string из функции

От: TarasKo
Дата: 29.12.06 09:55
Оценка:

TK>Я бы не стал так возвращать string и вообще любой другой объект. В момент вызова оператора= тот объект ссылку на которого мы вернули уже разрушен если конечно он был создан в стеке.
TK>Если хочешь возвращать по ссылке, лучше это делать через параметры.

Re[2]: Возврат std::string из функции

От: Аноним
Дата: 29.12.06 09:56
Оценка: -1

Нифиганиразрушен. Там static. Все работает. Остальное — дело вкуса.
Re: Возврат std::string из функции

От: Аноним
Дата: 29.12.06 10:11
Оценка:

Здравствуйте, Аноним, Вы писали:

А>

А>////////////////////////////////////////////////////////////////////////// А>std::string CXxxDlg::GetMyStr() А> < А>std::string stVar = "bla-bla-bla"; А>

А>Вопрос: Корректно ли возвращать так std::string? Сколько будет "жить" эта stVar.
Так почему сделать не хочешь?

Re[3]: Возврат std::string из функции

От: TarasKo
Дата: 29.12.06 10:16
Оценка:

Здравствуйте, Аноним, Вы писали:

А>Нифиганиразрушен. Там static. Все работает. Остальное — дело вкуса.

А блин static не заметил. Сорри

Re: Возврат std::string из функции

От: remark http://www.1024cores.net/
Дата: 29.12.06 10:23
Оценка:

Здравствуйте, Аноним, Вы писали:

А>Всех с наступяющими праздниками.
А>Господа, есть следующая функция:
А>

А>////////////////////////////////////////////////////////////////////////// А>const std::string &CXxxDlg::GetMyStr() А> < А>static std::string stVar = "bla-bla-bla"; А>. А>. А> return stVar; А>> А>. А>std::string st = GetMyStr(); А>. А>

А>Вопрос: Корректно ли возвращать так std::string? Сколько будет "жить" эта stVar.

Вполне нормально. Часто делают так, что бы избежать лишних копирований:

class AAA < std::mapint, std::string> m; const std::string& find(int key) const < static const std::string empty; const std::mapint, std::string>::const_iterator i = m.find(key); if (m.end() != i) return *i; else return empty; > >;

Re[2]: Возврат std::string из функции

От: Аноним
Дата: 29.12.06 10:41
Оценка:

Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Аноним, Вы писали:

А>>

А>>////////////////////////////////////////////////////////////////////////// А>>std::string CXxxDlg::GetMyStr() А>>< А>> std::string stVar = "bla-bla-bla"; А>>

А>>Вопрос: Корректно ли возвращать так std::string? Сколько будет "жить" эта stVar.
А>Так почему сделать не хочешь?
Это просто примерю.

Re: Возврат std::string из функции

От: Centaur
Дата: 29.12.06 11:00
Оценка:

Здравствуйте, Аноним, Вы писали:

А>Господа, есть следующая функция:
А>

А>////////////////////////////////////////////////////////////////////////// А>const std::string &CXxxDlg::GetMyStr() А> < А>static std::string stVar = "bla-bla-bla"; А>. А>. А> return stVar; А>> А>

А>Вопрос: Корректно ли возвращать так std::string? Сколько будет "жить" эта stVar.

Как объект — жить будет столько, сколько понадобится. То есть до скончания всей программы. Потому что static.

А вот как значение — будет жить только от одного вызова до другого. То есть, если функция решит в первый раз вернуть "bla-bla-bla", а во второй раз "abracadabra", то первый результат будет затёрт. И не дай б#г первому клиенту ещё держать указатель на данные первого результата, когда это произойдёт.

Re: Возврат std::string из функции

От: Sm0ke ksi
Дата: 29.12.06 11:07
Оценка:

Здравствуйте, Аноним, Вы писали:

А>Всех с наступяющими праздниками.
А>Господа, есть следующая функция:
А>

А>////////////////////////////////////////////////////////////////////////// А>const std::string &CXxxDlg::GetMyStr() А> < А>static std::string stVar = "bla-bla-bla"; А>. А>. А> return stVar; А>> А>. А>std::string st = GetMyStr(); А>. А>

А>Вопрос: Корректно ли возвращать так std::string? Сколько будет "жить" эта stVar.

В многопоточном приложении будет работать не правильно.

Re: Возврат std::string из функции

От: Аноним
Дата: 29.12.06 11:12
Оценка:

Здравствуйте, Аноним, Вы писали:

А>Всех с наступяющими праздниками.
А>Господа, есть следующая функция:
А>

А>////////////////////////////////////////////////////////////////////////// А>const std::string &CXxxDlg::GetMyStr() А> < А>static std::string stVar = "bla-bla-bla"; А>. А>. А> return stVar; А>> А>. А>std::string st = GetMyStr(); А>. А>

А>Вопрос: Корректно ли возвращать так std::string? Сколько будет "жить" эта stVar.

В принципе всё корректно. При вызове
std::string st = GetMyStr();
создаётся новый объёкт st в который копируется результат работы функции GetMyStr.

Сама stVar будет создана в момент запуска программы (до функции main)
и будет жить до её полного завешения. Порядок создания и разрушения таких объектов
зависит от порядка их объявления в тексте программы.

Re[2]: Возврат std::string из функции

От: demi
Дата: 29.12.06 11:27
Оценка:

Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Аноним, Вы писали:

А>>Всех с наступяющими праздниками.
Присоедиянюсь!

Разрешите подытожить:
-Корректно. Видимо сделано для устранения копирующего конструктора.
-Будут проблемы с многопоточностью. Вернуть string вместо string& — заморочек не будет.
-Возможны проблемы, если кто-то специально или случайно поменяет это строку там где этого не ожидается (писали выше).

Лично я бы так делать в 95% случаев не стал. Но есть 5%

Не стыдно попасть в дерьмо, стыдно в нём остаться!
Re: Возврат std::string из функции

От: ILva_
Дата: 29.12.06 11:28
Оценка:

Здравствуйте, Аноним, Вы писали:

А>Всех с наступяющими праздниками.
А>Господа, есть следующая функция:
А>

А>////////////////////////////////////////////////////////////////////////// А>const std::string &CXxxDlg::GetMyStr() А> < А>static std::string stVar = "bla-bla-bla"; А>. А>. А> return stVar; А>> А>. А>std::string st = GetMyStr(); А>. А>

А>Вопрос: Корректно ли возвращать так std::string? Сколько будет "жить" эта stVar.

Такой прием возможен и часто используется, как писали выше.
Но тут усть некие неприятные моменты.
Как известно, переменная stVar будет инициализированна 1 раз при первом вызове ф-ции и будет существовать до конца завершения программы.
Кто-нибудь может не разбираясь вставить в программу такой код:

std::string& myStr = const_cast(GetMyStr()); // теперь можно править статическую переменную myStr = "alb-alb-alb!";

Теперь все, кто позже обращался к этой ф-ции будут получать не то, что они ожидали:

std::string myStr2 = GetMyStr(); // вернет "alb-alb-alb!"

И все ссылки и указатели также изменятся.
Так что пользоваться надо аккуратно
Re[2]: Возврат std::string из функции

От: Аноним
Дата: 29.12.06 11:42
Оценка: +1

IL_>Кто-нибудь может не разбираясь вставить в программу такой код:
IL_>

IL_>std::string& myStr = const_cast(GetMyStr()); // теперь можно править статическую переменную IL_>myStr = "alb-alb-alb!"; IL_>

assert(stVar == "bla-bla-bla"); поможет отыскать таких умников
А вообще если ктото задасться целью развалить программу он это сможет сделать и по другому)

Re[3]: Возврат std::string из функции

От: Аноним
Дата: 29.12.06 11:51
Оценка:

Здравствуйте, demi, Вы писали:

D>Здравствуйте, Аноним, Вы писали:

А>>Здравствуйте, Аноним, Вы писали:

А>>>Всех с наступяющими праздниками.
D>Присоедиянюсь!

D>Разрешите подытожить:
D> -Корректно. Видимо сделано для устранения копирующего конструктора.
D> -Будут проблемы с многопоточностью. Вернуть string вместо string& — заморочек не будет.
D> -Возможны проблемы, если кто-то специально или случайно поменяет это строку там где этого не ожидается (писали выше).

D>Лично я бы так делать в 95% случаев не стал. Но есть 5%

Честно говоря не совсем понимаю какие могут быть проблемы с многопоточностью и с измененем строки.
1) При вызове:
std::string st = GetMyStr();
в стеке создается объект st и в него копируется строка ссылка на которую передаётся функцией GetMyStr.
Если после этого строку в GetMyStr изменить объект st этого уже не почуствует (у него уже есть копия).

Указанные Вами проблемы могут быть только при таком использовании:
std::string& st = GetMyStr();
или
std::string* st = &GetMyStr();

2) Вполне логично запретить изменение строки stVar вне функции GetMyStr
для этого её надо объявить так:
const std::string& GetMyStr();

Re[4]: Возврат std::string из функции

От: Аноним
Дата: 29.12.06 12:30
Оценка: 2 (1)

Инициализация статической переменной в функции (вызов конструктора статической std:;string) происходит при первом вызове функции. C++ не гарантирует thread-safety сего действа. Так что если два потока одновременно вызовут функцию могут получится неприятные вещи. btw новые компилеры имеют спец опцию для thread-safe static'ов.

Re[5]: Возврат std::string из функции

От: Аноним
Дата: 29.12.06 13:29
Оценка:

Здравствуйте, Аноним, Вы писали:

А>Инициализация статической переменной в функции (вызов конструктора статической std:;string) происходит при первом вызове функции. C++ не гарантирует thread-safety сего действа. Так что если два потока одновременно вызовут функцию могут получится неприятные вещи. btw новые компилеры имеют спец опцию для thread-safe static'ов.

Да это так.
Как Вы думаете, спасёт в данном случае что-то вроде:

const std::string GetMyStr()
static std::string* pVar;
lock();
static std::string stVar = "bla-bla-bla";
pVar = &stVar;

. каие-то операции над stVar;

А в случае если stVar никогда не меняется следует вообще написать:
const char* GetMyStr()
return "bla-bla-bla";
>

Re[3]: Возврат std::string из функции

От: Аноним
Дата: 30.12.06 11:01
Оценка:

Т.е. я как понял. Имея следующую функцию:

const std::string &CXxxDlg::GetMyStr(int nIdx) < static std::string stVar; switch(nIdx) < case 1: stVar = "aaaaaaaaa"; break; case2: stVar = "bbbbbbbbb"; break; default: stVar = "ccccccccc"; break; > return stVar; >

Совершенно корректно использовать её в _однопоточном_ приложении таким образом:

. std::string st1 = GetMyStr(1); . . std::string st2 = GetMyStr(999); . . std::string st3 = GetMyStr(2); . 

Правильно?
ЗЫ. Но приложение у меня не однопоточное, какие могут быть глюки. И что можно с ними сделать?

Re[2]: Возврат std::string из функции

От: IROV..
Дата: 30.12.06 12:46
Оценка: 1 (1)

Здравствуйте, remark, Вы писали:

R>Вполне нормально. Часто делают так, что бы избежать лишних копирований:

R>

R>class AAA R> < R>std::mapint, std::string> m; R> const std::string& find(int key) const R> < R>static const std::string empty; R> const std::mapint, std::string>::const_iterator i = m.find(key); R> if (m.end() != i) R> return *i; R> else R> return empty; R> > R>>; R>

Я для этого создал даже такую функцию..

я не волшебник, я только учусь!
Re[4]: Возврат std::string из функции

От: Аноним
Дата: 30.12.06 12:48
Оценка:

А>ЗЫ. Но приложение у меня не однопоточное, какие могут быть глюки. И что можно с ними сделать?
Обычные такие глюки. Мусор в строках, крэши, вобщем ниче необычного
Ваш код по глюкам в MT аналогичен следующему:

std::string stVar; const std::string &CXxxDlg::GetMyStr(int nIdx) < switch(nIdx) < case 1: stVar = "aaaaaaaaa"; break; case2: stVar = "bbbbbbbbb"; break; default: stVar = "ccccccccc"; break; >return stVar; >

Не получается вернуть строку. Как исправить?

mayton2019

Сергей Мокин , П3.8 регламента работы сервиса.
Тебе следует оформить код как следует. Выдачу ошибок стоит взять из лога сборки и тоже оформить правильно.

TosterModerator

Модератор @TosterModerator

Скриншоты кода запрещены.
Фрагменты кода надо размещать в виде текста и оборачивать тэгом code для корректного отображения. Удобно делать кнопкой
Это обязательно, см.п.3.8 Регламента.
Сюда же относится traceback, ввод и вывод в консоли и другая структурированная текстовая инфа.

Решения вопроса 1
Developer, ex-admin

1. Лучше бы вы использовали std::string, а не нативные ("сырые") строки.
2. Нативные строки - это не строки в привычном для С++ смысле (и в смысле интерпретируемых ЯП). У них нет встроенных операций типа конкатенации, выделения подстрок и т.п. Все это реализуется функциями в стиле Си str*
3. Если вы хотите вернуть сырую строку, то надо:
3.1. Массив под строку выделять в динамической памяти (или передавать его как параметр в функцию и его заполнять). Сейчас у вас автоматический массив, а он исчезнет, как только отработает оператор return и строка по факту не вернется (хотя вернется указатель, но он будет указывать в место на стеке, в котором уже нет вашей строки).
3.2. Возвращать char* . Сейчас тип возвращаемого значения в вашей функции char - а это один символ, а не строка.
4. Размер строки явно будет больше, чем size байт. На сколько больше - нельзя сказать заранее. Поэтому обычно выделяют достаточно большой буфер с запасом, чтоб покрыть все возможные варианты и при добавлении в буфер очередной подстроки контролируют размер буфера - чтоб оставалось место для очередной добавляемого куска и завершающего нулевого символа. Строка может быть равна size только в случае, если все числа в массиве будут состоять из одной десятичной цифры. Да и в этом случае требуется дополнительный байт на нулевой символ. Так что минимальный размер буфера должен быть size+1, реально он должен быть еще больше.

Ответ написан более года назад
Комментировать
Нравится 5 Комментировать
Ответы на вопрос 0
Ваш ответ на вопрос

Войдите, чтобы написать ответ

cpp

  • C++

Как передать в аргумент функцию, и выполнить её, передаваю в неё параметры?

  • 1 подписчик
  • 14 часов назад
  • 95 просмотров

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *