How can i read from a vector of strings in c++ - c++

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;

Related

wordDiff must return array of strings with word in s that are not in t, in the order they appear in s

using namespace std;
vector<string> wordDiff(string s, string t)
{
istringstream parse_s(s);
vector<string> words_s(istream_iterator<string>(parse_s), {});
istringstream parse_t(t);
vector<string> words_t(istream_iterator<string>(parse_t), {});
sort(words_s.begin(), words_s.end());
sort(words_t.begin(), words_t.end());
vector<string> funk;
set_difference(words_s.begin(), words_s.end(),
words_t.begin(), words_t.end(),
back_inserter(ret));
return funk;
}
so far i am able to get the array of strings with words in s that are not i t with set_difference however i am unable to get the array in the order of s
The simplest solution is to put all excluded words into a std::unordered_set instead of a std::vector.
Then you can use the set to check each word in your word list if it has to be excluded or not. This way, you no longer need to sort. All you need is a copy_if and a lambda.
Simple solution is not to sort words_s (only words_t) and use std::remove_if:
sort(words_t.begin(), words_t.end());
auto it = std::remove_if( words_s.begin(), words_s.end(), [words_t]( const std::string &str ) {
return std::find( words_t.begin(), words_t.end(), str ) != words_t.end() );
} );
words_s.erase( it, words_s.end() );
you may want consider to use std::unordered_set instead of sorted vector for words_t

Is it possible to iterate over an iterator?

I have a working program that capitalizes strings in a vector, using iterators:
vector<string> v7{ 10, "apples" };
for (auto vIterator= v7.begin(); vIterator!= v7.end(); ++vIterator){
auto word = *vIterator; //here
auto charIterator = word.begin();
*charIterator = toupper(*charIterator);
*vIterator = word; //also here, i guess i could just print `word` instead?
cout << *vIterator << endl;
}
My question is;
2nd line inside the loop # the comment, i had to save the pointer to the iterator to another string variable before i was able to iterate over it.
Iterating over the pointer like so
*vIterator.begin();
didn't seem to work.
Is this the correct practice, or am i missing something?
I'm new to the C languages, the concept behind pointer-like tools is quite hard to understand even if i can use them, and in this case it just feels like I'm doing it wrong.
Edit: It was a syntax error (*vIterator).begin();
It just didn't make sense why i'd have to save it to another variable before iterating over it, cheers.
Since you are using C++11 look how simpler your code can become using ranged loops like the example below:
std::vector<std::string> v(10, "apples");
for(auto &&word : v) {
word[0] = toupper(word[0]);
}
LIVE DEMO
Now as far as it concerns the (*vIterator.begin(); didn't seem to work.):
The dot operator (i.e., .) has a higher precedence than the dereference operator (i.e., *). Thus, *vIterator.begin() is interpreted as *(vIterator.begin()). The compiler rightfully complains because vIterator hasn't got a member begin().
Think of iterators as if they were pointers. The correct way to access the members of an object via a pointer/iterator pointing to it is either using the arrow operator (i.e., vIterator->begin()) or first dereference the pointer/iterator and then use the dot operator (i.e., (*vIterator).begin()).
So your code via the use of iterators would become:
std::vector<std::string> v(10, "apples");
for(auto it(v.begin()), ite(v.end()); it != ite; ++it) {
*(it->begin()) = toupper(*(it->begin()));
}
LIVE DEMO
The correct way to write *vIterator.begin(); is (*vIterator).begin(); or, more often, vIterator->begin();. Also note that you can also access the first character of a string directly (without having to iterate over it) as word[0].
A simple STL-ish way of doing it:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<string> v7{ 10, "apples" };
for_each(v7.begin(), v7.end(), [](string& word){word[0] = toupper(word[0]);});
}

Append a copy of std::vector to the end of itself [duplicate]

This question already has answers here:
Nice way to append a vector to itself
(4 answers)
Closed 8 years ago.
I am trying to make a copy of a vector of string and append it to the end of its original vector, i.e. duplicating its contents. Example:
Input : vector<string> s = {"abc", "def"}
Output: vector<string> s = {"abc", "def", "abc", "def"}
I was using the insert method, i.e.
s.insert(s.end(), s.begin(), s.end());
However, this exhibits compiler-dependent results. In, LLVM clang, it gave me the expected answer.
With GCC it gave me
Output: vector<string> s = {"abc", "def", "", ""}
I am wondering why this happens and what's the safest way to achieve this vector duplication goal?
Here is the ideone.com link for the program above: http://ideone.com/40CH8q
Although it can possibly be done with iterators, a safe alternative is to avoid them:
size_t size = v.size(); // Of course we shouldn't access .size() in the loop...
v.reserve(size * 2); // Preallocation. Thanks #Ali for this performance hint
for (size_t i = 0; i < size; ++i)
v.push_back(v[i]);
In general, working with iterators while also modifying the data structure (not only its elements) is dangerous; you should read carefully when iterators are invalidated and when it's safe to reuse old iterators after a modification. Thus, it sometimes makes sense to use the "old" method to iterate through a random-access sequence: using an index variable.
As others have already pointed out, you need to make sure by calling vector::reserve() that the vector doesn't get reallocated during insertion. (It is also a good idea to call reserve if you chose to put the elements with push_back() into your vector.)
Then there is still the iterator invalidation issue (as detailed under vector::insert()) but the code below, as far as I know, bypasses that:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
using namespace std;
int main() {
vector<string> s{"abc", "def"};
auto size = s.size();
s.reserve(2*size); // <-- This one is essential to ensure
// no reallocation during insertion
const string* first = s.data(); // using pointer, instead of iterator
copy(first, first+size, back_inserter(s));
for (const auto& e : s)
cout << e << '\t';
cout << endl;
}
As already stated, it seems all you need to do is make a call to reserve:
sv.reserve(sv.size() * 2);
This is because if a reallocation occurs, the iterators are invalidated. You can check this for yourself:
std::cout << sv.capacity() << "\n"; // 2
The new size will be bigger than the capacity so a reallocation occurs.
This can be done this way too
vector<string> data = {"abc", "def"}; // Input String Vector
int len = data.size();
for(int i = 0; i < len; i++)
{
data.push_back(data[i]); // Making Copy of String Vector
}
vector<string> data = {"abc", "def", "abc", "def"};
//Resultant String Vector

for loop for simple linked list c++

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.

copying an element from list<string>mylist to string mystr

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.