2D Vectors Char to Int - c++

I am trying to convert a 2D Vectors of randomly generated chars to int. For example, if the chars are 'abc' then I want my int vector to be '97,98,99' etc.
I tried looking on here and for the most part, people are asking about char to sting, string to char, etc.
This is what I have so far.
#include <vector>
#include <cstdlib>
#include <string>
#include <iostream>
using namespace std;
int main()
{
vector<vector<char> > vec(100, vector<char>(10));
vector<vector<int> > intVec(100, vector<int>(10));
srand(time(NULL));
int intAscii = 0;
// Fill 2D vector with random chars
for(int i = 0; i < 1; i++)
{
rand_num = (rand() % 8 + 3);
for(int j = 0; j < rand_num; j++)
{
//logic here... randomly gen a char and place it in the same position, but this time in the int vector as an int.
vec.at(i).push_back((rand() % 26 + 97));
intAscii = int(vec.at(i).at(j));
intVec.at(i).push_back(intAscii);
}
// Print Contents & print out the int vector.
for(int i = 0; i < vec.size(); i++)
{
for(int j = 0; j < vec.at(i).size(); j++)
{
cout << vec.at(i).at(j);
cout << intVec.at(i).at(j);
}
}
}
The problem that I am running into is that when it prints out both vectors, chars is fine, for int I am getting a whole bunch of zeros. Which doesn't seem right because the int(vec.at(i).at(j)) works i.e if char vector was a then the int vector would be 97 and so on.
At this point, my guess is that the syntax for the int vector might be wrong.

You may try this:
intAscii = (int)vec.at(i).at(j);
In addition, to access the elements it could be better to use indices instead of push_back, like:
intVec.at(i).at(j) = intAscii;
This should work because you already allocate memory for your vector at the very beginning.

Related

How to avoid using same members in a matrix which is made by rand() function?

I'm trying to make a 5x10 matrix with full of random letters and once the letter is used, it shouldn't be used again. 25 of them have to be small letters, 25 ought to be big letters. Even numbered columns should be small letters too. I don't know how to avoid using same letters. I tried to send the letters used to another array made of one dimension, then check every letter sent by it so that same letter won't be used but my coding skills didn't let me do it.
So, my code is this so far:
#include <iostream>
#include <iomanip>
#include <stdlib.h>
#include <ctime>
#include <locale.h>
using namespace std;
const int row = 5;
const int column = 10;
int main()
{
char matris[row][column];
srand(time(0));
for (int i = 0; i < row; i++)
for (int j = 0; j < column; j++)
if(j % 2 == 0)
matris[i][j] = rand() % 25 + 65;
else
matris[i][j] = rand() % 25 + 97;
for (int i = 0; i < row; i++)
{
for (int j = 0; j < column; j++)
cout << setw(5) << matris[i][j];
cout << endl;
}
system("pause");
return 0;
}
So, how can I avoid using same letters? Did I approach wrongly? Is there a easier way to do what I'm trying to do? Thanks...
A possible solution is to create a vector containing all the symbols you want to use, randomized it, then draw from that. Example
#include <iostream>
#include <algorithm>
#include <vector>
#include <random>
using namespace std;
struct CharPool
{
size_t pos;
vector<char> m_unused_char;
CharPool()
: pos(0)
{
// add whatever characters you like to the pool
for (char c = 'a'; c <= 'z'; ++c)
m_unused_char.push_back(c);
for (char c = 'A'; c <= 'Z'; ++c)
m_unused_char.push_back(c);
std::random_device rd;
std::mt19937 g(rd());
// randomize
shuffle(m_unused_char.begin(), m_unused_char.end(), g);
}
char next()
{
// here we should assert that the pool is not depleted
return m_unused_char[pos++];
}
};
int main()
{
CharPool pool;
for (size_t i = 0; i < 10; ++i)
cout << pool.next() << ", ";
cout << "\n";
}
You need to keep trace of the chars that already appeared, to do so you can use a std::set , at each random call, you check if the random result is inside the set: if it is you simply random another number and retry; if not, you insert it and put it in your matrix.
I'd use a set rather than a vector because it's faster when checking if a value already appears in it.
See this to know how to check if a set contains an element:
How to check that an element is in a std::set?

C++ Buffer is too small Error

Intermittently, Visual Studio throws an exception when running my code. I say intermittently because I've been able to successfully run my code without an error. The error was thrown after I created the function "print_Days."
The exception thrown is:
Debug Assertion Failed!
File: minkernel\crts\ucrt\corecrt_internal_string_templates.h
Line: 81
Expression: (L"Buffer is too small" && 0)
The function reads from a .txt file that has 7 days of the week listed (Monday thru Sunday) and then alphabetically sorts the days in a 2D c-string array (professor is making us use c-string instead of string unfortunately).
Here is all of my code:
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
using namespace std;
//Constants for 2D array
const int NUM_OF_ROWS = 7; //Seven days listed in the file
const int NUM_OF_COLS = 10; //Longest word is 9 chars long, plus \0
void get_Days(ifstream& file, char days[][NUM_OF_COLS], int rows);
void sort_Days(char days[][NUM_OF_COLS], int rows);
void print_Days(const char days[][NUM_OF_COLS], const int rows);
void get_Days(ifstream& file, char days[][NUM_OF_COLS], int rows) {
//Read from text file and return day
for (int i = 0; i < rows; ++i)
{
file >> days[i];
}
}
void sort_Days(char days[][NUM_OF_COLS], int rows) {
//Sort the array alphabetically
char temp[NUM_OF_COLS];
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < rows; j++)
{
if (strcmp(days[j - 1], days[j]) > 0)
{
strcpy_s(temp, days[j - 1]);
strcpy_s(days[j - 1], days[j]);
strcpy_s(days[j], temp);
}
}
}
}
void print_Days(const char days[][NUM_OF_COLS], const int rows) {
//Print the sorted array to the console
for (int i = 0; i < NUM_OF_ROWS; ++i)
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < NUM_OF_COLS; j++)
{
cout << days[i][j] << endl;
}
}
}
int main() {
//This program reads from a file (days.txt), sorts the days
// alphabetically, and then prints the result to the console.
ifstream infile("days.txt");
char days[NUM_OF_ROWS][NUM_OF_COLS];
if (!infile)
{
cout << "File (days.txt) does not exist." << endl;
return 1;
}
get_Days(infile, days, NUM_OF_ROWS);
infile.close();
sort_Days(days, NUM_OF_ROWS);
print_Days(days, NUM_OF_ROWS);
return 0;
}
A few things are wrong with the code:
sort_Days
The sort_Days algorithm is throwing errors because you are trying to index days[j - 1] when the nested for loop starts with j = 0. So your initial index is out of bounds.
Furthermore, it seems like you are trying to perform bubble sort on the c-style strings, but your bubble sort implementation is incorrect. Please consult this page for how to implement a simple bubble sort. Hint: the for loop conditional, strcmp and strcpy_s indices need some tweaking.
print_Days
Your print_Days function is incorrect. Here is a version that prints out each c-style string instead of each char within the string:
void print_Days(const char days[][NUM_OF_COLS], const int rows)
{
for (int j = 0; j < rows; j++)
{
cout << days[j] << endl;
}
}
You should know that std::cout understands that when you pass it a c-style string (i.e. the char[NUM_OF_COLS] within days), it means you want to print out the whole string up to the null-terminator.
Your for loop termination conditional was also wrong, because you had j < NUM_OF_COLS, whereas days actually is an array with NUM_OF_ROWS elements, and each element is an array of NUM_OF_COLS size. The way you had it had indexing out of bounds of the days array.
And while I am nitpicking
Try not to use using namespace::std;, there are plenty of reasons why you shouldn't..

