【问题标题】:C++ forbidding setting char* and char[] from const char*C++ 禁止从 const char* 设置 char* 和 char[]
【发布时间】:2011-10-07 06:37:00
【问题描述】:

这是代码。我不知道为什么它不承认它需要复制内存,而且我不能强迫它。

 string message="The quick brown fox jumped over the lazy dog.";

  vector<char*> words;

  while(message.length()>0){
    char wtf[message.substr(0,message.find(" ")).c_str().length()]=message.substr(0,message.find(" ")).c_str();
    words.push_back(wtf);
    message=message.substr(message.find(" ")+1);
  }

我看到有类似的线程,但没有。此外,C++ 不能那么容易地处理这似乎是一个缺点。

【问题讨论】:

  • 哇。你能解释一下你想要做什么,出了什么问题吗?如果您遇到编译器错误,为什么不发布呢?
  • 关于“C++ 无法轻松处理这个问题似乎是一个缺点”......确实,文本处理不是 C++ 的强项之一,但你是写的人用相同的参数调用find 三次的代码。 PEBCAK。
  • 对不起。错误会根据我尝试的解决方法而改变,但它总是归结为无法将 const char* 转换为 char* 就是这样。它是隐藏输入到它的消息的程序的一部分。
  • 你能多解释一下代码的实际目的或目标是什么吗?

标签: c++ char constants


【解决方案1】:

如何将文本分解为单词(简单的方法)

#include <string>
#include <sstream>
#include <vector>
#include <algorithm>
#include <iterator>

int main()
{
    std::string message="The quick brown fox jumped over the lazy dog.";

    std::vector<std::string>    words;

    std::stringstream   stream(message);                  // 1: Create a stream
    std::copy(std::istream_iterator<std::string>(stream), // 2: Copy words from the stream
              std::istream_iterator<std::string>(),
              std::back_inserter(words));                 //    into the back of the vector.
}

分解其工作原理(12 岁学习编程)

  • 运算符>>在应用于流(和字符串)时读取单个(空白)空格分隔的单词。

    std::string message="The quick brown fox jumped over the lazy dog.";
    std::stringstream   stream(message);
    
    std::string  word;
    stream >> word; // Reads "The"
    stream >> word; // Reads "quick"
    stream >> word; // Reads "brown" etc...
    
  • istream_iterator 是流的适配器,使它们看起来像容器。
    它使用运算符 >>

    从“T”类型的流中读取项目
    std::stringstream   stream("The quick brown fox jumped over the lazy dog.");
    std::istream_iterator<std::string> i(stream);
    
    std::string  word;
    
    word = *i;      // de-reference the iterator to get the object.   Reads "The"
    ++i;
    word = *i; ++i; // Reads "quick"
    word = *i; ++i; // Reads "brown" etc
    
    // Works for any type that uses >> to read from the stream 
    std::stringstream   intstream("99 40 32 64 20 10 9 8 102");
    std::istream_iterator<int> i(stream);  // Notice the type is int here
    
    int   number;
    
    number = *i;      // de-reference the iterator to get the object.   Reads "99"
    ++i;
    number = *i; ++i; // Reads "44"
    number = *i; ++i; // Reads "32" etc
    
  • 标准算法都适用于迭代器。
    std::copy 遍历源并将每个项目放在目标中:

    int    src[] = { 1, 2, 3, 4, 5, 6 };
    int    dst[] = { 0, 0, 0, 0, 0, 0 };
    
    std::copy(src, src+6, dst); // copies src into dst
                                // It assumes there is enough space in dst
    
  • back_inserter 是一个适配器,它使用 push_back 将项目添加到容器中。
    我们可以确保目标向量的大小正确。但是使用 back_inserter 来确保向量是动态调整大小更容易。

    int    src[] = { 1, 2, 3, 4, 5, 6 };
    std::vector<int> dst; // Currently has zero size
    
    std::copy(src, src+6, std::back_inserter(dst)); // copies src into dst
                                                    // back_inserter expands dst to fit
                                                    // by using push_back
    
  • 将它们重新组合在一起:

    // Create a stream from the string
    std::stringstream   stream(message);
    
    // Use std::copy to copy from the string.
    //     The stream is iterated over a word at a time.
    //     because the istream iterator is using std::string type.
    //
    //     The istream_iterator with no parameters is equivelent to end.
    //
    //     The destination appends the word to the vector words.
    std::copy(std::istream_iterator<std::string>(stream), // 2: Copy words from the stream
              std::istream_iterator<std::string>(),
              std::back_inserter(words));                 //    into the back of the vector.
    

【讨论】:

  • 哦,废话。我十二岁,这是什么?嗯,远远超过我的水平。让我看看这些......
【解决方案2】:

