为什么我的字符串为空,而我可以访问单个字符?

huangapple go评论59阅读模式
英文:

Why is my string null while if I can access an individual char?

问题

以下是翻译好的内容:

我是C++的新手,最近通过u-demy讲座学习了指针和引用。在讲座之后,我正在解决一个使用单独函数来反转字符串的问题。我编写了一段代码,但出现了一个问题,就是我可以使用[]符号来访问单个字符(比如reverse[0]等于'!'),但当我打印整个字符串时,我得到一个空字符串?是什么原因导致了这个问题?

谢谢您提前的时间!

这里是我粘贴的代码:

#include <iostream>
// using namespace std;

std::string reverse_string(const std::string &str) {
    std::string reversed;

    size_t size {str.length()};
    for(int i{}; i < size/2; i++) {
        reversed[i] = str[(size-1)-i];
        reversed[(size-1)-i] = str[i];
    }
    
    return reversed;
}

int main() {
    // 在这里编写C++代码
    std::string input = "Hello, World!";
    std::string reversed = reverse_string(input);
    std::cout << reversed << std::endl;  //我得到了空字符串,但是
    std::cout << reversed[0] << std::endl //这里我得到了一个'!'
    return 0;
}
英文:

I am new to C++ and I recently learned pointers and references through u-demy lectures. After lectures, I am solving a problem to reverse a string using a separate function. I came up with a code but for some reason, I can access an individual char using [] notation (like reverse[0] is equal to !) but when I print the whole string I get an empty string? What is causing this issue?

Thank you for your time in advance!

Here I have pasted my code:

#include &lt;iostream&gt;
// using namespace std;

std::string reverse_string(const std::string &amp;str) {
    std::string reversed;

    size_t size {str.length()};
    for(int i{}; i &lt; size/2; i++) {
        reversed[i] = str[(size-1)-i];
        reversed[(size-1)-i] = str[i];
    }
    
    return reversed;
}

int main() {
    // Write C++ code here
    std::string input = &quot;Hello, World!&quot;;
    std::string reversed = reverse_string(input);
    std::cout &lt;&lt; reversed &lt;&lt; std::endl;  //I get nothing, BUT
    std::cout &lt;&lt; reversed[0] &lt;&lt; std::endl //here I do get a &#39;!&#39;
    return 0;
}

答案1

得分: 5

问题的根本在于在函数reverse_string()中从不为std::string reversed保留空间。这会创建并返回一个空的std::string

operator[] 不执行边界检查。这是未定义行为的第一个实例。

可以将方括号中的数字视为内存偏移量。如果你不打开它们,就不会检查偏移量是否仍在你的字符串所拥有的内存块内。

main()中看到的是一个次要问题。reverse是一个空字符串(因为这是reverse_string()始终返回的值,见上文)。而reverse[0](另一个超出边界的访问,因此是未定义行为)是""!",因为你错误地将其设置为这个值。

要解决问题,可以使用str.size()的容量来初始化reversed,或者简单地将其初始化为str的副本。

为了防止此类问题,打开所有编译器警告并进行调试构建。

英文:

The original issue is that no space is ever reserved for std::string reversed in function reverse_string(). This creates and returns an empty std::string.

The operator[] performs no bounds checking. That's your first instance of undefined behavior.

Think of the number in brackets as a memory offset. If you don't switch them on, there are no checks to see if the offset is still within the chunk of memory owned by your string.

What we see in main() is a secondary problem. reverse is an empty string (because that's what reverse_string() always returns, see above). And reverse[0] (another out-of-bounds access and thus undefined behavior) is "!" because you incorrectly set it to this value.

To fix the problem, initialize reversed with a capacity of str.size() or simply as a copy of str.

To prevent such problems, turn on all compiler warnings and do a debug build.

答案2

得分: 1

我在运行您的代码时遇到以下错误(在添加字符串头之后):

usr/src/debug/gcc/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:1259: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::reference std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator[](size_type) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; reference = char&; size_type = long unsigned int]: Assertion '__pos <= size()' failed.
Aborted (core dumped)

通常,您会收到“分段错误”(Segmentation fault),但正如您从错误消息中所看到的那样,断言“__pos <= size()”失败了。因此,程序被中止。

无效的内存访问是“分段错误”的常见原因。这是未定义的行为。

具体来说,在这种情况下,索引不在字符串对象的范围内。

请将[]运算符替换为.at(),它会在索引超出范围时引发异常。[]运算符不会引发异常。

使用调试器(推荐)或手动调试程序,找出可能发生这种情况的地方。

英文:

I get the following error when running your code (after adding string header)

usr/src/debug/gcc/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:1259: std::__cxx11::basic_string&lt;_CharT, _Traits, _Alloc&gt;::reference std::__cxx11::basic_string&lt;_CharT, _Traits, _Alloc&gt;::operator[](size_type) [with _CharT = char; _Traits = std::char_traits&lt;char&gt;; _Alloc = std::allocator&lt;char&gt;; reference = char&amp;; size_type = long unsigned int]: Assertion &#39;__pos &lt;= size()&#39; failed.
Aborted (core dumped)

Usually you'd get Segmentation fault, but here as you can see from the error message,
Assertion &#39;__pos &lt;= size()&#39; failed,
some assertion failed. Thus, the program was aborted.

Invalid memory access is a common cause of Segmentation fault. It is undefined behavior.

Specifically in this case, the index is not within the range of the string object.

Replace the [] operator with .at(), which throws when the index is out of range. [] operator does not.

Debug the program either using a debugger (recommended) or manually to find out where this might be happening.

huangapple
  • 本文由 发表于 2023年6月1日 16:54:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/76380213.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定