How can i prohibit duplicate input values on a 2D array? - c++

Here is my code and I want to restrict reoccurring values when the user is trying to input the same value. It would be best if everything is only at the main function because i'm still learning about declaring more functions.
`
#include <iostream>
using namespace std;
int main() {
int num[10][10];
int times;
cout << "Please input the number of times you wish to enter a value but does not exceed to 100: ";
cin >> times;
cout << "Enter a value " << times * times << " times." << endl;
for(int i = 0; i < times; i++) {
for(int k = 0; k < times; k++) {
cout << "Please input a number on index [" << i << "][" << k << "]: ";
cin >> num[i][k];
}
}
//Displaying the inputs
cout << "Printing all values inside the array: " << endl;
for(int i = 0; i < times; i++) {
cout << endl;
for(int k = 0; k < times; k++) {
cout << "\t" << num[i][k] << " ";
}
}
return 0;
}
`
This is my expected output to be when a user tries to input a duplicate value:
Please input a number on index [0][0]: 7
Please input a number on index [0][1]: 7
Value already entered. Please try again.
Please input a number on index [0][1]:

In this context, you could have a function like this:
bool doesExist(
const int array[][10], const size_t size, const int value, int x, int y)
{
for (size_t i = 0; i < size; i++)
for (size_t j = 0; j < size; j++) {
if (x == i && y == j)
continue; // Skip the new element.
// If duplicate found
if (value == array[i][j])
return true;
}
return false;
}
It takes the array, its size, the value to be compared, and the position of the unique element inserted for the first time as arguments.
You could implement it this way:
cin >> num[i][k];
if (doesExist(num, times, num[i][k], i, k)) {
cout << "Already exists.\n";
...
}
This is not the best approach to this problem. In C++, it is recommended to apply STL containers as they provide more safety and iterators.

You just want the use not to enter duplicate values :-
First very basic you can just check all the previous values,
if it matches with the current one then you can tell the user to change the value.
You can use unordered_map, as map is (key,value) pair whenever you insert any value in map just set its corresponding value to 1, and then you can check in your map if thats value is already present in map or not if its present then you can tell the user to change, in map it will be easy to search.(code is simple)

Related

C++: Removing a duplicate of the user input in an array

