【问题标题】:How to use multidimensional char or string arrays in a loop如何在循环中使用多维字符或字符串数​​组
【发布时间】:2012-01-09 17:08:35
【问题描述】:

我对 C++ 很陌生,只是不知道如何使用任何多维数组。我想做这样的事情:

input number of product: number; //the products' name can be 7 with NULL char. (max 6)
char arr[number][7];

这行得通。但是当我想在 for loop(i) 中这样做时:

cin>>arr[i][7];

我不知道编译器到底在做什么?

我只是想要那个:

arr[0][7]=apple;
arr[1][7]=orange;

那么请问我该怎么做呢?

【问题讨论】:

  • 由于您是新手,因此您可以从一开始就学习良好的做法 - 为此请使用 std::vector<std::string>
  • 您是否有经过深思熟虑的真正理由不使用字符串向量?如果不是,则使用字符串向量。
  • @KerrekSB:我有一种直觉,网名WhoCares的人不会有现成的正版,原因(当然不是她is new about c++ ... something like that

标签: c++ arrays string char multidimensional-array


【解决方案1】:
#include <string>
#include <vector>

既然每个人都在推荐它,我想我会为你勾勒出选项。

请注意,如果您提供了一个简短的工作示例代码 sn-p(翻译代码 1:1 是比您可能认识的“思考”示例更有效)

给你:

std::vector<std::string> strings

strings.push_back("apple");    
strings.push_back("banana");

// or
std::string s;

std::cin >> s; // a word
strings.push_back(s);

// or
std::getline(std::cin, s); // a whole line
strings.push_back(s);

// or:
// add #include <iterator>
// add #include <algorithm>

std::copy(std::istream_iterator<std::string>(std::cin),
     std::istream_iterator<std::string>(),
     std::back_inserter(strings));

也可以直接寻址:

std::vector<std::string> strings(10); // 10 empty strings

strings[7] = "seventh";

编辑以响应 cmets:

const char* eighth = "eighth";

if (strings[7] != eighth)
{  
      // not equal
}

// If you really **must** (read, no you don't) you can get a const char* for the string:

const char* sz = strings[7].c_str(); // warning: 
         // invalidated when `strings[7]` is modified/destructed

【讨论】:

  • 嘿。我不能对这种类型的数据使用 strcmp 吗?我试图将其与链表中的数据进行比较: products->name 。并且它错误:无法将参数 '1' 的参数 '1' 转换为 'std::basic_string, std::allocator >' 到 'const char*' 到 'int strcmp(const char* , const char*)'|
  • @WhoCares:我用更多 C++ 风格的方式更新了答案,以使用 std::string 与 C api 互操作的方式。但是,str* 系列函数在 C++ 风格中是 冗余not 的。所以,不要用它。
【解决方案2】:

除非您有真正的原因(您不能对我们隐瞒),否则请按照 Björn 的说法制作并使用字符串向量。您甚至可以取消对总大小的初始请求:

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

std::vector<std::string> fruits;
std::string line;

while (std::getline(std::cin, line))
{
  fruits.push_back(line);
}

让我们测试一下:

std::cout << "You entered the following items:\n";
for (auto const & f : fruits) std::cout << "* " << f << "\n";

【讨论】:

    【解决方案3】:

    因为arr[i][7]char,实际上是在最后一个元素之后,这意味着您可能会遇到内存访问错误。

    你想做的也许是cin&gt;&gt;arr[i];

    然而,这不是一个好主意,因为您无法控制从输入中读取多少个字符,这很容易导致内存溢出。

    按照其他人的建议,最简单的方法是使用std::vector&lt;std::string&gt;

    【讨论】:

    • 嗯。我错过了第一个维度是硬编码的事实(不是char*[]
    • 它确实有效。当我输入“apple”并在手表屏幕上观看变量时,就像这样: arr[i]='a' :\
    • cin&gt;&gt;arr[i] 是一个非常糟糕的主意 - 输入过多会导致写入超出数组末尾。最好使用std::vector&lt;std::string&gt;,并安全地写入每个字符串。
    • @WhoCares 它适用于我的简单程序std::cin&gt;&gt;arr[0];std::cout&lt;&lt;arr[0];。我不知道您使用的是哪个 IDE,但如果它显示'a',可能它只显示第一个字符。一个字符串可能会包含在"" 中。
    【解决方案4】:
    strcpy(&arr[0], "apple");
    strcpy(&arr[1], "orange");
    

    但对于 C++,最好使用 std::vector&lt;std::string&gt; 来表示字符串数组

    【讨论】:

    • 这可能有效,但用户将从键盘输入产品。那么我应该使用什么类型的变量?例如:char pr;辛>>公关; strcpy(&arr[0],pr);有效吗?
    • 这行不通。一次只能获得一个charstrcpy 是错误的。
    • 当我有空时,我会选择 std::vector&lt;std::string&gt; 而不是 char[][]
    • 否 :) 在开始时使用 std::string,很简单。但是如果仍然想使用 char 数组,你应该定义数组,比如 char input[7],并使用它,但是如果有人输入长度超过 6 个字符的字符串,它会破坏你的记忆,你会得到分段错误
    • 说 &arr[0] 实际上是一个编译错误,至少对于 g++ 来说是这样。说 arr[0] 或 &arr[0][0]。
    【解决方案5】:

    你有一个二维数组char

    char arr[number][7];
    

    然后尝试为它们分配一个字符串(char* 或 const char*),但这是行不通的。你可以在这里做的是分配一个字符,例如:

    arr[0][1] = 'a';
    

    如果可以的话,我会推荐使用std::vectorstd::string,这会让事情变得更清晰。在你的情况下,你可以做

    cin>>arr[i];
    

    但我不推荐它,因为您最多只能存储 6 个字符 char* 字符串(加上空终止符)。你也可以有一个 char* 数组

    char* arr[number];
    

    然后动态分配内存来存储字符串。

    【讨论】:

      【解决方案6】:

      使用 std::vector 和 std::string 通常会在你理解它们之后让你头疼。由于您是 C++ 的新手,因此了解二维数组到底发生了什么可能会很有用。

      当你说

      char array[N][M];
      

      由于 N 和 M 是常量,而不是变量,您是在告诉编译器分配 char 类型的 N*M 项。将有一块内存专用于该大小为 N*M*sizeof(char) 的数组。 (您可以声明任何内容的数组,而不仅仅是 char。由于 sizeof(char) 为 1,内存将是 N*M 字节长。)如果您查看原始内存,内存中的第一个字节将是数组 [ 0][0] 是。第二个字节将是 array[0][1] 所在的位置,依此类推,对于 M 字节。然后你会看到数组[1][0]。这称为行优先顺序。

      正如@jbat100 提到的,当您说 array[i][j] 时,您指的是单个字符。当您说数组 [i] 时,您指的是数组中第 i 行的地址。实际上没有指针存储在内存中,但是当你说 array[i] 时,编译器知道你的意思是你想要数组中第 i 行的地址:

      char* row_i = array[i];
      

      现在如果 i>0,则 row_i 指向专用于数组的内存块中间的某个位置。这会做同样的事情:

      char* row_i = &array[i][0];
      

      如果你有一个字符串 "orange" 并且你知道它的长度小于 M,你可以将它存储在数组的给定行中,如下所示:

      strcpy(array[i], "orange"); // or
      array[i][0] = 'o'; array[i][1] = 'a'; ... array[i][6] = 0;
      

      或者你可以说 row_i 而不是 array[i]。这会将 7 个字节复制到 row_i 位置的数组中。 strcpy() 还复制一个额外的字节,即 0,这是在 C 和 C++ 中终止字符串的约定。所以这7个字节是6个字节,'o'、'r'、'a'、'n'、'g'和'e',加上一个0字节。现在 strcmp(row_i, "orange") == 0。

      请注意,如果您的字符串比 M 长,则 strcpy 和简单的字符分配不会(可能)产生编译错误,但您最终会将部分字符串复制到下一行。

      在一本优秀的 C/C++ 书籍中了解指针和数组。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多