使用std::async替换字符串

inplace string reverse using std::async

本文关键字:字符串 替换 async 使用 std      更新时间:2023-10-16

我一直在尝试使用std::async(或std::thread)在原地反转字符串,但未能找到成功的算法。

void reverse(char* x, char* y)
{
    while (x < y)
    {
        char temp = *x;
        *x = *y;
        *y = temp;
        x++;
        y--;
    }
}
int main(int argc, char** argv)
{
    int numthreads = 2;
    char input[] = "abcdef";
    size_t size = strlen(input);
    size_t substrsize = 0;
    substrsize = size / numthreads;
    char* end = &input[strlen(input) - 1];
    char* begin = &(input[size-substrsize]);
    for (int i = 0; i < numthreads; i++)
    {
        std::async(std::launch::async, reverse, begin, end);
        end = begin -1; 
        begin = begin-substrsize;
    }
    cout << input << endl;    
    return 0;
}

为简单起见,我假设输入可以分成大小相等的子字符串(即;Size % numthreads假定为0)

然而,在上面,我得到的输出是:

cbafed

我理解这个输出,因为abc和def颠倒了位置。但是,正确的输出应该是fedcba

是否有可能扩展此代码以实现所需的输出?我试图将返回的未来存储在一个向量中(通过移动),然后调用它,但它没有帮助(可能是因为函数返回void)

请给出一些提示或建议,使其正确工作。很多谢谢!

您的算法将源字符串划分为两个子字符串,其中第一个是"def"。你的"反向"算法将"d"answers"f"交换,将指针转换为指向"e"的指针,并将"e"与自身交换。

结果是两个反向子字符串:

abc  def

cba  fed

你需要改变你的反向算法接受3个输入:

void reverse(char* begin, const char* const end, char* back) {
    while (begin != end) {
        std::swap(*(begin++), *(--back));
    }
}

然后你需要用字符串的子范围来调用它:

size_t subtrlen = 2;
reverse(input + 0, input + substrlen, input + sizeof(input) - 1);
reverse(input + substrlen, input + 3, input + sizeof(input) - 1 - substrlen);
演示:

#include <iostream>
#include <string.h>
void reverse(char* begin, const char* const end, char* back) {
    while (begin != end) {
        std::swap(*(begin++), *(--back));
    }
}
int main(int argc, char** argv)
{
    char input[] = "abcdef";
    size_t len = strlen(input);
    size_t substrlen = 2;
    std::cout << input << std::endl;    
    reverse(input, input + substrlen, input + len);
    reverse(input + substrlen, input + substrlen, input + len - substrlen);
    std::cout << input << std::endl;
    return 0;
}
http://ideone.com/gGjB9D

如果我没有错,你正试图以多线程的方式逆转字符串。所以你需要一个在多线程环境下执行的算法。

我可以为你提出一个简单的解决办法。

算法(函数)多线程

void reverse_str_mt(char* str,
                const size_t len,
                const size_t id_thread,
                const size_t max_num_threads) {
  // Some assertion on input parameters
  assert(str != nullptr);
  assert(max_num_threads != 0);
  // In case the num of threads is greater than the len of the string
  if (id_thread > len) {
    assert(max_num_threads > len);
    return;
  }
  // Swap operation
  for (size_t i = id_thread; i <= len / 2; i += max_num_threads) {
    std::swap(str[i], str[len - i - 1]);
  }
}

你可以像这样操作一个字符串:

int main(int argc, char *argv[]) {
  static constexpr size_t NUM_THREADS = 10;
  char str[] = "123456";
  const auto len = strlen(str);
  std::vector<std::thread> threads;
  for (size_t i = 0; i < NUM_THREADS; ++i) {
    threads.emplace_back(reverse_str_mt, str, len , i, NUM_THREADS);
  }
  // Join threads
  for (auto& t : threads) {
    t.join();
  }
  // Print the result
  std::cout << str << std::endl;
  return 0;
}

为了完整起见,你应该包括的头文件是:

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <thread>
#include <cstring>
#include <cassert>