Fill 2D vector in C++

I'm trying to fill 2D vector in C++ with characters, but when I run this code it ends with one line characters (*..).
How can I fill 2D vector like this:
*.*
.**
#include <iostream>
#include <vector>
int main()
{
std::vector<std::vector<char> > vec2D;
std::vector<char> rowV;
unsigned int row=2;
unsigned int col=3;
char c;
unsigned int temp=0;
while(temp!=col)
{
while(rowV.size()!=row)
{
std::cin>>c;
rowV.push_back(c);
}
vec2D.push_back(rowV);
++temp;
}
return 0;
}
You should clear rowV after each insertion, otherwise it will be full and no other characters will be added. Also, row should be swapped by col and vice-versa, otherwise you will get a 3x2 (and not 2x3) 2D vector.
while(temp!=row)
{
while(rowV.size()!=col)
{
std::cin>>c;
rowV.push_back(c);
}
vec2D.push_back(rowV);
rowV.clear(); // clear after inserting
++temp;
}
It helps to know what [pushing back a 2DVector with an empty 1D vector] looks like.
See the example below.
#include <algorithm>
#include <cmath>
#include <iostream>
#include <vector>
using namespace std;
//-v-----A FUNCTION TO PRINT 2D VECTORS
template<typename T> //We don't know what type the elements are yet, so we use a template
void printVec2D(vector<vector<T>> a) // a is the name of our input 2Dvector of type (T)
{
for (int i = 0; i < a.size(); i++) {// a.size() will equal the number of rows (i suppose rows/columns can depend on how you look at it)
for (int j = 0; j < a[i].size(); j++) {// a[i].size() is the size of the i'th row (which equals the number of columns, foro a square array)
std::cout << a[i][j] << "\t";
}
std::cout << "\n";
}
return;
}
//-^--------
int main()
{
int X = 3; int Y = 3;
int VectorAsArray[3][3] = {{1,2,3},
{14,15,16},
{107,108,109}};
vector<vector<int>> T;
for (int i = 0; i < X; i++)
{
T.push_back({});// We insert a blank row until there are X rows
for (int j = 0; j < Y; j++)
{
T[i].push_back(VectorAsArray[i][j]); //Within the j'th row, we insert the element corresponding to the i'th column
}
}
printVec2D(T);
//system("pause"); //<- I know that this command works on Windows, but unsure otherwise( it is just a way to pause the program)
return 0;
}

