Почему мой код, включающий «строку», дает сбой, когда я помещаю его в функцию?

Я пытаюсь запустить простую программу на C++, которая в основном подсчитывает количество символов, используя функцию length() из библиотеки <string> C++.

Вот моя пользовательская функция:

#include <iostream>
#include <string>
using namespace std;

string TrimTextFunction() {
    string Text = "Hello I am your program!";

    cout << "String size is: " << Text.length();

    return 0; 
} 

Затем я просто запускаю эту пользовательскую функцию внутри main() через отладчик в Visual Studio:

int main()
{
    cout << TrimTextFunction(); 
}

В конце концов я получаю этот код ошибки:

Исключение, возникающее по адресу 0x00007FFE67837A41 (ucrtbased.dll)

Затем он перенаправляет меня во внутренний файл под названием xstring, показывающий саму ошибку.

Без отладчика код возвращает нужное мне значение.

Но когда я запускаю тот же код внутри main() с помощью того же отладчика (или без него), ошибок не возникает.

#include <iostream>
#include <string>
using namespace std; 


int main()
{
    string Text = "Hello I am your program!";

    cout << "String size is: " << Text.length();
}

Кажется, мне что-то не хватает в пользовательских функциях, особенно когда я что-то отлаживаю.

Почему функция main() позволяет мне получить нужный мне результат без ошибок, а пользовательская функция — нет?

Я использовал пользовательскую функцию, и мне нужно ожидать результата string, который возвращает длину переменной string, равную 24.

вы путаете вывод чего-либо на экран с возвратом чего-либо из функции. Это совершенно отдельные понятия.

463035818_is_not_an_ai 28.06.2024 15:11

Я отредактировал заголовок «постфактум». В нем содержится подсказка об ответе. Я надеюсь, что это никого не смущает.

anatolyg 28.06.2024 15:15

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

drescherjm 28.06.2024 15:19
Хорошая книга по C++
user12002570 29.06.2024 04:29
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
4
116
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ваша функция определяется как

string TrimTextFunction() {
    string Text = "Hello I am your program!";

    cout << "String size is: " << Text.length();

    return 0; 
} 

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

std::string(const char* s, const Allocator& alloc = Allocator())

Создает строку с содержимым, инициализированным копией символьной строки с нулевым завершением, на которую указывает s. Длина строки определяется первым нулевым символом. Поведение не определено, если [s, s + Traits::length(s)) не является допустимым диапазоном (например, если s — нулевой указатель). Этот конструктор не используется для вывода аргументов шаблона класса, если выводимый тип распределителя не соответствует требованиям распределителя.

Обратите внимание, что начиная с C++23 этот конструктор объявлен удаленным, поэтому он даже не компилируется.

std::string(std::nullptr_t) = delete;

Если вы просто хотите, чтобы ваша вспомогательная функция выводила данные на стандартный вывод, ей не нужно ничего возвращать, поэтому тип возвращаемого значения будет void, и вы можете опустить оператор return.

void TrimTextFunction() {
  string Text = "Hello I am your program!";

  cout << "String size is: " << Text.length();
} 

int main() {
  TrimTextFunction(); 
}
Ответ принят как подходящий

Давайте упростим пример. Версия со всем кодом в основном

#include <iostream>

int main() {
    std::cout << 42;
}

Вы хотите поместить 42 внутри функции. Функция должна вернуть это значение. Это было бы:

 #include <iostream>

 int foo() { return 42; }

 int main() {
     std::cout << foo();
 }

Но вместо этого вы сделали что-то вроде этого:

 #include <iostream>

 int foo() { 
     std::cout << 42;
     return 0;
 }

 int main() {
     std::cout << foo();
 }

Вам необходимо решить: является ли функция выводом значения на экран. Или функция возвращает значение, чтобы main мог его распечатать. Вы также можете сделать и то, и другое: функцию распечатать и позволить main распечатать. Однако ваш код находится где-то посередине.

Здесь

string TrimTextFunction() {
    string Text = "Hello I am your program!";

    cout << "String size is: " << Text.length();

    return 0; 
} 


int main()
{
    cout << TrimTextFunction(); 
}

Вы позволяете TimeTextFunction распечатать результат и вернуть какой-то несвязанный 0. К сожалению, std::string имеет конструктор, который можно вызвать с литералом 0, но при этом он вызывает неопределенное поведение, поскольку ожидает указатель на строку, завершающуюся нулем, а 0 преобразуется в nullptr.

main с другой стороны, похоже, что функция возвращает restul для печати, она использует возвращенный результат для его печати.

Решение, как упоминалось выше, состоит в том, чтобы не путать печать на экране с возвратом из функции. Решите, должна ли функция или main или оба печатать его, и когда вы объявляете функцию возвращающей std::string, убедитесь, что она возвращает правильный std::string (я полагаю, вы действительно хотите вернуть size_t, длину строки).

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

Single96 28.06.2024 15:36

Другие вопросы по теме