【问题标题】:Assign string to column of char array将字符串分配给 char 数组的列
【发布时间】:2013-08-04 15:57:04
【问题描述】:

我正在尝试为 C++ 中的多维 char 数组的列分配一个类似“hello”的字符串。例如,当它完成时,二维数组的第一列应该从上到下变为“hello”。

我正在寻找一个不使用 for 循环的简单解决方案,例如使用 strcpy()。这可能吗?

【问题讨论】:

  • 请包含您尝试过的代码、您得到的结果以及您期望的结果。
  • 您最大的问题将是 C++ 是行优先顺序,而 strcpy 函数将在一行上运行。
  • 它似乎是例如 a[10][10]。 a[0] 是一个可以发送到 strcpy 的指针。
  • AFAIK,没有标准库函数可以做到这一点。您想要的是库中未提供的具有 write-stride 的副本。但是对于一个非常短的for 循环来说,这绝对是微不足道的。为什么不想使用循环?
  • @yzt 我认为他真的不想使用多维数组,因为为它们编写循环可能很棘手。我的回答显示了一点点 C++11 如何可以大大减少这个问题。 (_我仍然建议不要使用多维数组,但这无关紧要)

标签: c++ string multidimensional-array char


【解决方案1】:

我强烈建议不要使用 C++ 中的原始多维数组 - 它们容易出错且不灵活。考虑 Boost MultiArray。

也就是说,您始终可以通过编写辅助函数来“隐藏”复杂性。这是一个相当通用的版本,适用于任何大小/元素类型的二维数组:

template<typename T, size_t N, size_t M>
   void setColumn(T(&arr)[N][M], size_t col, std::string const& val)
{
    assert(col>=0 && col <M);

    for (auto& row : arr)
        row[col] = val;
}

注意它是怎么回事

  • 通过引用获取数组,因此模板参数推导可用于“感知”维度边界(N,M)
  • 它断言列索引实际上是有效的(奖励功能)
  • 它使用基于范围的for,这实际上非常简洁,并且肯定有助于隐藏在 C++ 中使用二维数组会暴露的所有混乱你去。

如何使用?

std::string arr[][7] = {
    { "0", "1", "2", "3", "4", "5", "6" },
    { "0", "1", "2", "3", "4", "5", "6" },
    { "0", "1", "2", "3", "4", "5", "6" },
    { "0", "1", "2", "3", "4", "5", "6" },
    { "0", "1", "2", "3", "4", "5", "6" },
    { "0", "1", "2", "3", "4", "5", "6" },
};

// straightforward:
setColumn(arr, 0, "hello");

或者,如果您不想“说出”哪个数组,请使用 lambda:

// to make it even more concise
auto setColumn = [&](int c, std::string const& val) mutable { ::setColumn(arr, c, val); };

setColumn(3, "world");

现场演示是Here on Coliru,它会打印出来

hello;1;2;world;4;5;6;
hello;1;2;world;4;5;6;
hello;1;2;world;4;5;6;
hello;1;2;world;4;5;6;
hello;1;2;world;4;5;6;
hello;1;2;world;4;5;6;

使用简单的代码

// dump it for demo purposes
for (auto& row : arr)
{
    std::copy(begin(row), end(row), std::ostream_iterator<std::string>(std::cout, ";"));
    std::cout << "\n";
}

【讨论】:

  • 非常好,但我 认为 OP 希望给定的列包含 "h", "e", "l", "l", "o" 而不是 "hello" 六次。
  • @juanchopanza“二维数组的第一列应该从上到下变成“你好””——我不完全确定是什么让你断定你的解释更有可能:|我同意两者都是可能的
【解决方案2】:

AFAIK 无法使用标准库函数来做到这一点。

然而,用一个简单的循环来完成是一件容易的事:

std::size_t col = 0;
std::string s{"hello"};
for (std::size_t i = 0; i != s.size(); ++i) {
    arr[i][col] = s[i];
}

注意,如果s.size() 大于arr 的行尺寸,这不会进行边界检查。

现场示例: http://ideone.com/K63uDQ

【讨论】:

    【解决方案3】:

    使用 strcpy():

    #include <string.h>
    #include <iostream>
    using namespace std;
    
    int main()
    {    
            const int rows = 10; 
            const int cols = 10; 
            const int wordlen = 255;
    
            char a[rows][cols][wordlen];
            for (int ix = 0; ix < rows ; ++ix)
                strcpy(a[ix][0] , "hello");
            for (int ix = 0; ix < rows ; ++ix)
                cout << a[ix][0] << endl;
    }
    

    使用 for_each() 函数:

    #include<algorithm>
    #include <iostream>
    using namespace std;
    
    string* val(string *s) 
    {
        s[0] = "hello";
        return s;
    }
    
    int main()
    {    
            const int rows = 8;
            const int cols = 8;
    
            string a[rows][cols];
            for (int ix = 0; ix < rows; ++ix)
                for (int jx = 0; jx < cols; ++jx)
                    a[ix][jx] = "something";
            for_each(a,a+rows,val);
            for (int ix = 0; ix < rows; ++ix)
                for (int jx = 0; jx < cols; ++jx)
                    cout << "a[" << ix << "][" << jx << "] = " << a[ix][jx] << endl;
    }
    

    【讨论】:

    • 非常感谢,但我仍然在寻找更简单的解决方案。使用地址和指针而不使用 for 循环。但仍然感谢
    猜你喜欢
    • 2015-06-25
    • 1970-01-01
    • 1970-01-01
    • 2011-02-07
    • 1970-01-01
    • 2014-06-08
    • 2012-10-16
    • 2012-05-03
    • 1970-01-01
    相关资源
    最近更新 更多