【问题标题】:C++: Get index of char element in arrayC ++:获取数组中char元素的索引
【发布时间】:2011-12-14 02:31:11
【问题描述】:

我需要获取数组中的字符数。

const char myarray[5] = {'0', 'a', 'e', 'f', 'c'}; // Create array of char
int number=0; // Create variable
number = getposition(myarray, 'f'); // Now number equals to 3
number = getposition(myarray, 'z'); // -1, because array doesn't have this char

我的任务很简单,因为数组没有重复字符(例如,它不能是这样的:{'a', '1', 'f', 'a'})。我该怎么做?

【问题讨论】:

  • 你的意思是“字符的索引”?
  • 你可以返回一个位置数组。
  • 是的。不是索引,而是一个索引:正如我所说,没有重复的字符。
  • memchr 是你的朋友——除非这是家庭作业——在这种情况下——你应该考虑一下......
  • 不,这是一种解码算法。我可以使用数百个 if 或用例进行构建,但我认为可能会有更有效的决策。

标签: c++ arrays char


【解决方案1】:

多一点 C++:

 #include <algorithm>

int getposition(const char *array, size_t size, char c)
{
     const char* end = array + size;
     const char* match = std::find(array, end, c);
     return (end == match)? -1 : (match-array);
}

更多 C++:

template <typename T, size_t N>
int getposition(const T (&array)[N], const T c)
{
     const T* match = std::find(array, array+N, c);
     return (array+N==match)? -1 : std::distance(array, match);
}

C++11/C++11 更新奖励

#include <algorithm>
#include <iterator>

template <typename Range, typename T>
size_t index_of(Range const& range, T const& c) {
    using std::begin;
    using std::end;

    auto b = begin(range), e = end(range);
    auto match = std::find(b, e, c);

    return (e==match)? -1 : std::distance(b, match);
}

奖励 C++17 更新

在这里,原始问题得到了std::string_view 的直接支持:

Live On Coliru

#include <string_view>
using namespace std::string_view_literals;

int main() {
    return "hello"sv.find('e');
}

