How to select the nth position from a string vector? - c++

How does one find, let's say, the 2nd position from a string vector?
Here's a string vector example:
1 2 3 4 Hi
7 8 9 0 Bye
2 2 5 6 World
If I use example.at(2), it gives me the whole row 2 2 5 6 World.
I just want to get 2 from the 1st row instead of getting the whole line of 2 2 5 6 World. How do I do that?

The return value of example.at(2) is the 3rd item in your vector, in this case, a std::string.
To access a specific character in your string, you can use the operator[]. So to select 2 from the first row, you would simply need to do the following:
example.at(0)[2];

So what you actually have is vector of string where string represents another dimension, so you have an table with both rows and columns, similar to an 2D array, in other to access a single cell you need 2 indexes, one index for position in vector and another for position in string.
So in your case it would be example[0][0] to get first char of a string in first row, and to get one you are looking for you would need to write example.at(0)[2];

This should work:
#include <iostream>
#include <string>
#include <vector>
int main() {
std::vector<std::string> strings;
strings.push_back("1234Hi");
strings.push_back("7890Bye");
std::cout << strings.at(0)[1] << std::endl; // prints 2
std::cout << strings.at(1)[1] << std::endl; // prints 8
}
It's sort of like a two-dimensional array: each string you push to the vector is analogous to the first dimension, and then each character of the string is analogous to the second dimension.
But as mentioned above, there may be better ways to do this, depending on what exactly you're trying to do.

Other answers show you how to access individual numbers in your strings, but they assume that the numbers are always 1 digit in length. If you ever need to support multi-digit numbers, use std::istringstream() or std::stoi() instead to parse the strings.

Related

Unexpected vector behavior using set intersection

I am trying to compare a 2 dimensional vector against another 2 dimensional vector.
vector<vector<int> >::iterator rowit1;
for(rowit1 = aboveaveperms.begin(); rowit1 != aboveaveperms.end();rowit1++)
{
vector<vector<int> >::iterator row2it;
int s = 0;
for(row2it = afterave.begin(); row2it != afterave.end();row2it++)
{
vector<int> matches (9);
vector<int>::iterator itset;
itset = set_intersection(rowit1->begin(),rowit1->end(),row2it->begin() + 1,row2it->end(),matches.begin());
matches.resize(itset-matches.begin());
s = matches.size();
matches.erase(matches.begin(),matches.end()); // my attempt at trying to correct it
}
}
In the second loop on the first pass matches is created correctly holding 9 zeros. But once it begins the second loop, as soon as it hits the curly bracket, it comes out with 101 million instead of 9. Once it actually hits it's declaration it goes back to the 9 which is proper. I have noticed while debugging that it is holding all of the 2 dimensional vector I am checking against before the declaration corrects it to only holding 9 ints.
idzireit
APPENDUM:
As it has been pointed out I forgot to ask my question. The above code does work as I want the number of matches (between 5 and 9) but because of the erratic behaviour of the vector will it cause a memory leak or sigseg if the other vectors get too big?
Also, as whozcraig asked, I have row2it->begin() + 1 because the first element is the game number which is much bigger then the rest of the numbers. The rest of the numbers are sorted though.
Example of what I am trying to do is as follows:
perm vector 1
1 3 5 6 7
compare against 4 vectors and count for number of matches in each
5 8 9 10 11
3 7 11 14 18
1 5 6 7 8
so in running through the loop the first match should be 1 second should be 2 and third should be 4. Hope this helps to clarify what I am trying to do.
ADDENDUM 2:
Now that I have my windoze machine up and running and have reinstalled qt creator on it I have run the above code and works fine on windows. I do not get the 101 million elements like I did when running under ubuntu. Why does it work correctly on windoze and not ubuntu ?
idzireit
Firstly, according to https://en.cppreference.com/w/cpp/algorithm/set_intersection, both vectors be intersected must be sorted.
Secondly, you set an initial size of 9 to vector matches, but if the number of intersected elements is greater than 9, then std::set_intersection is writing out of bounds of matches, which may cause an undefined behaviour.
You can execute your code using a memory analyzer as Valgrind in order to detect a possible memory leak. You could use std::back_inserter to avoid this problem:
#include <iterator> // std::back_inserter
vector<int> matches;
std::back_insert_iterator<std::vector<int> > itset(matches);
itset = set_intersection(rowit1->begin(),rowit1->end(),row2it->begin() + 1,row2it->end(), std::back_inserter(matches));

Occurrences in 2D array from 2D Array

Recently I've come into a wall, because I have no idea how to count the occurrences in one 2d array from another 2d array. For example, if I have
int winning_nums[3][6]; // random generated numbers array
and
int array[7][7]; // Sorted array from 1 to 49
I need to get all occurrences of each number in winning_nums to all the elements in array.For example: If I got 1 array of winning_nums that equals 6 size, 1 2 3 4 5 6 needs to be checked if they are occuring in array, like for each row in winning_nums.
I've tried to sort it out, like sort the winning_nums array, and then try to occur it with two additional for loops.
Any better ideas? Anything is welcomed.

Sort numbers in digit order