Copying elements from one array to another c++

I have looked and looked and am still lost on how to copy or get elements from an array and put them into new arrays ( divide and conquer is the goal).
I have an array that generates 100 random numbers. I need to split the random numbers into 4 smaller arrays obviously containing 25 elements and not have any duplicates. I have read about using pointers, but honestly I don't understand why even use a pointer. Why do I care about another variables address?
I don't know how to do this. Here is my code so far:
#include <iostream>
#include <time.h>
#include <stdlib.h>
using namespace std;
int main()
{
// Seed the random number generator
srand(time(NULL));
//create an array to store our random numbers in
int Orignumbers[100] = {};
// Arrays for the divide and conquer method
int NumbersA [25] = {};
int NumbersB [25] = {};
int NumbersC [25] = {};
int NumbersD [25] = {};
//Generate the random numbers
for(int i =0; i < 100; i++)
{
int SomeRandomNumber = rand() % 100 + 1;
// Throw random number into the array
Orignumbers[i] = SomeRandomNumber;
}
// for(int i = 0; i < ) started the for loop for the other arrays, this is where I am stuck!!
// Print out the random numbers
for(int i = 0; i < 100; i++)
{
cout << Orignumbers[i] << " , ";
}
}
"divide and conquer" is rather easy; when copying into NumbersA and so forth, you just have to access your Originnumbers with a proper offset, i.e. 0, 25, 50, and 75:
for(int i = 0; i < 25; i++) {
NumbersA[i] = Orignumbers[i];
NumbersB[i] = Orignumbers[i+25];
NumbersC[i] = Orignumbers[i+50];
NumbersD[i] = Orignumbers[i+75];
}
The thing about "no duplicates" is a little bit more tricky. Generating a random sequence of unique numbers is usually solved through "shuffling". Standard library provides functions for that:
#include <random>
#include <algorithm>
#include <iterator>
#include <vector>
int main()
{
std::random_device rd;
std::mt19937 g(rd());
int Orignumbers[100];
//Generate the random numbers without duplicates
for(int i =0; i < 100; i++) {
Orignumbers[i] = i+1;
}
std::shuffle(Orignumbers, Orignumbers+100, g);
// Arrays for the divide and conquer method
int NumbersA [25] = {};
int NumbersB [25] = {};
int NumbersC [25] = {};
int NumbersD [25] = {};
for(int i = 0; i < 25; i++) {
NumbersA[i] = Orignumbers[i];
NumbersB[i] = Orignumbers[i+25];
NumbersC[i] = Orignumbers[i+50];
NumbersD[i] = Orignumbers[i+75];
}
// Print out the random numbers
for(int i = 0; i < 100; i++)
{
cout << Orignumbers[i] << " , ";
}
}
Problem:
The program can't be guaranteed to have no duplicate value as the rand() function can generate any random sequence and that may include the decimal value of 99 for 99 times though probability is very low but chances are.
Example:
for(loop=0; loop<9; loop++)
printf("%d", Rand()%10);
If looped for 10 times, it may result some values like:
Output: 6,1,1,1,2,9,1,3,6,9
Compiled Successfully:
Hence, no certainity that values won't repeat
Possibly Solution:
There could be a solution where you can place the values in OriginalArray and compare the rand() generate values against the OriginalArray values.
For first iteration of loop, you can directly assign value to OriginalArray then from 2nd iteration of loop you've to compare rand() value against OriginalArray but insertion time consumption may be higher than O(NN) as rand() function may repeat values.
Possibly Solution:
#include <iostream>
#include <time.h>
#include <stdlib.h>
using namespace std;
int main()
{
int Orignumbers[100] ;
int NumbersA [25] ,
NumbersB [25] ,
NumbersC [25] ,
NumbersD [25] ;
srand(time(NULL));
for(int i =0; i < 100; i++){
Orignumbers[i] = rand() % 100+1;
for(int loop=0; loop<i; loop++) {
if(Orignumber[loop] == Orignumber[i] ) {
i--;
break;
}
}
}
//Placing in four different arrays thats maybe needed.
for(int i = 0; i <25; i++ ) {
NumbersA[i] = Orignumbers[i];
NumbersB[i] = Orignumbers[i+25];
NumbersC[i] = Orignumbers[i+50];
NumbersD[i] = Orignumbers[i+75];
}
for(int i = 0; i < 99; i++)
cout << Orignumbers[i] << " , ";
}
As you tagged your question with C++ then forget about old-fashion arrays, let's do it C++ style.
You want to split your array into 4 arrays and they should not have duplicate numbers, so you can't have a number 5 times in your original array, because then surely one of your 4 arrays will have a duplicate one, So here is the way I propose to do it :
#include <set>
#include <ctime>
#include <vector>
int main() {
std::multiset<int> allNums;
std::srand(unsigned(std::time(0)));
for (int i = 0; i < 100; ++i) {
int SomeRandomNumber = std::rand() % 100 + 1;
if (allNums.count(SomeRandomNumber) < 4) {
allNums.insert(SomeRandomNumber);
}
else {
--i;
}
}
std::vector<int> vOne, vTwo, vThree, vFour;
for (auto iter = allNums.begin(); iter != allNums.end(); ++iter) {
vOne.push_back(*iter);
++iter;
vTwo.push_back(*iter);
++iter;
vThree.push_back(*iter);
++iter;
vFour.push_back(*iter);
}
system("pause");
return 0;
}
EDIT : As you mentioned in the comments, you just want to find a number in an array, so how about this :
for (int i = 0; i < 100; ++i) {
if (origArray[i] == magicNumber) {
cout << "magicNumber founded in index " << i << "of origArray";
}
}
On some situations, even on C++, the use of arrays might be preferable than vectors, for example, when dealing with multidimensional arrays (2D, 3D, etc) that needs to be continuous and ordered on the memory. (e.g. later access by other applications or faster exporting to file using formats such as HDF5.)
Like Jesper pointed out, you may use Copy and I would add MemCopy to copy the content of an array or memory block into another.
Don't underestimate the importance of pointers, they may solve your problem without the need doing any copy. A bit like Stephan solution but without the need of the index variable "i", just having the pointers initialized at different places on the array. For a very large number of elements, such strategy will save some relevant processing time.

