【问题标题】:Printing string array with for-loop doesn't function properly (C++)使用 for 循环打印字符串数组无法正常工作(C++)
【发布时间】:2019-09-11 17:12:00
【问题描述】:

我是 C++ 的新手,我只是想尝试一些东西,在这种情况下特别是数组。我想将一个字符串数组打印到控制台,但它要么以二进制形式打印随机的东西,要么告诉我我遇到了分段错误,要么什么也不做。

最初的程序有点复杂,但我尽量减少额外的东西,以便我能看到问题所在,但没有成功。

#include <iostream>
#include <string>

using namespace std;

int main() {

    string stArr[] = {" 1 | ","_"," | ","_"," | ","_"," | "};
    for(int i = 0; i < sizeof(stArr); i++) {
           cout << stArr[i];
    }

    return 0;
}

现在,预期的输出显然是数组。但我通常得到的是这样的:UH��AWAVAUATSH��(L�%�!I���#�E�K��H��v!H��H��%H�=�!” {�!I��H���I�����H�=_!�Q�!���t�H�D��A��D����;u��u�u ����H�e�E1�H� [等等]

提前致谢!

【问题讨论】:

  • 你知道sizeof(stArr)返回什么吗?如果没有,请检查一下。
  • 这就是为什么在使用 C++ 时应该使用 std::vectorstd::array 和适当的枚举器。 C 风格的 for 循环充满了危险。

标签: c++ arrays for-loop sizeof


【解决方案1】:

sizeof(stArr) 为您提供整个数组的总字节大小。它不会为您提供您正在寻找的元素计数。因此,您的循环超出了数组的范围,这就是您在输出中得到垃圾的原因。

要得到数组的元素个数,需要用数组的字节大小除以数组中单个元素的大小,例如:

#include <iostream>
#include <string>

int main() {

    std::string stArr[] = {" 1 | ","_"," | ","_"," | ","_"," | "};
    int count = sizeof(stArr) / sizeof(stArr[0]);

    for(int i = 0; i < count; ++i) {
        std::cout << stArr[i];
    }

    return 0;
}

话虽如此,如果您使用的是 C++17 或更高版本的编译器,则可以使用 std::size() 获取静态数组的元素计数:

#include <iostream>
#include <string>
#include <iterator>

int main() {

    std::string stArr[] = {" 1 | ","_"," | ","_"," | ","_"," | "};
    size_t count = std::size(stArr);

    for(int i = 0; i < count; ++i) {
        std::cout << stArr[i];
    }

    return 0;
}

或者,如果您使用的是 C++11 编译器,则可以改用 std::extent

#include <iostream>
#include <string>
#include <type_traits>

int main() {

    std::string stArr[] = {" 1 | ","_"," | ","_"," | ","_"," | "};
    size_t count = std::extent<decltype(stArr)>::value;

    for(int i = 0; i < count; ++i) {
        std::cout << stArr[i];
    }

    return 0;
}

也就是说,如果您使用的是 C++11 或更高版本的编译器,请考虑改用 std::array

#include <iostream>
#include <string>
#include <array>

int main() {

    std::array<std::string, 7> stArr = {" 1 | ", "_", " | ", "_", " | ", "_", " | "};
    // or: in C++17 and later:
    // std::array stArr{" 1 | ", "_", " | ", "_", " | ", "_", " | "};

    std::size_t count = stArr.size();

    for(size_t i = 0; i < count; ++i) {
        std::cout << stArr[i];
    }

    return 0;
}

或者,您也可以使用ranged-based for loop

#include <iostream>
#include <string>

int main() {

    std::string stArr[] = {" 1 | ", "_", " | ", "_", " | ", "_", " | "};
    // or std::array...

    for(auto &s : stArr) {
        std::cout << stArr[i];
    }

    return 0;
}

否则,如果您不使用 C++11 或更高版本的编译器,请考虑使用 std::vector

#include <iostream>
#include <string>
#include <vector>

int main() {

    std::vector<std::string> stArr;
    stArr.push_back(" 1 | ");
    stArr.push_back("_");
    stArr.push_back(" | ");
    stArr.push_back("_");
    stArr.push_back(" | ");
    stArr.push_back("_");
    stArr.push_back(" | ");

    std::size_t count = stArr.size();

    for(size_t i = 0; i < count; ++i) {
        std::cout << stArr[i];
    }

    return 0;
}

【讨论】:

    【解决方案2】:

    for循环中的这个条件

    i < sizeof(stArr)
    

    没有意义。它不提供数组中元素的数量。

    至少你得写

    i < sizeof(stArr) / sizeof( *stArr )
    

    例如,如果您有一个包含N 元素类型为T 的数组,则使用此公式计算数组的大小

    sizeof( array ) = N * sizeof( T )
    

    所以要获取数组中元素的数量,知道它的大小和你可以写的元素的大小

    N = sizeof( array ) / sizeof( T )
    

    但使用基于范围的 for 循环要简单得多。

    for ( const auto &s : stArr ) std::cout << s;
    

    如果您的编译器支持 C++ 17,那么您可以使用在标头 &lt;iterator&gt; 中声明的标准泛型函数 std::size。例如

    #include <iostream>
    #include <string>
    #include <iterator>
    
    using namespace std;
    
    int main() {
    
        string stArr[] = {" 1 | ","_"," | ","_"," | ","_"," | "};
        for ( size_t i = 0; i < size( stArr ); i++) {
               cout << stArr[i];
        }
    }
    

    否则你可以使用头文件&lt;type_traits&gt;中定义的结构std::extent如下方式

    #include <iostream>
    #include <string>
    #include <type_traits>
    
    using namespace std;
    
    int main() {
    
        string stArr[] = {" 1 | ","_"," | ","_"," | ","_"," | "};
        for ( size_t i = 0; i < extent<decltype( stArr )>::value; i++) {
               cout << stArr[i];
        }
    }
    

    【讨论】:

      【解决方案3】:

      检查,sizeof(strArray 的值是多少)。我打赌你假设它是 7(即数组中的字符串数)。

      剧透:嗯,肯定不是。 sizeof(strArray) 返回整个数组占用的内存量,即 7 个​​字符串。它是一个大于 7 的数字,因此在迭代期间,您会读取数组边界之外的内存。

      将其除以一个元素的大小(例如sizeof(strArray)/sizeof(string))得到您期望的大小。

      【讨论】:

      • 谢谢,成功了!不过我不完全理解: sizeof(string) 是否采用每个字符串的单独大小,或者它究竟是如何工作的?因为我不必指定要考虑的字符串。
      • @splashrt 检查sizeof(stArr[0])sizeof(stArr[1]) 等的结果是什么(即,sizeof 为数组中的连续字符串返回什么)。这些真的不同吗?将其与stArr[0].length()stArr[1].length() 等的结果进行比较。通常您可能会将sizeof(string) 视为存储有关字符串信息的事物的大小(以字节为单位),而不是字符串本身。跨度>
      猜你喜欢
      • 1970-01-01
      • 2023-03-20
      • 1970-01-01
      • 2014-02-17
      • 2017-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多