Related
I'm a C++ beginner and I'm stuck on my course assignment because I can't wrap my head around how to modify values of an array passed to a function.
Honestly, we haven't reached the topic about arrays yet in class, but I recall some basic functionalities related to them and I wanted to solve the exercise using arrays because it's surely a smarter way to do it then the easy version of the assignment without them (that I've already solved). I've looked online for some references but clearly I'm missing something important.
The assignment states:
In this exercise you’ll investigate a simple scheme for encrypting and decrypting data. A company that wants to send data over the Internet has asked you to write a program that will encrypt the data so that it may be transmitted more securely. All the data is transmitted as four-digit integers. Your application should read a four-digit integer entered by the user and encrypt it as follows:
Replace each digit with the result of adding 7 to the digit and getting the remainder after dividing the new value by 10.
Then swap the first digit with the third, and swap the second digit with the fourth.
Then print the encrypted integer.
And my attempt is this:
main.cpp
#include "encrypt.h"
#include <iostream>
const size_t size{4};
int main () {
int arrEncrypt[size] = {1, 2, 3, 4};
swap(arrEncrypt[size]);
encrypt(arrEncrypt[size]);
printArr(arrEncrypt[size]);
}
encrypt.h
#ifndef ENCRYPT_H
#define ENCRYPT_H
void encrypt(int a[]);
void swap(int a[]);
void printArr(int a[]);
#endif
encrypt.cpp
#include <iostream>
#include "encrypt.h"
const size_t num{4};
// Replace each digit with the result of adding 7 to the digit and getting the remainder after dividing the new value by 10.
void encrypt(int arr[::num]) {
for (int k = 0; k < ::num; k++) {
arr[k] = (arr[k] + 7) % 10;
}
}
// Then swap the first digit with the third, and swap the second digit with the fourth.
void swap(int arr[::num]) {
int box[1] = {0};
for (int k = 0; k < (::num / 2); k++) {
box[1] = arr[k];
arr[k] = arr[k+2];
arr[k+2] = box[1];
}
box[1] = arr[0];
arr[0] = arr[2];
arr[2] = box[1];
box[1] = arr[1];
arr[1] = arr[3];
arr[3] = box[1];
}
// Then print the encrypted integer.
void printArr(int arr[::num]) {
for (int k = 0; k < ::num; k++) {
std::cout << arr[k] << " ";
}
}
The swap function has some problems in the algorithm probably because I tried printing the for loop output and I get just one random value, while the bit manually written is working fine. I don't know why.
This program clearly doesn't work because every time I pass the array to a function it is always the one declared in main and not an array modified by the functions. I tried pointing to the array passed to the functions but I think I messed it up because I got a bunch of errors - moreover, I've read that taking the address of a built-in array to pass it to a function is not needed and I can simply pass the built-in array’s name because the called function can modify all the elements of an array in the caller, unless the function precedes the corresponding built-in array parameter with const to indicate that the elements should not be modified. But I don't get why in my program it doesn't work.
Thanks in advance for anyone who would take their time to help me out, I really appreciate it.
An array can't be passed to a function by value, only by reference or pointer. In your case, a parameter like int a[] is really just syntax sugar for a pointer int *a. But you are not actually calling the functions with a pointer, you are indexing into arrEncrypt and passing an individual int instead (using an index that is out of range!).
Get rid of the array indexing at the call sites. An array decays into a pointer to its 1st element when it is referred to by just its name.
Also, such parameters don't carry size information, so you have to pass the array size explicitly in a separate parameter.
Try this instead:
#include "encrypt.h"
const size_t size{4};
int main () {
int arrEncrypt[size] = {1, 2, 3, 4};
swap(arrEncrypt, size);
encrypt(arrEncrypt, size);
printArr(arrEncrypt, size);
}
encrypt.h
#ifndef ENCRYPT_H
#define ENCRYPT_H
void encrypt(int a[], int size);
void swap(int a[], int size);
void printArr(int a[], int size);
#endif
encrypt.cpp
#include <iostream>
#include <stdexcept>
#include "encrypt.h"
// Replace each digit with the result of adding 7 to the digit and getting the remainder after dividing the new value by 10.
void encrypt(int arr[], int size) {
if (!arr || size < 0) throw invalid_argument("");
for (int k = 0; k < size; k++) {
arr[k] = (arr[k] + 7) % 10;
}
}
// Then swap the first digit with the third, and swap the second digit with the fourth.
void swap(int arr[], int size) {
if (!arr || size < 4) throw invalid_argument("");
int box;
for (int k = 0; k < (size / 2); k++) {
box = arr[k];
arr[k] = arr[k+2];
arr[k+2] = box;
}
box = arr[0];
arr[0] = arr[2];
arr[2] = box;
box = arr[1];
arr[1] = arr[3];
arr[3] = box;
}
// Then print the encrypted integer.
void printArr(int arr[], int size) {
if (!arr) throw invalid_argument("");
for (int k = 0; k < size; k++) {
std::cout << arr[k] << " ";
}
}
That being said, consider using std::vector instead, eg:
#include "encrypt.h"
int main () {
std::vector<int> arrEncrypt = {1, 2, 3, 4};
swap(arrEncrypt);
encrypt(arrEncrypt);
printArr(arrEncrypt);
}
encrypt.h
#ifndef ENCRYPT_H
#define ENCRYPT_H
#include <vector>
void encrypt(std::vector<int> &a);
void swap(std::vector<int> &a);
void printArr(const std::vector<int> &a);
#endif
encrypt.cpp
#include <iostream>
#include <utility>
#include <stdexcept>
#include "encrypt.h"
// Replace each digit with the result of adding 7 to the digit and getting the remainder after dividing the new value by 10.
void encrypt(std::vector<int> &arr) {
for (size_t k = 0; k < arr.size(); k++) {
arr[k] = (arr[k] + 7) % 10;
}
}
// Then swap the first digit with the third, and swap the second digit with the fourth.
void swap(std::vector<int> &arr) {
if (arr.size() < 4) throw invalid_argument("");
for (size_t k = 0; k < (a.size() / 2); k++) {
std::swap(arr[k], arr[k+2]);
}
std::swap(arr[0], arr[2]);
std::swap(arr[1], arr[3]);
}
// Then print the encrypted integer.
void printArr(const std::vector<int> &arr) {
for (size_t k = 0; k < arr.size(); k++) {
std::cout << arr[k] << " ";
}
}
Or std::array, eg:
#include "encrypt.h"
int main () {
std::array<int, size> arrEncrypt = {1, 2, 3, 4};
swap(arrEncrypt);
encrypt(arrEncrypt);
printArr(arrEncrypt);
}
encrypt.h
#ifndef ENCRYPT_H
#define ENCRYPT_H
#include <array>
#include <iostream>
#include <utility>
// Replace each digit with the result of adding 7 to the digit and getting the remainder after dividing the new value by 10.
template<typename T, size_t N>
void encrypt(std::array<T, N> &arr) {
for (size_t k = 0; k < N; k++) {
arr[k] = (arr[k] + 7) % 10;
}
}
// Then swap the first digit with the third, and swap the second digit with the fourth.
template<typename T, size_t N>
void swap(std::array<T, N> &arr) {
if (N < 4) throw invalid_argument("");
for (size_t k = 0; k < (N / 2); k++) {
std::swap(arr[k], arr[k+2]);
}
std::swap(arr[0], arr[2]);
std::swap(arr[1], arr[3]);
}
// Then print the encrypted integer.
template<typename T, size_t N>
void printArr(const std::array<T, N> &arr) {
for (size_t k = 0; k < N; k++) {
std::cout << arr[k] << " ";
}
}
#endif
The arguments arrEncrypt[size] in the function main() is bad because
It is out-of-range because the array arrEncrypt has only size elements and its valid indice are 0 to size-1.
The functions are expecting pointers, but an integer is passed.
The element box[1] used in the function swap() is out-of-range because the array box has only one element. Since it looks you are using only the element box[1] from the array box, you should stop using array here and instead of that you should use simple variable box.
In the function main(), you should pass the array (or a pointer to the first element of the array converted from the array) to the function:
int main () {
int arrEncrypt[size] = {1, 2, 3, 4};
swap(arrEncrypt);
encrypt(arrEncrypt);
printArr(arrEncrypt);
}
In the function swap(), you should stop using out-of-range "element":
void swap(int arr[::num]) {
int box = 0;
for (int k = 0; k < (::num / 2); k++) {
box = arr[k];
arr[k] = arr[k+2];
arr[k+2] = box;
}
box = arr[0];
arr[0] = arr[2];
arr[2] = box;
box = arr[1];
arr[1] = arr[3];
arr[3] = box;
}
Given a std::vector, for example of ints
std::vector vec{10, 20, 30}
how to select all items except of with given index, for example int i=1 resulting
std::vector {10, 30}?
If you just want to "select" values from the original vector, I would create another vector with all the new values.
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> vect{ 10, 20, 30 };
vector<int> selected;
int i = 1;
for (int j = 0; j < vect.size(); j++) {
if (j != i) {
selected.push_back(vect[j]);
}
}
// Added so you can check the new values
for (int z = 0; z < selected.size(); z++) {
cout << selected[z] << " ";
}
return 0;
}
However, if you want to erase values from your original vector I would recommend using the vector.erase method (research the documentation).
Here is a function for it where you can pass the vector and index and it will return you the new vector without that index element.
#include <iostream>
#include <vector>
using namespace std;
// returns a new vector without the v[index]
vector<int> getElementsExceptIndex(vector<int> v, int index){
vector<int> newVector;
for(auto &x:v ){
if(( &x - &v[0]) != index)
newVector.push_back(x);
}
return newVector;
}
int main() {
vector<int> originalVector{ 10, 20, 30 ,33,53};
int index=1;
auto RemovedIndexVector = getElementsExceptIndex(originalVector,index);
for(auto item:RemovedIndexVector)
cout<<item<<" ";
return 0;
}
// Output - 10 30 33 53
Hope this helps
I am trying to get the nth largest number of an array, I tried to sort the array then access the nth number by indexing; I have written this code:
#include <iostream>
using namespace std;
int largest(int a[],int k){
for (int i=0;i<=(sizeof(a)/sizeof(*a));i++){
for (int j=i+1;j<=(sizeof(a)/sizeof(*a));j++){
if(a[j]>a[i]){
int temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
}
return a[k-1];
}
int main()
{
int a[]={3,2,1,0,5,10};
int m=largest(a,4);
cout<<m<<endl;
return 0;
}
and when I print out m it appears to be 5 while it is expected to be 2, when I tried to replace int m=largest(a,4); with m=largest(a,1); it printed 2 so it appears that he prints the index of the array a but without sorting it, any idea?
The problem lies in the use of sizeof(a)/sizeof(*a) to get the number of elements of the array. sizeof(a) is the size of a pointer.
You need to pass the size of the array to the function.
int largest(int a[], int size, int k){
for (int i=0;i<size;i++){
for (int j=i+1;j<size;j++){
...
}
}
}
and call it with
int m = largest(a, 6, 4);
There are three problems with your code.
First, when you pass the array as an argument to your function, it decays into a pointer. So the function can never know the size of the array without additional information. It is main()'s job to find the size of the array and pass that information along to largest().
Second, you have an off-by-one error in your code, because you are attempting to iterate from 0 to the number of elements in the array.
The following will work:
#include <iostream>
using namespace std;
int largest(int a[],int k, int n){
for (int i = 0; i < n; i++){
for (int j = i + 1; j < n; j++){
if (a[j] > a[i]){
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
return a[k-1];
}
int main()
{
int a[] = {3, 2, 1, 0, 5, 10};
int k = 4;
int m = largest(a, k, sizeof a/ sizeof *a);
cout << m << endl;
}
At last but not least, you have nasty side effects in your function. If you have a function that is supposed to find the largest element of the array, it shouldn't modify the entire array in order to do so.
You can make a copy of the original array and sort it. Or you can implement a k-element sort algorithm. Either way you shouldn't change user data just to find some statistic from it.
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int a[]={3,2,1,0,5,10};
std::sort(a, a+6, greater<int>() ); // Sort an array of 6 elements in greatest-first order.
cout<<a[3]<<endl; // Show the 4th element from the front.
return 0;
}
UPD: There are STL algorithm to use: std::nth_element.
#include <iostream>
#include <algorithm>
int main(){
int arr[] = {54, 897, 87, 4, 6,987};
size_t length = 6, k = 3;
std::cout<<std::nth_element(arr, arr + k, arr + length, std::greater<int>());
}
Also, if you want to implement it by yourselt you can do such thing based on quick sort:
#include <iostream>
#include <algorithm>
template<class T>
T largest_k(T* a, size_t left, size_t right, size_t k) {
if(left>=right)
return a[k-1];
size_t i = left, j = right;
T middle = a[ i + (j-i) / 2 ];
do {
while ( a[i] > middle ) i++;
while ( a[j] < middle ) j--;
if (i <= j) {
std::swap(a[i], a[j]);
i++; j--;
}
} while ( i<=j );
// We need to go deeper only for needed part of a
if ( k<=j+1 )
return largest_k(a, left, j, k);
if ( k>= i )
return largest_k(a, i, right, k);
}
int main()
{
int arr[] = {54, 897, 87, 4, 6,987};
size_t length = 6, k = 3;
std::cout<<largest_k<int>(arr, 0, length-1, k);
}
I'm trying to convert my array to a vector, yet I'm having trouble printing it.
It says in int main() in my for loop that v is undefined. When I define
vector v; inside int main() the program compiles and runs and yet prints nothing. What am I doing wrong?
#include <iostream>
#include <vector>
using namespace std;
vector<int> a2v(int x[], int n)
{
vector<int> v(n);
for(int i = 0; i < n; i++)
{
v.push_back(x[i]);
}
return(v);
}
int main()
{
vector<int> a2v(int x[], int n);
int array[] = {11,12,13,14,15,16,17,18};
a2v(array, 8);
for(int i = 0; i < v.size(); i++)
{
cout << v[i] <<" ";
}
cout << endl;
return(0);
}
This is your program corrected:
#include <iostream>
#include <vector>
using namespace std;
vector<int> a2v(int x[], int n)
{
vector<int> v(0);
v.reserve(n); //optional
for(int i = 0; i < n; i++)
{
v.push_back(x[i]);
}
return(v);
}
int main()
{
int array[] = {11,12,13,14,15,16,17,18};
auto v = a2v(array, 8);
for(size_t i = 0; i < v.size(); i++)
{
cout << v[i] <<" ";
}
cout << endl;
return(0);
}
There were 2 errors:
In the function a2v, you instantiated a vector of 0 with length n, and then you pushed back other elements;
You were not defining v inside the main, as the return value of a2v
The vector you want to read is the return of the a2v function.
But there is a lot more simpler than that to go from C-array to vector array , I put here the example in found the vector reference web page :
http://www.cplusplus.com/reference/vector/vector/vector/
int myints[] = {16,2,77,29};
std::vector<int> fifth (myints, myints + sizeof(myints) / sizeof(int) );
When you define a variable, such as your vector v, you always do it in a certain scope. The body of a function such as a2v, or main, is an example of a possible scope. So if you only do it in the function a2v, that's the only scope where it will be visible.
It says in int main() in my for loop that v is undefined.
Well it will be because there is no v in main()
a2v(array, 8);
The above function call returns a vector so you need to collect the returned vector like
vector<int> v=a2v(array,8)
Also,
vector<int> v(n);//creates a vector of size n
for(int i = 0; i < n; i++)
{
v.push_back(x[i]);//adds n more elements to the vector
}
The returned vector has 2n elements and not n
Finally you could directly create a vector from an array as
vector<int> v(arr,arr+n);//where n is the number of elements in arr
So I have a function
f(int D[],int A[],int len){
for(int k = 0; k < len; k++)
D[k] = A[k];
and if I output D the numbers are all wrong. The function f is called with D initialised as int* D = new int[100000]; in the main function and A is all good because I output it in the function and it looks ok. So... can't understand where the problem is... I also tried memcpy(D+k,A+k,sizeof(int)); and it doesn't work.
Your loop works perfectly. The problem must be somewhere else in your code.
Here is an example program which copies the data in three different ways: a for loop, memcpy, and std::copy:
#include <algorithm>
#include <cstring>
#include <iostream>
#include <iterator>
void copy1(int D[], int A[], int len) {
for(int k = 0; k < len; k++)
D[k] = A[k];
}
void copy2(int D[], int A[], int len) {
std::memcpy(D, A, len*sizeof(int));
}
void copy3(int D[], int A[], int len) {
std::copy(A, A+len, D);
}
int main () {
int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int *d = new int[10];
std::ostream_iterator<int> out(std::cout, ",");
// First, print the initial values
std::copy(d, d+10, out);
std::cout << "\n";
// Next do the copies and print the values again
copy1(d, a, 10);
std::copy(d, d+10, out);
std::cout << "\n";
copy2(d, a, 10);
std::copy(d, d+10, out);
std::cout << "\n";
copy3(d, a, 10);
std::copy(d, d+10, out);
std::cout << "\n";
}
The output I get is:
0,0,0,0,0,0,0,0,0,0,
1,2,3,4,5,6,7,8,9,10,
1,2,3,4,5,6,7,8,9,10,
1,2,3,4,5,6,7,8,9,10,
Run your code in debugger and see if you do not have garbage in A[] in the first place (it could go wrong after function call). Also I suggest you pass reference (like int & D[] and const int & A[] — const to prevent altering of A).
Start with a minimal working example such as the following, then integrate your other code into it until something breaks. That’ll be the source of your error. Without more information, this is pretty much all I can tell you; when you encounter wrong values in a C++ program, you’re likely reading from an uninitialised variable. I suggest you try stepping through your program in a debugger such as GDB.
#include <algorithm>
#include <iostream>
#include <iterator>
void f(int D[], const int A[], int len){
for(int k = 0; k < len; k++)
D[k] = A[k];
}
int main(int argc, char** argv) {
int A[] = { 1, 2, 3, 4, 5 };
int D[5];
f(D, A, 5);
std::copy(A, A + 5, std::ostream_iterator<int>(std::cout, " "));
std::cout << '\n';
std::copy(D, D + 5, std::ostream_iterator<int>(std::cout, " "));
return 0;
}
Unless you have a very good reason to do so, prefer std::vector and std::array over raw arrays. Learning how arrays and pointers work is a good reason to use them, though.
I believe the problem is that you are passing in a pointer to an array
int* D = new int[100000];
however, your function takes two integer arrays, which is not the same as a pointer to an array.
Here's a SSCCE of a snippet that behaves like you want it:
#include <iostream>
using namespace std;
void f(int * d, int * a, int length){
for(int k = 0; k < length; k++){
d[k] = a[k];
}
}
int main() {
int* a = new int[9];
for(int i = 0; i < 9; i++){a[i] = i;}
int* d = new int[9];
f(d, a, 9);
for(int i = 0; i < 9; i++){
cout << d[i] << " ";
}
}