list<string> mylist;
mylist.push_back("random stuff");
list<string>::iterator it;
it=mylist.begin();
string mystr;
//and this doesn't work:
mystr=*it;
Let's say I have a list<string> mylist and it has 3 items. Since I can't work on the characters of each element I must copy what item I want to a simple string or a char buffer. But I can't find a way at all, I've tried with pointers to arrays as well.
So is there a way to copy those items out of the list ?
Edit:
Yeah sorry , revisited my code , the project that is , and found the error to be somewere else, i was copying from listmylist to a string mystr, with the help of an iterator, and i was using a for loop that had the condition to stop when it encountered the character '\0' put when i was copying it, it didn't copy the '\0' in my string so in the end i had to put it manually so the function would not work outside the string
Good code:
string temp;
list<string>::iterator it;
it=mylist.begin();//let's say myslist has "random stuff"
temp=*it;//this does not copy the '\0'
temp+='\0';//so i add it myself
for(int n(0);temp[n]!='\0';n++)//now the for loop stops properly
cout<<temp[n];
If you want characters from the string:
for (std::string::iterator it=mystr.begin(); it!=mystr.end(); it++)
{
char ch = *it;
// do something with the character?
}
If you want to pass the string as a C (zero-terminated) string, use
mystr.c_str()
The code works great and outputs the correct result. Also, you can work with characters of each element like this:
for (list<string>::iterator iter = mylist.begin(); iter != mylist.end(); ++iter)
{
char c = (*iter)[0]; //this is the first character.
}
You can cycle through the string with an iterator too even, strings have them as well :) Though strings support random-access-iterators, so you can just access them as arrays like a c-string as I showed in the for loop.
Are you perhaps looking for
list<string> mylist;
mylist.push_back("random stuff");
list<string>::iterator it = it=mylist.begin();
string& mystr = *it; // Note the &
The type string& is a reference to a string. It introduces a new name for the first element of the list. Well, at least what's currently the first element. You could of course do mylist_push_front("Hi There"); and mystr would still be "random stuff". But if you now say mystr = "Not so random stuff";, you will change the string inside the list.
Note that this is explicitly not a copy.
Small warning: mystr doesn't magically keep the string alive. If you remove the underlying string from the list, you must stop using mystr as well.
Related
for example how can i read just the first character of the first string:
vector <string> vec= {"aa","ab","abc","efg"};
Thank you.
You can read it like this:
std::vector <std::string> vec = { "aa","ab","abc","efg" };
std::vector<char> result;
for (auto it = vec.begin(); it != vec.end(); ++it)
{
result.push_back((*it)[0]); // (*it)[0] == vec[i][0]
}
Now result is a vector of first elements of each string
A vector just stores stuff you put in it, in this case, std::strings. To access the first element of a vector, as you said, there are multiple ways of doing that. The easiest, if you are used to arrays, is just using []:
std::string myString = myVector[0]; // store the first string of myVector
The second question is, how to access a character of a string, again, there are multiple ways of doing that, but again you can use []:
char myChar = myString[0]; //store the first character of myString
Also tip: It is generally frowned upon to use using namespace std;
I'm trying to convert .fsp files to strings but new .fsp file is very abnormal. It contains some undesirable characters that I want to delete from string. How can I make it?
I have tried to search char in string and delete them but I dont know how to make it.
The string looks like this:
string s;
s = 144˙037˙412˙864;
and I need to make it just like that
s = 144037412864;
So I except result like this:
string s = 144037412864;
Thank you for help.
We can use the remove-erase idiom to remove unnecessary characters from the string! There's a function in <algorithm> called remove_if. What remove_if does is it removes elements that match some predicate. remove_if returns a iterator pointing to the new end of the container after all elements have been removed. I'll show you how to write a function that does the job!
#include <algorithm>
#include <string>
void erase_ticks(std::string& s) {
// Returns true for characters that should be removed
auto condition = [](char c) { return c == '`'; };
// Removes characters that match the condition,
// and returns the new endpoint of the string
auto new_end = std::remove_if(s.begin(), s.end(), condition);
// Erases characters from the new endpoint to the current endpoint
s.erase(new_end, s.end());
}
We can use this in main, and it works just as expected!
#include <iostream>
int main() {
std::string s("123`456`789");
std::cout << s << '\n'; // prints 123`456`789
erase_ticks(s);
std::cout << s << '\n'; // prints 123456789
}
This problem has two parts, first we need to identify any characters in the string which we don't want. From your use case it seems that anything that is not numeric needs to go. This is simple enough as the standard library defines a function std::isdigit (simply add the following inclusion "#include <locale>") which takes a character and returns a bool which indicates whether or not the character is numeric.
Second we need a way to quickly and cleanly remove all occurrences of these from the string. Thus we can use the 'Erase Remove' idiom to iterate through the string and do what we want.
string s = "123'4'5";
s.erase(std::remove_if(s.begin(), s.end(), [](char x)->bool {return !std::isdigit(x);}), s.end());
In the snippit above we're calling erase on the string which takes two iterators, the first refers to where we want to begin to delete from and the second tells the call where we want to delete to. The magic in this trick is actually all in the call to remove_if (include "#include <algorithm>" for it). remove_if actually works by shifting the elements (or characters) of string forward to the end of the string.
So "123'4'5'" becomes "12345'''", then it returns an iterator to where it shifted these characters to which is then passed to erase to tell it remove the characters starting here. In the end we're left with "12345" as expected.
Edit: Forgot to mention, remove_if also takes a predicate here I'm using a lambda which takes a character and returns a bool.
I use a vector (string) book and a word list const char** liste mywords. I know the push_back() method to fill the book. But I would like to insert each word at the beginning of the book. I try this, but I do not understand why the book is still empty.
vector<string>::iterator begin=book.begin();
vector<string>::iterator end=book.end();
vector<string>::iterator pos = book.insert(begin, *mywords);
vector<string>::reverse_iterator rit=book.rbegin();
while (*mywords !=NULL) {
for (rit=book.rbegin();rit != book.rend(); ++ rit)
dico.insert(pos, begin, end);
mywords++;
}
In the shown code, pos, begin, and end, are all iterators of book.
dico.insert(pos, begin, end);
This attempts to use these iterators, for some purposes, with some mysterious container called dico.
The insert() method of most containers typically takes an iterator for the same container. pos is not a dico iterator; as such this is most likely undefined behavior.
Ignoring your code for the moment (since I don't understand it), if you have a char ** containing a list of words (not sure why you'd do that, but let's move on) the easiest way to insert them at the beginning of a container would be to use std::deque instead of std::vector:
std::deque<std::string> book;
for (char *word = mywords[0]; word != NULL; ++word)
book.push_front(word);
If you really want to use a vector, then iterate it back to front, that's fairly easy as well:
std::vector<std::string> book;
for (char *word = mywords[0]; word != NULL; ++word)
book.push_back(word);
// Copy the words in reverse to standard output:
std::copy(book.rbegin(), book.rend(),
std::ostream_iterator<std::cout, "\n"));
I'm trying to do a loop for this part:
insert_front(&list,name[0]);
insert_front(&list,name[1]);
insert_front(&list,name[2]);
but, i can't figure out which should be used as a limiter, which should stop the loop for going and how it will change the name[] perimeters.
Here's the whole code:
#include "list.h"
#include "string"
using namespace std;
int main(){
cout<<"What is your name \n";
string name;
getline(cin,name);
Node *list;
list = new_list();
insert_front(&list,name[0]);
insert_front(&list,name[1]);
insert_front(&list,name[2]);
}
print_list(list);
delete_list(&list);
print_list(list);
return 0;
}
Iterator version (C++03):
for (std::string::iterator iter = name.begin(); iter != name.end(); ++iter)
insert_front(&list, *iter);
Foreach version (C++11):
for ( char c : name)
insert_front(&list, c);
Index version (C++03):
for (size_t i = 0; i < name.size(); ++i)
insert_front(&list, name[i]);
Foreach version (C++03 with Boost):
std::for_each(name.begin(), name.end(), boost::bind(insert_front, &list, _1));
I'm not so sure on the C++11 foreach version.
There's probably also a reasonable way to use std::copy or std::transform if your hand-coded list has iterators.
That's not really "the whole code" as you say. What elements does your list store? Looks to be a single character per node. So it appears you are you trying to make a list of characters to represent the person's name in reverse order.
That being the case:
for( size_t i = 0; i < name.length(); i++ ) {
insert_front(&list,name[i]);
}
The Standard Template Library, which strings are part of, provide some nice efficient and safe iterators for dealing with items you might want to loop over.
for(string::iterator iter = name.begin(); iter < name.end(); iter++) {
insert_front(&list, *iter);
}
string::begin shows this same example.
string::begin() returns an object that when dereferenced with operator* gives the value where its at. operator++() increments to the next position. string::end() gives another object after the end of the string so that the operator==() after the operator++() stops the loop.
Now, the important part here is that you aren't using indices. Many STL containers let you copy in values using the iterators. You could even skip the for loop to use an stl list and do something like the following:
std::list list (name.begin(), name.end());
Done. No manual for loop or for_each() call at all. You can even use name.begin() + 1 to skip the first character. See the list constructor for this.
As pointed out in a comment, to achieve the insert_front() reversing effect, this should be:
std::list list (name.rbegin(), name.rend());
string::rebgin() and string::rend() iterate in reverse order. To be simpler, this is coming after the use of string::begin() and string::end() to introduce the reversal separately.
Obviously, you are using a different list and will need some looping to continue using it. But, you might just decide to leave the string as a string and pass the relevant iterators to a print function and avoid using a list at all. This might allow you to make code generic enough to not care whether this is from a string or list.
I think you are trying to do:
for(int i=0; i<name.size(); i++)
{
insert_front(&list,name[i]);
}
And this will store each character of the name in the list.
In my program I would like to manipulate boost::filesystem::path elements of a vector in a for loop.
typedef vector<fs::path> path_vec;
path_vec pv;
for (auto it = pv.cbegin(), end = pv.cend(); it != end; ++it)
What I would like to do is to add a string to the end of the path.
If I do it like this, it works fine:
stringstream image_file_0001;
image_file_0001 << it->string() << "/x_alpha0001.png";
p1 = image_file_0001.str();
If I do it like this, it works fine too:
string a = it->string();
string b = a.append("/prx");
But if I try to do it in one line
string c = it->string().append("/prx");
or
string d = (it->string()).append("/prx");
it gives compile errors:
7 overloads have no legal conversion for 'this' pointer
I think it must be my lack of knowledge about how to use pointers, or is it something to do with the boost::filesystem::path .string() function?
OK, the thing I would like to do is to create a directory with "/prx" appended to the origianl path in *it. Can I do it in one line?
boost::filesystem::createdirectory ( something here );
What seems to be my problem is that I don't understand that why would .append() modify the original string. Isn't it a function which returns an other string, which I can use freely, while just reading the original string?
fs::path.string() returns const& so you cannot append anything to it, first you need to make a copy
but why do you do this at all? there's a obvious way to append nested path:
path / nested_path
EDIT:
typedef vector<fs::path> path_vec;
path_vec pv;
for (auto it = pv.begin(), end = pv.end(); it != end; ++it)
*it /= "prx";
or to create directories instead of modifying vector values, replace the last line by:
fs::create_directory(*it / "prx");
it->string() is probably constant. Why don't you say:
const std::string a = it->string() + "/prx";