【讨论】:

  • 第一个确实是 C++ 中唯一正确的答案。如果问题在 C 语言中,则响应为 memchr(另一张海报提到)。问题是经典的线性搜索,您无需重新发明轮子(除非这是练习的目标)。
  • 这里的第一个肯定是错误的,因为它使用strlen而不是size参数,而且我们不知道数组是否是字符串(示例中的那个是' t) 如果是,则是否应该搜索 0 终止符。但除此之外,它基本上是正确的。你可以有一个使用std::begin(array), std::end(array) 的“甚至更多的C++”版本,尽管这样它也不需要宣传捕获N 的模板推导技巧,因为它可以只接受一个模板参数Range。跨度>
  • @SteveJessop:呵呵。你能告诉我我是从 OP 中复制的吗...这就是我在没有好好阅读的情况下复制粘贴所应得的 :( 已修复。关于基于范围的版本,我考虑添加它(但我已经有 2 个选项,而且它原来速度在 SO 很重要)
  • 在第二个代码块中,没有定义end。但是,在第一个代码块中,它被定义了。我错过了什么吗?
  • @JamesLittle 哇。这么多年怎么没人注意到。我借此机会分别添加了内容丰富且更优雅的 c++11、c++14 和 c++17 版本!干杯
【解决方案2】:
#include <algorithm>

template <typename T, size_t size>
int getposition(T const (&array)[size], T const & c)
{
    T const * found = std::find(&array[0], &array[size], c);
    return found == &array[size] ? -1 : found - array;
}

【讨论】:

  • 非常好,但很神秘;)
  • 如果found - array 被替换为std::distance(array,found),我真的很想为此+1。
  • @xtofl:我看不出有什么意义——这个函数专门处理数组,而不是通用迭代器范围。
  • @MikeSeymour:我编辑了帖子:the type T was missing in the second parameter。希望你没事。
  • @Nawaz:不,不是;我已经回滚以删除重复的T
【解决方案3】:

您需要告诉getposition() 方法要在数组中搜索多少元素,并且在编译时初始化数组时,您可以使用sizeof 指令:

int number = getposition(myarray, sizeof(myarray), 'f');

...

int getposition(const char *array, size_t size, char c)
{
    for (size_t i = 0; i < size; i++)
    {
        if (array[i] == c)
            return (int)i;
    }
    return -1;
}

【讨论】:

  • 在一个函数中使用多个返回无助于维护和易读性。
  • @m0skit0:这是一个偏好问题。 IMO 将值保存在一个额外的 var 中并在您知道可以立即返回时退出循环也无济于事。
  • @m0skit0: 添加额外变量和break 语句也无济于事。
  • @m0skit0:您需要添加一个break(或更复杂的终止条件)和一个存储返回值的变量,以便遵循您的建议并避免提前返回.或者您有什么建议可以避免提前返回,并且设法比这更清晰?
  • 我碰巧同意单次返回的概念,但在像这样不考虑维护的琐碎函数中,考虑到函数的大小。我认为@m0skit0 并没有真正提供“证据”证明单个return 是王者——他的答案比它需要的复杂得多,维护将是一个真正的问题。
【解决方案4】:
int getposition(const char* a, int arr_size, char to_find)
{
    int pos = -1;

    for(int i = 0; i < arr_size; ++i)
    {
        if(a[i] == to_find)
        {
            pos = i;
            break;
        }
    }

    return pos;
}

【讨论】:

  • 甚至不会编译...这不是功能。请在发布之前确保您的答案;)
  • 更新了一些可以编译和工作的东西。坦率地说,我的第一个答案是垃圾。其他答案也比我聪明得多:-)
  • @m0skit0:你的答案也不会编译;你知道“玻璃屋里的人……”这句话吗?
【解决方案5】:

如果这真的是一个纯粹的解码练习 - 为什么不重新组织你的数组......然后查找是恒定时间 - 例如......

int lt[128]; // ignoring negative values..

memset(lt, -1, 128); // initialize all to -1

// set the ones you want mappings for..
lt['0'] = 0;
lt['a'] = 1;
lt['e'] = 2;
lt['f'] = 3;
lt['c'] = 4;

所以现在你的查找功能是:

int indexOf(char v) { return lt[v]; }

你很难在性能上击败它......

【讨论】:

    【解决方案6】:

    您还需要将数组大小传递给函数。

    int getposition(const char* array, size_t array_size, char value)
    {
        int ret = -1;
    
        int i = 0;
        bool found = false;
        while (i < array_size && !found)
        {
            found = (array[i++] == value);
        }
    
        if (found)
        {
            ret = i - 1;
        }
    
        return ret;
    }
    

    【讨论】:

    • :) 似乎我们都夸大了:第一次出现就行了。
    • 我将在第一次出现时返回;) while() 循环在第一次出现时结束。不要在没有真正理解代码的情况下投反对票;)顺便说一句,我没有对你投反对票,因为你的答案是有效的。我只是批评了表格:P
    • 抱歉 - 我阅读了 !found 条件。添加一个显式的return 会阻止这种情况:)。但我投了反对票,因为您编写了函数而不是使用标准库。
    • 奇怪的是,特洛伊木马没有得到你的任何反对意见。而且我不想添加额外的return,这就是重点;)
    • @m0skit0:你的回答有一些错误:输入数组应该是const char *。您不应该使用-1 初始化unsigned 类型(ret),而boolean 不是有效的C++ 关键字。这个问题是关于数组的大小,而不是如何教条地编程。
    猜你喜欢
    • 2023-03-24
    • 2018-11-14
    • 1970-01-01
    • 2017-10-14
    • 2014-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-15
    相关资源
    最近更新 更多