programing tip

C ++에서 문자열로 가득 찬 std :: map을 반복하는 방법

itbloger 2020. 11. 28. 08:49
반응형

C ++에서 문자열로 가득 찬 std :: map을 반복하는 방법


을 사용하여 정의 된 문자열의 연관 배열을 반복하는 것과 관련된 다음 문제가 있습니다 std::map.

-- snip --
class something 
{
//...
   private:
      std::map<std::string, std::string> table;
//...
}

생성자에서 문자열 데이터와 관련된 문자열 키 쌍으로 테이블을 채 웁니다. 다른 곳에서는 toString테이블 개체 (키 = 데이터 형식)에 포함 된 모든 키와 관련 데이터를 포함하는 문자열 개체를 반환 하는 메서드 가 있습니다.

std::string something::toString() 
{
        std::map<std::string, std::string>::iterator iter;
        std::string* strToReturn = new std::string("");

        for (iter = table.begin(); iter != table.end(); iter++) {
           strToReturn->append(iter->first());
           strToReturn->append('=');
           strToRetunr->append(iter->second());
           //....
        }
       //...
}

컴파일하려고 할 때 다음 오류가 발생합니다.

error: "error: no match for call to ‘(std::basic_string<char,
    std::char_traits<char>, std::allocator<char> >) ()’".

누군가 나에게 무엇이 빠졌는지, 내가 뭘 잘못하고 있는지 설명해 줄 수 있습니까? hash_map사용자가 객체 hash_map와 함께 사용할 수 있도록 해싱 함수를 정의해야하는 경우 유사한 문제에 대한 논의 만 찾았습니다 std::string. 내 경우에도 비슷한 것이 될 수 있습니까?


주요 문제는 first()반복기에서 호출되는 메서드를 호출한다는 것 입니다. 당신이하려는 것은 다음과 같은 속성을 사용하는 것입니다 first.

...append(iter->first) rather than ...append(iter->first())

스타일의 문제로 new해당 문자열을 만드는 데 사용해서는 안됩니다 .

std::string something::toString() 
{
        std::map<std::string, std::string>::iterator iter;
        std::string strToReturn; //This is no longer on the heap

        for (iter = table.begin(); iter != table.end(); ++iter) {
           strToReturn.append(iter->first); //Not a method call
           strToReturn.append("=");
           strToReturn.append(iter->second);
           //....
           // Make sure you don't modify table here or the iterators will not work as you expect
        }
        //...
        return strToReturn;
}

편집 : facildelembrar는 (주석에서) 현대 C ++에서 이제 루프를 다시 작성할 수 있다고 지적했습니다.

for (auto& item: table) {
    ...
}

  1. toString()메소드를 작성하지 마십시오 . 이것은 Java가 아닙니다. 클래스에 대한 스트림 연산자를 구현하십시오.

  2. 자체 루프를 작성하는 것보다 표준 알고리즘을 사용하는 것이 좋습니다. 이 상황에서 std::for_each()원하는 작업에 대한 멋진 인터페이스를 제공합니다.

  3. 당신은 루프를 사용해야하지만, 데이터를 변경하지 않으려면, 선호 const_iterator이상 iterator. 이렇게하면 실수로 값을 변경하려고하면 컴파일러에서 경고를 표시합니다.

그때:

std::ostream& operator<<(std::ostream& str,something const& data)
{
    data.print(str)
    return str;
}

void something::print(std::ostream& str) const
{
    std::for_each(table.begin(),table.end(),PrintData(str));
}

Then when you want to print it, just stream the object:

int main()
{
    something    bob;
    std::cout << bob;
}

If you actually need a string representation of the object, you can then use lexical_cast.

int main()
{
    something    bob;

    std::string  rope = boost::lexical_cast<std::string>(bob);
}

The details that need to be filled in.

class somthing
{
    typedef std::map<std::string,std::string>    DataMap;
    struct PrintData
    {
         PrintData(std::ostream& str): m_str(str) {}
         void operator()(DataMap::value_type const& data) const
         {
             m_str << data.first << "=" << data.second << "\n";
         }
         private:  std::ostream& m_str;
    };
    DataMap    table;
    public:
        void something::print(std::ostream& str);
};

Change your append calls to say

...append(iter->first)

and

... append(iter->second)

Additionally, the line

std::string* strToReturn = new std::string("");

allocates a string on the heap. If you intend to actually return a pointer to this dynamically allocated string, the return should be changed to std::string*.

Alternatively, if you don't want to worry about managing that object on the heap, change the local declaration to

std::string strToReturn("");

and change the 'append' calls to use reference syntax...

strToReturn.append(...)

instead of

strToReturn->append(...)

Be aware that this will construct the string on the stack, then copy it into the return variable. This has performance implications.


Note that the result of dereferencing an std::map::iterator is an std::pair. The values of first and second are not functions, they are variables.

Change:

iter->first()

to

iter->first

Ditto with iter->second.


iter->first and iter->second are variables, you are attempting to call them as methods.


Use:

std::map<std::string, std::string>::const_iterator

instead:

std::map<std::string, std::string>::iterator

in c++11 you can use

for ( auto iter : table ) {
     key=iter->first();
     value=iter->second();
}

Another worthy optimization is the c_str ( ) member of the STL string classes, which returns an immutable null terminated string that can be passed around as a LPCTSTR, e. g., to a custom function that expects a LPCTSTR. Although I haven't traced through the destructor to confirm it, I suspect that the string class looks after the memory in which it creates the copy.

참고URL : https://stackoverflow.com/questions/1066677/how-to-iterate-over-a-stdmap-full-of-strings-in-c

반응형