您想按空格将字符串拆分为标记。你应该使用合适的工具——例如Boost.Tokenizer。你的代码在几个方面是错误的:

  1. 您不能这样定义数组,维度必须是编译时常量表达式。
  2. 数组不是指针,不能分配给数组。
  3. c_str 返回一个指针,只要字符串对象有效,该指针就有效。
  4. 除非需要,否则不要使用char*。使该向量保持std::string
  5. c_str 返回一个 char*,它没有 length 成员函数或任何与此相关的成员函数。

这表明你缺乏一些 C++ 基础知识。您或许应该阅读a good book on C++。所以,不,这不是 C++ 的缺点。

真的,只需使用 Boost.Tokenizer。它在文档中有一个按空格分割的示例。

【讨论】:

    【解决方案3】:

    stringsubstr 方法返回一个新的临时字符串,而c_str 方法返回一个指向该临时字符串内存的指针。 简而言之,将指针保存到临时缓冲区会导致未定义的行为。 如果您想保留子字符串,请改用string 类。 (i.e. vector&lt;string&gt;)

    【讨论】:

    • 等等,这听起来像是垃圾收集器的不良行为。
    • C++ 没有垃圾收集器。如果您使用char* 或其他原始指针,管理内存是您的工作,这正是您应该尽可能避免使用它们的原因。
    • @Josh:研究异常安全、RAII 和智能指针 :) C++ 非常需要...
    • @Josh:不要学删除。了解将为您删除的库类。它更安全,学习和使用也更快。
    【解决方案4】:

    天哪

    char *message="The quick brown fox jumped over the lazy dog.";
    
    vector<char*> words;
    
    int p=0;
    while(message[p])
    {
     words.push_back(&message[p++]);
    }
    
    //if you Must use a string, change to 
    words.push_back(&message.c_str()[p++]);
    

    这是,假设您想要指向每个字符的指针(我不知道您为什么会这样,但这是您编写的代码)。

    顺便说一句,你想做什么?

    【讨论】:

    • 从字符串中按空格分隔单词并将它们放入向量中
    【解决方案5】:

    通常,您只需使用vector&lt;string&gt;。作为 C++ 中的一般规则,看到原始指针是一个巨大的警告信号——要么使用智能指针并动态分配内存,要么使用值类型——例如std::string

    【讨论】:

    • 我不得不将它们用于我在高中用了 6 个月的人工神经网络——它们很熟悉。
    • @Josh:这可能是问题。没有懂 C++ 的人会写出类似上面的代码。
    • 嗯,我做到了,它奏效了。我想我把它弄坏了,通过让它指向已经初始化的东西来绕过 const ......这是不久前,我的最后一个硬盘驱动器代码死了。
    【解决方案6】:

    你想要数组中单词的副本,还是只是指向原始单词的指针?

    如果你想要副本,那么你需要一个字符串向量。

    此代码将创建单词的副本:

    vector<string> words;
    string::iterator it1 = message.begin();
    string::iterator it2 = find(message.begin(), message.end(), ' ');
    while (it2 != message.end())
    {
        words.push_back(string(it1, it2));
        it1 = ++it2;
        it2 = find(it2, message.end(), ' ');
    }
    words.push_back(string(it1, it2));
    

    此代码将为您提供指向原始单词的指针:

    vector<char*> words;
    string::iterator it1 = message.begin();
    string::iterator it2 = find(message.begin(), message.end(), ' ');
    while (it2 != message.end())
    {
        words.push_back(&*it1);
        it1 = ++it2;
        it2 = find(it2, message.end(), ' ');
    }
    words.push_back(&*it1);
    

    【讨论】:

    • 给我时间来处理这个。新东西。
    • 我现在希望数据一直持续到 main() 结束,那么你会建议哪一个?他们需要坚持到 main 中的后续循环,在那里他们会分散/随机化。
    • 原始指针选项给了我这个错误: corruptionEncryption.cpp:36:38: error: conversion from 'std::vector::iterator' to non-scalar type 'std: :basic_string::iterator' 请求 corruptionEncryption.cpp:37:62: 错误:没有匹配函数调用 'find(std::vector::iterator, std::vector: :iterator, char)' corruptionEncryption.cpp:38:27: error: no match for 'operator!=' in 'it2 != words.std::vector<_tp _alloc>::end [with _Tp = char*, _Alloc = std::allocator, std::vector<_tp _alloc>::iterator = __gnu_cxx::__norma...
    • 道歉:大部分wordsmessage。我会修复它[编辑:完成]
    • 我很懒,复制/粘贴了它们。
    猜你喜欢
    • 1970-01-01
    • 2013-03-20
    • 1970-01-01
    • 2022-08-11
    • 1970-01-01
    • 2013-11-09
    • 1970-01-01
    • 1970-01-01
    • 2020-01-09
    相关资源
    最近更新 更多