Passing an array by reference as a function parameter in C++

How can I pass an array, declared in main method by reference as a parameter to a function? Also the compiler wants dimentions, but when i give them with variables, the compiler gives errors of invalid integer dimensions of the array, here's the code:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int scanV(int Row, int value, int M, int (&tableValues)[])
{
for (int i = 0; i <= M; ++i)
{
if (tableValues[Row - 1][i] == 1)
{
if (i + value <= M)
{
tableValues[Row][i+value] == 1;
}
if (i - value >= 0)
{
tableValues[Row][i-value] = 1;
}
}
}
}
int main()
{
int C, B, M;
cin>>C;
int integers[C];
for (int i = 1; i < C; ++i)
{
cin>>integers[i];
}
cin>>B;
cin>>M;
integers[0] = B;
int tableValues[C][M + 1];
tableValues[0][B] = 1;
for (int i = 1; i < C; ++i)
{
scanV(i, integers[i], M, tableValues);
}
return 0;
}
One simple solution is to use vectors. Consider this simple example:
#include <iostream>
#include <vector>
void f (std::vector<std::vector<int> > &v)
{
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j)
v[i][j] = i * 3 + j;
}
int main()
{
std::vector<std::vector<int> > v (3, std::vector<int> (3, 0));
f (v);
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j)
std::cout << v[i][j] << ' ';
}
In main, a 2D vector of ints (3x3) is created. The constructor shows 3 elements, all initialized with a vector of ints, which are in turn created with 3 elements initialized to 0.
Then, the vector is passed by reference to the function f, which assigns increasing values. When the vector is printed in main, it shows:
0 1 2 3 4 5 6 7 8
As you can see, their use is very similar to normal arrays, but they are actually contained, and provide easy access to a new level of programming using the STL.
In C++11, their use becomes even more familiar. You can assign vectors as follows:
std::vector<int> v0 = {2, 5};
std::vector<std::vector<int> > v1 { {1,2,3} , {4,5,6} , {7,8,9} };
Note that for vectors of multiple dimensions it's a good idea to encapsulate it in a matrix class of some sort with an underlying 1D vector type instead.
Edit:
Here's an example of initializing a 1D and 2D vector to specified elements. As seen above, this is easy in C++11, but if you have an array already, it's still pretty quick.
int a [5] = {1,2,3,4,5}; //normal
std::vector<int> v1 (a, a +5); //create using beginning and ending addresses of a
int b[3][3] = { {1,2,3} , {4,5,6} , {7,8,9} }; //normal
std::vector<std::vector<int> > v2; //empty vector
for (int i = 0; i < 3; ++i) //3 in first dimension
v2.push_back (std::vector<int> (b [i], b [i] + 3)); //push a vector with the appropriate 3 elements of b onto the back of v2
For going through one element at a time, you can do this:
std::vector<std::vector<int> > v (3, std::vector<int> (3));
for (int i = 0; i < v.size(); ++i) //v.size() == 3
for (int j = 0; j < v [i].size(); ++j)
adjustElement (v [i][j]); //replace with what you need
std::vectors are the way to go in C++ as variable-length arrays (such as int integers[C];) are forbidden.
I recommend typedefing these to make your code easier to read:
#include <vector>
typedef std::vector<int> row_t;
typedef std::vector<row_t> table_t;
Then you can declare:
void scanV(int Row, int value, int M, table_t& tableValues)
I've made this void since it doesn't return anything.
Your variables in int main() then become:
row_t integers;
table_t tableValues;
Watch out for this line:
tableValues[Row][i+value] == 1;
You probably meant to assign, rather than to check equivalence!
And please try to pick some more meaningful variable names than B, M, C...