I know that when the numbers are input as strings and sorted normally, I would get the correct output. But can someone explain how/why this is happening?
Example test case:
Input:
100 1 10 2 21 20
Output:
1 10 100 2 20 21
Digits, when considered as characters, are handled the same as alphabetical characters. (i.e. they have a relative lexicographical order, which is the same as their ordering based on ascending value)
In effect, when you're handling integers as string,s you may consider digits 0,1,2,3,4,5,6,7,8,9 to be letters 'a','b','c','d','e','f','g','h','i','j'. Consequently, sorting the input can be thought of as sorting strings.
Your original input;
100 1 10 2 21 20
can then be considered as;
baa b ba c cb ca
for which the appropriate ordering would be;
b ba baa c ca cb
If you switch back the values, you may see that this is the output you provided in your question, namely;
1 10 100 2 20 21
That is just how default lexicographical string comparison works.
What you are probably looking for is called natural sort:
Natural order means sorting strings so that embedded numbers are treated as numbers. This means that if you use natural order for sorting you get this:
1 one
2 two
3 three
10 ten
Instead of the default sort behaviour:
1 one
10 ten
2 two
3 three
Reading a list of numbers, sorting them and then printing them out is extremely easy in C++ once you know the "secret".
The "secret" is to use the functionality that exist in the standard library. In this case (reading numbers, sorting them, printing them out) you need to know about std::vector, std::istream_iterator, std::sort, std::copy and std::ostream_iterator.
Then you could do something like
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
int main()
{
// Create a vector containing numbers read from std::cin
std::vector<int> number(std::istream_iterator<int>(std::cin),
std::istream_iterator<int>());
// Sort the numbers
std::sort(begin(numbers), end(numbers));
// Print all the numbers in the vector to std::cout
std::copy(begin(numbers), end(numbers),
std::ostream_iterator<int>(std::cout, " "));
}

C++ Arrays and overflow

I am mis-understanding something about the code below. From my understanding the tester declaration should return a pointer to the first array of two elements, i.e. [1,2], and so *(tester+1) should return [3,4], which only has 2 elements so how does it make sense to call (*(tester + 1))[2] . This example prints the number 5 by the way. Any clarifications much appreciated.
int main() {
int tester[][2]{ 1,2,3,4,5,6 };
cout << (*(tester + 1))[2] << endl;
return 0;
}
When you declare a 2-dimensional array, all the elements are contiguous. The entire array is a single object, so you're not going out of bounds when you just exceed one of the row limits, so longer as you're still in the array. So the next element after tester[1,1] is tester[2,0], and that's what (*(tester + 1))[2] accesses.
[2] is higher than the highest element at [1] because the index starts at [0]
There are three arrays.
[1,2] positions 0,0 and 0,1
[3,4] positions 1,0 and 1,2
[5,6] positions 2,0 and 2,1
Since all of the arrays are next to each other in the data segment, going out of bounds on the second array (tester + 1) bleeds over into the third array giving you the first element of the third array.
i.e. position 1,2 is the same as 2,0
int tester[][2]{ 1,2,3,4,5,6 } creates a 3 by 2 array.
tester[0][0] = 1
tester[0][1] = 2
tester[1][0] = 3
tester[1][1] = 4
tester[2][0] = 5
tester[2][1] = 6
The compiler creates an array using the least amount of memory possible based on your specifications. [][2] explicit says to organize the data in such a fashion that there a x rows and 2 columns. Because you put 6 elements into the tester array, the compiler decides the number of rows to assign by dividing the number of total elements by the number of columns.
Furthermore, (*(tester + 1))[2], is equivalent to tester[2], which would access the element in the first column of the third row. Thus returning 5.
It is another way to write this code which means you define vector but it acts like 2-dimensional array.
int main() {
int tester[3][2]{ {1,2},{3,4},{5,6} };
std::cout<< tester[1][2] <<std::endl;
return 0;
}

Position of elements in vector

I have several elements in a vector type that are read from cin and then i perfrom some calculations on the vector and it's order of elements gets changed. The problem is that I need to print the positions of the vector elements after the calculations. I don't know how to explain this well that's why i'll give an example:
10 1 100 1000
and 10 is 1st element, 1 is 2nd, 100 is 3rd etc. After the calculations the vector changes in :
100 10 1 1000
so I should print
3 1 2 4
because 100 is the 3rd element of the input, 10 is the 1st etc. etc.
I tried with an array[1000] (because there aren't numbers larger than 1000 in the input), but it won't work because there can be multiple numbers with the same value, like:
10 10 10 100
and the output can be 1 2 3 4 or 2 3 1 4 or 3 1 2 4 etc. but here i need to output 1 2 3 4 because it's the 'smallest'.
I tried with array f[1001] and f[10] = 1, f[100] = 2, f[1] = 3 - if the numbers from the input are 10 100 1. But in case there are multiple numbers with the same value like 10 10 100, then my idea's not working. Please help me in any possible way.
Sounds like you need to store both the value and the initial position. You should be able to do this with an array of structs:
struct UserInput
{
unsigned int initialPosition;
int userInputValue;
};
int main()
{
userInput theUserInput[100];
// increment a counter, starting at 1, and place it in
// "initialPosition" in the struct as user input is read
}
I'll leave the rest up to you... as it is after all homework :) good luck.
Use an associative array if you know what it is.
Use linear search to determine the index if the number of input is limited.
Consider using log10 (or strlen) to transform the 1, 10, 100, 1000, etc. into 0, 1, 2, 3, etc.
From your description of such example:
10(3) 10(2) 10(1) 100(4)
What we have to output is 1 2 3 4, instead of 3 2 1 4.
So I don't think your requirement is just print the initial position directly. You've to make the position sequences as small as possible.
Following is my solution:
Use a direct-mapping hash table to store all the initial positions for specified element. All the initial positions for the same element is sorted. So if you want output the smallest position sequence, you only need to read the initial positions for this specified element from first to last.
The detailed implementation is left to you, since it's a homework.