1

This is a beginner type of question

I'm just wondering if there is a way to convert a null terminated char* to std::list.

Thank you

char* data = ...
std::list<char> clist = convert_chars2list(data);
...
convert_chars2list(char* somedata)
{
    //convert
}
Mohamed Tarek
  • 111
  • 4
  • 11

6 Answers6

9

This is probably the simplest way:

#include <list>
#include <string>

int main() 
{ 
    char const* data = "Hello world";
    std::list<char> l(data, data + strlen(data));
}

It exploits the fact that std::string has an interface which is compatible with STL containers.

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
  • A better solution that mine. – Nik Bougalis Feb 22 '13 at 23:10
  • That works? I would have thought you needed to use iterators. – chris Feb 22 '13 at 23:15
  • Doing it this way does give a warning with vs2010. warning C4930: 'std::list<_Ty> l(std::string)': prototyped function not called (was a variable definition intended?) – Caesar Feb 22 '13 at 23:16
  • @Caesar, Yeah, that's a sign of the MVP. `l` is a function with that declaration. – chris Feb 22 '13 at 23:17
  • While doing it this way is quick in term of typing, I think it is not the most optimal option just because a string has to be allocated and than a list. – Caesar Feb 22 '13 at 23:22
  • 1
    @Caesar: That's correct. In fact, I wrote this is probably the "simplest" way. I believe you should always favor simplicity, unless you are really concerned with performance. There is no evidence here that this would be a performance-critical operation. Hence, my choice. – Andy Prowl Feb 22 '13 at 23:24
  • Unless I'm missing something, couldn't you just do `data, data + strlen(data) + 1`? Will avoid extra allocations, and seems just as readable. – Corbin Feb 22 '13 at 23:44
2
std::list<char> convert_chars2list(char *somedata)
{
    std::list<char> l;

    while(*somedata != 0)
        l.push_back(*somedata++);

    // If you want to add a terminating NULL character
    // in your list, uncomment the following statement:
    // l.push_back(0);

    return l;
}
Nik Bougalis
  • 10,495
  • 1
  • 21
  • 37
  • `l.push_back(*somedata++);`: Isn't this Undefined Behavior? The side effect of `operator ++` is not sequenced before the evaluation the argument of `operator *`... or am I confused? – Andy Prowl Feb 22 '13 at 23:25
  • @NikBougalis: I always get confused even with this simple stuff: so is it `*(somedata++)` or `(*somedata)++`? In the first case I believe it is UB, because the side effect of `++` is unsequenced wrt to the value computation of `*`. I believe... – Andy Prowl Feb 22 '13 at 23:34
  • @AndyProwl actually I was wrong. According to http://en.cppreference.com/w/cpp/language/operator_precedence *postfix* `++` has a higher precedence that `*`. I don't think this is UB - franly, I'd be surprised if it were since it's such a commonly used idiom. But you do have me thinking; I'll have to research this more closely now I think. – Nik Bougalis Feb 22 '13 at 23:39
  • Well, the side-effect of incrementing `somedata` is not sequenced before the value computation of `*(somedata++)`. At least I believe so. So that should be UB... but I'm not 100% sure. – Andy Prowl Feb 22 '13 at 23:48
  • 1
    I got it wrong too, even after looking it up! The moral is that you basically shouldn't do things like this because it's too easy to misunderstand; however, this is an exception because it's a common idiom that programmers know works even if they don't know all the rules that make it work off the top of their heads. – David Schwartz Feb 22 '13 at 23:49
  • 2
    @AndyProwl: It doesn't matter when the side-effect happens. It has no effect on the result. – David Schwartz Feb 22 '13 at 23:50
  • @DavidSchwartz: Hm, on the one hand I know this *must* work, on the other hand I can't see why. I thought since `operator ++` has a side-effect on the object `somedata`, and `operator *` performs a value computation that depends on the value of the object `somedata`, this would be UB per 1.9/15: *"If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined."* – Andy Prowl Feb 22 '13 at 23:54
  • I think I'm going to post a question about this and hopefully get some of the C++ gurus on here to chime in. – Nik Bougalis Feb 22 '13 at 23:55
  • 2
    @DavidSchwartz: Oh, I got it. `operator *` does not perform a value computation that depends on the value of the object `somedata`. The value computation depends on the value returned by `somedata++`. So that's not UB. Damn, I think I'll never learn this stuff – Andy Prowl Feb 22 '13 at 23:55
  • 2
    @NikBougalis: Don't do that: you'll most likely get stoned by people pissed off at how many times these things have been repeated over and over again :-) – Andy Prowl Feb 22 '13 at 23:56
  • 1
    Woe... my dreams of a "Famous Question" gold badge evaporated. – Nik Bougalis Feb 23 '13 at 00:06
1
std::list<char> convert_chars2list(char* somedata)
{
  std::list<char> res;
  while (*somedata)
     res.push_back(*somedata++);
  return res;
}
eci
  • 2,294
  • 20
  • 18
0

If your char* is a C-style string than you can do this (that means it ends with a \0)

#include <list>

int main()
{
    char hello[] = "Hello World!";

    std::list<char> helloList;

    for(int index = 0; hello[index] != 0; ++index)
    {
        helloList.push_back( hello[index] );
    }    
}
Caesar
  • 9,483
  • 8
  • 40
  • 66
0

Let C++ standard library take care of pointer handling and iterator traversing.

std::string str = "Hello world";

Though you can access each character with [] operator from std::string itself, if you want a list of characters

std::list<char> chars(str.begin(), str.end());
Pavan Chandaka
  • 11,671
  • 5
  • 26
  • 34
-1

It's really weird to use a std::list to contain characters, if you really want to use stl to contain characters, you could use std::string, which would allow you to do:

char*           data = ....;
std::string     string(data);
SeedmanJ
  • 444
  • 2
  • 8