I have been trying to solve this problem since yesterday. The program should accept N numbers from the user and will place them in an array. I have done this. However, I don't seem to know how to "warn" the user that the input is a duplicate and lets the user enter again.
Here is my code:
# include <iostream>
using namespace std;
int main () {
int N, pos = -1, arr [N], i, j;
int startLoop = 1;
// the 'startLoop' variable is used so that the first user input can have the break function
bool found = false;
while (startLoop != 0) {
cout << "Enter the number of integers to be entered: ";
cin >> N;
if (N <= 4) {
cout << "Invalid. \n";
}
if (N > 4) {
cout << "\n\nEnter " << N << " unique numbers: " ;
for (i = 0; i < N; i++) {
cin >> arr [i];
for (j = 0; j < N && !found; j++) {
if (arr [j] == arr [i]) {
found = true;
cout << "Enter again: ";
}
}
break;
}
}
}
The following is the copy paste of your code:
By adding break you will jump out of the outer for loop and you cannot read n inputs.
the inner loop range is not correct since i is the total number of values read by now. i.e. if N= 10 and in third iteration you are trying to loop among 10 elements to double check if the latest number is a duplicate, while you have read 3 elements by now.
if (N > 4) {
cout << "\n\nEnter " << N << " unique numbers: " ;
for (i = 0; i < N; i++) {
cin >> arr [i];
for (j = 0; j < N && !found; j++) {
if (arr [j] == arr [i]) {
found = true;
cout << "Enter again: ";
}
}
break;
}
}
How to fix?
One approach would be to read the input in a separate loop and then try to find the duplicates and remove them.
Time Complexity will be O(n) since you need to traverse through the list twice, however you need to implement removing elements from the array efficiently without shifting all the elements
Second approach is like what you are trying to implement but it is not efficient since every time a user is adding a new elements you need to re-evaluate i numbers (in worst case n numbers when you are filling the end of array). this process should be repeated every time user insert a repeated number.
The best approach would be store all input numbers inside a hash (set) and every-time a new number is inserted check whether it is already suggested by the user or not. Time complexity of searching elements through unordered_set will be O(1)
Problems:
Your code has many several problems:
You shouldn't use VLAs (Variable Length Arrays) as they are non-standard.
Using N before initializing it is UB (Undefined Behaviour).
Your approach is not efficient as it checks on average n/2 elements n times and therefore it has a time complexity of O(n^2).
You have many unused variables and variables that should be in a more specific scope.
Solutions:
Use std::vector insted of VLAs.
Resize the vector after initializing N.
Change your approach.
Change the scope of your variables.
Additional information:
using namespace std; is considered a bad practice (More info here).
You should probably add input checking to std::cin to verify that the input is a number.
Full code:
Checking duplicates once at the end of input with std::vector (Time complexity: O(n * log(n)). Space complexity: O(n)):
#include <iostream>
#include <vector>
#include <algorithm>
bool hasDuplicates(std::vector<int> toCheck)
{
std::sort(toCheck.begin(),toCheck.end());
for(unsigned int i = 1; i < toCheck.size(); i++)
if(toCheck[i] == toCheck[i-1])
return true;
return false;
}
int main () {
std::vector<int> arr;
int N;
while (true) {
std::cout << "Enter the number of integers to be entered: ";
std::cin >> N;
if (N <= 4) {
std::cout << "Invalid: The number of integers to be entered must be bigger than 4. \n";
}
else {
arr.resize(N);
std::cout << "\n\nEnter " << N << " unique numbers: " ;
for (int i = 0; i < N; i++)
std::cin >> arr [i];
if(hasDuplicates(arr))
std::cout << "Invalid: The numbers must be unique. \n";
else
break;
}
}
}
Checking duplicates each time a number is entered with std::unordered_map (Time complexity: Amortized O(n). Space complexity: O(n)):
#include <iostream>
#include <vector>
#include <unordered_set>
int main () {
std::vector<int> arr;
std::unordered_set<int> alreadyAppeared;
int N;
std::cout << "Enter the number of integers to be entered: ";
std::cin >> N;
while (N <= 4) {
std::cout << "Invalid: The number of integers to be entered must be bigger than 4. \n";
std::cout << "Enter the number of integers to be entered: ";
std::cin >> N;
}
arr.resize(N);
std::cout << "\n\nEnter " << N << " unique numbers: \n";
for (int i = 0; i < N; i++)
{
int entering;
std::cout << "Enter unique number: ";
std::cin >> entering;
if(alreadyAppeared.find(entering) == alreadyAppeared.end())
{
alreadyAppeared.insert(entering);
arr[i] = entering;
}
else
{
std::cout << "Invalid: The numbers must be unique. \n";
i--;
}
}
}

How to end a user input array

So this is for a lab assignment and I already have it working, but one thing is bothering me. The assignment involves creating a 1-dimensional array and then manipulating it. I am supposed to allow a max of 100 inputs but the user does not have to use all 100. Right now, I am using a while statement to either break or allow another input to be entered. To break the statement, you have to enter a negative number (this is what I don't like and want to change). What other options are there to end the user input, once they are done entering their numbers? Is it possible to end the loop once you hit enter with nothing typed?
I have searched stackoverflow for the last 3 days and found some compelling stuff but could never get it to work.
Note, I get the void function is redundant here but that's besides the point (unless it actually affects my ability to achieve what I want).
Also, thanks in advance.
here is my code so far (my while statement is in the main)... be kind I'm a newbie to coding.
#include <iostream>
using namespace std;
void reverseElements(int array[], int size)
{
int tmp;
int j;
int i = size;
j = i - 1;
i = 0;
while (i < j)
{
tmp = array[i];
array[i] = array[j];
array[j] = tmp;
i++;
j--;
}
cout << "I will now reverse the elements of the array." << endl;
cout << endl;
for (i = 0; i < size; i++)
{
cout << array[i] << " " << endl;
}
}
int main()
{
const int NUM_ELEMENTS = 100;
int iArr[NUM_ELEMENTS];
int i;
int myInput;
cout << "Enter your numbers, then enter a negative number to finish" << endl;
cout << endl;
for (i = 0; i < NUM_ELEMENTS; i++) //loop to obtain input
{
cin >> myInput;
if (myInput < 0) //checks for negative number to end loop
{
break;
}
else //continues to allow input
{
iArr[i] = myInput;
}
}
cout << endl;
reverseElements(iArr, i);
return 0;
}
Probably the easiest solution: let your user choose how many numbers to write before actually writing them.
int readNumbersCount()
{
int const numbersMin = 1;
int const numbersMax = 100;
int numbersCount = -1;
while (numbersCount < numbersMin || numbersCount > numbersMax)
{
std::cout <<
"How many numbers are you going to enter? Choose from " <<
numbersMin << " to " << numbersMax << ":\n";
std::cin >> numbersCount;
}
return numbersCount;
}
int main()
{
int const numbersCount = readNumbersCount();
for (int i = 0; i < numbersCount; ++i)
{
// read the numbers etc.
}
return 0;
}
I wrote readNumbersCount() as a separate function to extract numbersMin and other "one-use" identifiers from main() and to make main()'s numbersCount const.
I have edited the main function a little bit.
Here the user is asked how many elements he wants to enter .
and doing the memory allocation dynamically so as to save space
int main()
{ int n=101;
while(n>100){
cout<<"How many numbers do you want to enter";
cin>>n;
}
int *ptr=new(nothrow)int[n];
for (int i=0;i<n;i++){
cout << "Enter your number" << endl;
cin>>ptr[i];
}
cout << endl;
reverseElements(ptr, n);
return 0;
}

How to count how many times each number has been encountered?

I am trying to write a program to count each number the program has encountered. by putting M as an input for the number of the array elements and Max is for the maximum amount of number like you shouldn't exceed this number when writing an input in the M[i]. for some reason the program works just fine when I enter a small input like
Data input:
10 3
1 2 3 2 3 1 1 1 1 3
Answer:
5 2 3
But when I put a big input like 364 for array elements and 15 for example for max. the output doesn't work as expected and I can't find a reason for that!
#include "stdafx.h"
#include <iostream>
#include<fstream>
#include<string>
#include <stdio.h>
#include<conio.h>
using namespace std;
int ArrayValue;
int Max;
int M[1000];
int checker[1000];
int element_cntr = 0;
int cntr = 0;
int n = 0;
void main()
{
cout << "Enter the lenght of the Elements, followed by the maximum number: " << endl;
cin >> ArrayValue>> Max;
for (int i = 0; i < ArrayValue; i++)
{
cin >> M[i];
checker[i]= M[i] ;
element_cntr++;
if (M[i] > Max)
{
cout << "the element number " << element_cntr << " is bigger than " << Max << endl;
}
}
for (int i = 0; i < Max; i++)
{
cntr = 0;
for (int j = 0; j < ArrayValue; j++)
{
if (M[n] == checker[j])
{
cntr+=1;
}
}
if (cntr != 0)
{
cout << cntr << " ";
}
n++;
}
}
You have general algorithm problem and several code issues which make code hardly maintainable, non-readable and confusing. That's why you don't understand why it is not working.
Let's review it step by step.
The actual reason of incorrect output is that you only iterate through the first Max items of array when you need to iterate through the first Max integers. For example, let we have the input:
7 3
1 1 1 1 1 2 3
While the correct answer is: 5 1 1, your program will output 5 5 5, because in output loop it will iterate through the first three items and make output for them:
for (int i = 0; i < Max; i++)
for (int j = 0; j < ArrayValue; j++)
if (M[n] == checker[j]) // M[0] is 1, M[1] is 1 and M[2] is 1
It will output answers for first three items of initial array. In your example, it worked fine because the first three items were 1 2 3.
In order to make it work, you need to change your condition to
if (n == checker[j]) // oh, why do you need variable "n"? you have an "i" loop!
{
cntr += 1;
}
It will work, but both your code and algorithm are absolutely incorrect...
Not that proper solution
You have an unnecessary variable element_cntr - loop variable i will provide the same values. You are duplicating it's value.
Also, in your output loop you create a variable n while you have a loop variable i which does the same. You can safely remove variable n and replace if (M[n] == checker[j]) to if (M[i] == checker[j]).
Moreover, your checker array is a full copy if variable M. Why do you like to duplicate all the values? :)
Your code should look, at least, like this:
using namespace std;
int ArrayValue;
int Max;
int M[1000];
int cntr = 0;
int main()
{
cout << "Enter the lenght of the Elements, followed by the maximum number: " << endl;
cin >> ArrayValue >> Max;
for (int i = 0; i < ArrayValue; i++)
{
cin >> M[i];
if (M[i] > Max)
{
cout << "the element number " << i << " is bigger than " << Max << endl;
}
}
for (int i = 0; i < Max; i++)
{
cntr = 0;
for (int j = 0; j < ArrayValue; j++)
{
if (i == M[j])
{
cntr ++;
}
}
if (cntr != 0)
{
cout << cntr << " ";
}
}
return 0;
}
Proper solution
Why do you need a nested loop at all? You take O(n*m) operations to count the occurences of items. It can be easily counted with O(n) operations.
Just count them while reading:
using namespace std;
int arraySize;
int maxValue;
int counts[1000];
int main()
{
cout << "Enter the lenght of the Elements, followed by the maximum number: " << endl;
cin >> arraySize >> maxValue;
int lastReadValue;
for (int i = 0; i < arraySize; i++)
{
cin >> lastReadValue;
if (lastReadValue > maxValue)
cout << "Number " << i << " is bigger than maxValue! Skipping it..." << endl;
else
counts[lastReadValue]++; // read and increase the occurence count
}
for (int i = 0; i <= maxValue; i++)
{
if (counts[i] > 0)
cout << i << " occurences: " << counts[i] << endl; // output existent numbers
}
return 0;
}

Trying to ask a user to provide a set of numbers, then have program determine if the numbers are in ascending order or not?

I am trying to create a program that asks the user for a set of numbers, first asking for the quantity of numbers, then having them input all the numbers. The program then checks the numbers, and determines whether or not the numbers given are in ascending order or not. Then, simply print out "yes ascending" or "no not ascending" and print out the array on one line..So far, my code will just always say that "yes, this is an increasing array!" Please look below for my code. Thanks in advance!..
tested: 1 2 3 4 5 6 --> pass
1 3 5 2 4 6 --> fail (still says it is an ascending array)
#include <iostream>
#include <string>
using namespace std;
bool isAscending(int arr[], int size)
{
for (int i=0; i < size-1; i++)
{
if (arr[i] > arr[i+1])
{
return false;
}
}
return true;
}
int main()
{
int arraysize = 0;
string numbers;
cout << "Enter the size of the array: " << endl;
cin >> arraysize;
if (arraysize < 1)
{
cout << "ERROR: you entered an incorrect value for the array size!" << endl;
}
cout << "Enter the numbers in the array, separated by a space, and press enter: " << endl;
numbers += ' ' + numbers;
cin >> numbers;
int arr[arraysize];
if ( isAscending(arr, arraysize))
{
cout << "This IS an increasing array!" << endl;
}
else
{
cout << "This is NOT an ascending array!" << endl;
}
for (i = 0; i < arraysize - 1; i++)
{
cout << arr[i];
}
return 0;
}
You're reading in "numbers", which you created as type String.
cout << "Enter the numbers in the array, separated by a space, and press enter: " << endl;
numbers += ' ' + numbers;
cin >> numbers;
Your numbers+= line isn't doing anything except adding a space to your numbers string before your cin happens... I know what you're trying to accomplish, and that won't do it.
Then you're suddenly making an array which, without initializing is filled with garbage, and immediately running isAscending on it:
int arr[arraysize];
if ( isAscending(arr, arraysize)){....}
I advise you declare your array before receiving input, read the input line and process it into INTEGERS, and then add each integer to your array. Here is a (crude) correction of the first section of code in your main that just reads in whitespace separated integers and fills the array with them:
int main(){
int arraysize = 0;
int number = 0;
cout << "Enter the size of the array: " << endl;
cin >> arraysize;
if (arraysize < 1) // you should really have this loop until you get correct input
{ cout << "ERROR: you entered an incorrect value for the array size!" << endl; }
int* arr = new int[arraysize];
cout << "Enter the numbers in the array, separated by a space, and press enter: " << endl;
int i = 0;
while(i < arraysize){
cin >> number;
arr[i] = number;
i++;
};
if ( isAscending(arr, arraysize)){ cout << "This IS an increasing array!" << endl; }
else{ cout << "This is NOT an ascending array!" << endl;}
for (int i = 0; i < arraysize; i++){
cout << arr[i];
if( (i+1) == arraysize){ cout << ". ";}
else cout << ", ";
}
return 0;
}
If you're going to whine about somebody giving partial answers that only address the asker's question, maybe you should take the time to write something yourself.

C++ Program Debugging

I seem to be having some problems with my program. It compiles fine, but when I get to my first loop it asks me for a positive integer than it asks me again like its suppose too. Than it hops down a blank space and wont run any further until you enter another number which its not suppose to do. But than when you enter a number it goes back and asks me to enter an integer also like its suppose to the problem is, IT will do this infinite amount of times until I quit the program. Any suggestions as to why this is happening?
/* Search the entries of the n X n matrix mat in rowwise order for an entry to item */
#include <iostream>
using namespace std;
int main(void)
{
int n=10, item, row=3, col=3, mat[row][col];
bool found;
for (int row = 0; row < 3; row++)
for (int col = 0; col < 3; col++)
{
cout << "Enter Positive Integer : ";
cin >> row;
cout << " Enter Positive Integer : ";
cin >> mat[row][col];
}
cout << "Enter a positive integer you want to be searched: ";
cin >> item;
for(int i=0; i<row; ++i)
{
for(int j=0; j<col; ++j)
{
if(mat[row][col] == item)
found = true;
else
found = false;
}
}
if(found==true)
cout << "item found" ;
else
cout << "item found ";
return 0;
}
The line for (int cols = 0; cols < 5; col++) increments the variable col, not cols. Since cols is always 0, the loop will never terminate.
You've done the same in for (int rows = 0; rows < 5; row++). Infinite loops often occur due to typos in loop conditions ;)
I would also like to point out some logic errors during your search:
for(int i=0; i<row; ++i)
{
for(int j=0; j<col; ++j)
{
if(mat[row][col] == item)
found = true;
else
found = false;
}
}
When that loop ends, found will only be true if mat[row-1][col-1] == item (the very last element). Heck, row and col never change in the loop so you are repeatedly checking the exact same element every time! You should also expect even more funky program behavior if you don't get a grasp on your variable names. I strongly recommend adding debug statements to see how your variables are being modified throughout the program (aka: cout << "rows = " << rows << endl;, and cout << "i = " << i << endl;, etc). You're preparing a recipe for disaster when you reuse your variables.
Disclaimer: Reusing variables is not always a bad thing. However, it's best to avoid it until you have a stronger understanding of variables.
In your loop you are incrementing row and col not rows and cols.
It looks to me like you are using the same variable for the loop counter and the user input storage. That is doomed to not do what you want.
Do something like:
for (rowCounter = 0; rowCounter < 3; rowCounter++) {
for (colCounter = 0; colCounter < 3; colCounter++) {
cout << “Give me value for (“ << rowCounter << “,” << colCounter << “) :”;
cin >> mat[rowCounter][colCounter];
}
}
and then the rest of your code
It seems you had a couple of issues.
In the first for loop, you were incrementing the wrong variable (col instead of cols), you also went from 0 to 4 in a 3x3 matrix
you asked the user for 2 numbers then you asked the user to put in a number in the matrix, but its only a 3x3 matrix, the user could easy go out of bounds. I think what you were trying to do was populate the matrix with users number. So i made that change.
In the second for loop, you set found =true, but the loop will keep going, meaning the last number it searched, if it was false, then found = false, also changed it to mat[i][j] instead of mat[row][col], so it doesn't check the same one every time.
both found = true and found = false would return "item found", i think you left off the "not" in the second hard coded string.
I added a pause so you can read the output at the end.
I fixed them and I think this code should do what you want it to now.
#include <iostream>
using namespace std;
int main(void)
{
int n=10, item, row = 3, col = 3;
int mat[3][3];
bool found = false;
int j,k;
for (int rows = 0; rows < 3; rows++)
for (int cols = 0; cols < 3; cols++)
{
cout << "Enter row Integer: ";
cin >>j;
cout << "Enter col Integer: ";
cin >> k;
cout << "Enter Positive Integer : ";
cin >> mat[j][k];
}
cout << "Enter a poistive integer you want to be searched: ";
cin >> item;
int flag = 0;
for(int i=0; i<row; ++i)
{
for(int j=0; j<col; ++j)
{
if(mat[i][j] == item)
{
flag = flag + 1;
}
}
}
if(flag > 0)
found = true;
if(found==true)
cout << "item found" ;
else
{
cout << "item not found ";
}
system("PAUSE");
return 0;
}