I'm trying to use something other than a boolean function - c++

P is one-dimensional array of integers. Write a C++ function to efficiently search for a data VAL from P. If VAL is present in the array then the function should return the position of the value otherwise display the value doesn’t exist.
#include<iostream>
using namespace std;
bool lsearch(int Arr[], int s, int VAL);
int main()
{
int Arr[100],n,val;
bool found;
cout<<"Enter number of elements you want to insert ";
cin>>n;
for(int i=0;i<n;i++)
{
cout<<"Enter element "<<i+1<<":";
cin>>Arr[i];
}
cout<<"Enter the number you want to search ";
cin>>val;
found=lsearch(Arr,n,val);
if(found)
cout<<"\nItem found";
else
cout<<"\nItem not found";
return 0;
}
bool lsearch(int Arr[], int s, int VAL)
{
for(int I=0; I<s; I++)
{
if(Arr[I]==VAL)
return true;
}
return false;
}
I'm asked to use something other than boolean like void found: i tried void with return at end but it does not work

Your requirement is to return the position.so, you can do in the below way.
int lsearch(int Arr[], int s, int VAL)
{
for(int I=0; I<s; I++)
{
if(Arr[I]==VAL)
return I;
}
return -1;
}

You're supposed to return the position of the value, so bool and void are both the wrong choice - it should be an integer of some sort.
Since the position must be a non-negative integer, you can return a signed integer and indicate failure by returning a negative number. (-1 is the "normal" choice, so choose that.)
Then you make the output depend on whether the result is negative or not.
The relevant part of your main would look like
int position = lsearch(Arr,n,val);
if (position >= 0)
{
cout << "Item found at position " << position << endl;
}
else
{
cout << "Item not found" << endl;
}

Related

Is there some way to stop initializing a character array using an appropriate boolean condition inside of an If statement in C++?

I am trying to get a user to populate a character array up to 10 letters, but they should (in theory) be able to stop entering letters at any time. Said differently, if a user wants to only enter 5 letters, they should be able to.
My question is how can I use some sort of expression structure like if-else branches to exit the for loop shown below that initializes and populates the array?
#include <iostream>
const int DECLARED_SIZE = 10; //max size of an array in the main
void fillUpArray(char array[], int size, int& actual_size);
void reverseArray(char array[], int actual_size);
int main()
{
char letters[DECLARED_SIZE];
int actualSize;
fillUpArray(letters, DECLARED_SIZE, actualSize);
reverseArray(letters, actualSize);
}
void fillUpArray(char array[], int size, int& actual_size) //here is where my question is!
{
int index;
char letter;
std::cout << "Enter up to " << size << " letters. Enter something the loop to stop\n";
for(index = 0; index < size; index++)
{
std::cin >> letter;
if(letter == something that stops this loop)
break;
else
array[index] = letter;
}
actual_size = index;
}
void reverseArray(char array[], int actual_size)
{
int index;
for(index = actual_size; index >= 0; index--)
{
std::cout << array[index] << "\t";
}
std::cout << std::endl;
}
Okay, so I used a period '.' inside the if statement inside the function fillUpArray(), but why does a period character work and not say something like a number?

How is the pointer (*) making changes in the following code?

The following program is intended to check if a given element is in a given array, indices of array where the element occurs and number of times the element occurs. But, it doesn't give right results. I tried to replace poscount in seqsearch function with *poscount and did further changes for this pointer data type. Then the code works well. Why this is so?
#include <iostream>
using namespace std;
const int SIZE = 100;
void seqsearch(int[], int, int, int[], short);
int main() {
int array[SIZE], indices[SIZE];
int num, value;
short count = 0;
cerr << " Give number of elements in array : ";
cin >> num;
cerr << " Key in the array elements ";
for(int i = 0; i < num; i++) cin >> array[i];
cout << endl;
cerr << " Give the value to be searched : " << endl;
cin >> value;
cout << endl;
seqsearch(array, num, value, indices, count); // void function
if(count >= 0) {
cout << value << " found in array " << count << " times"
<< " at index positions " << endl;
for(int i = 0; i < count; i++) cout << indices[i] << " ";
cout << endl;
} else
cout << value << " not found in array " << endl;
return 0;
}
void seqsearch(int arr[], int size, int elm, int pos[], short poscount) {
int i, item;
poscount = 0;
for(i = 0; i < size; i++) {
if(arr[i] == elm) {
pos[poscount] = i;
poscount = poscount + 1;
}
}
return;
}
The function seqsearch is supposed to return the result in pos and poscount, but the function takes poscount by-value which means that any changes you make to poscount inside the function, will be local to the function and not visible from the call site.
If you change the function to take the argument by-reference, the changes you make inside the function will actually be made to the variable used in the call to the function. Like this:
seqsearch(int arr[], int size, int elm, int pos[], short& poscount) // note short&
The int pos[] does not have the same problem because arrays decay into pointers, so it could have been int* pos instead - and that pointer points at the same array that you passed in at the call site.
Also note that the check after the call will make the program display "found in array" even if it isn't found in the array because the condition checks if count is zero or greater than zero.
if(count >= 0) { // should be if(count > 0) {
Suggestions unrelated to the problem in your question:
When the number of elements is not known at the time you compile your program, prefer to use a container which can grow dynamically, like a std::vector<int>. In your program you have a hardcoded limit of SIZE number of elements, but:
You will rarely use all of them.
You do not check if the user wants to enter more than SIZE elements and your program will gladly try to write out of bounds - which would cause undefined behavior.
Divide the program's subtasks into functions. It'll be easier to search for bugs if you can test each individual function separately.
Check that extracting values from std::cin actually succeeds.
int number;
if(std::cin >> number) { /* success */ } else { /* failure */ }
Check that the values entered makes sense too.
int wanted_container_elements;
if(std::cin >> wanted_container_elements && wanted_container_elements > 0) {
/* success */
} else {
/* failure */
}
poscount (or count in the context of the caller) in your code seems to be expected to be an output parameter.
To modify the passed value you must either have its address (a pointer) or a reference to the value.
Currently you are using "pass-by-value", meaning that poscount is a copy of count.
The original count stays untouched.
My personal favorite would be to return the value instead of using an out-parameter:
short seqsearch(int arr[], int size, int elm, int pos[]) {
int i, item;
short poscount = 0;
for(i = 0; i < size; i++) {
if(arr[i] == elm) {
pos[poscount] = i;
poscount = poscount + 1;
}
}
return poscount;
}
count = seqsearch(array, num, value, indices);
Alternatively you can use a reference to manipulate the out-parameter:
void seqsearch(int arr[], int size, int elm, int pos[], short& poscount) {
int i, item;
poscount = 0;
for(i = 0; i < size; i++) {
if(arr[i] == elm) {
pos[poscount] = i;
poscount = poscount + 1;
}
}
return;
}
seqsearch(array, num, value, indices, count);
And, as you already tried, you can also solve this by passing a pointer to the value:
void seqsearch(int arr[], int size, int elm, int pos[], short* poscount) {
int i, item;
*poscount = 0;
for(i = 0; i < size; i++) {
if(arr[i] == elm) {
pos[*poscount] = i;
*poscount = *poscount + 1;
}
}
return;
}
seqsearch(array, num, value, indices, &count);
When you pass your posscount argument, you pass a copy to the count variable in main, not the variable itself. That's why it works, when you pass it by pointer. You can also pass by reference. https://www.includehelp.com/cpp-tutorial/argument-passing-with-its-types.aspx

If statement is not accessing the value of an array (using the index) when evaluating the expression

I am supposed to be creating a program that asks a user to populate an array of size 10. There are three functions which by their name are self-explanatory; one fills up the array with elements, the second one displays the array horizontally, and the third function checks to see if a number entered by the user is an element in the array.
#include<iostream>
#include<iomanip>
void fillUpArray(int array[], int size);
void displayArray(int array[], int size);
bool isNumberPresent(int array[], int size, int SearchNum);
int main(){
int s = 10; //size of array
int A[s]; //array A with size s
int num; //search number
fillUpArray(A, s);
std::cout <<"\n";
displayArray(A, s);
std::cout << "\n";
std::cout << "Enter a number to check if it is in the array:\n";
std::cin >> num;
std::cout << std::boolalpha << isNumberPresent(A, s, num) << std::endl;
return 0;
}
void fillUpArray(int array[], int size)
{
std::cout << "Enter 10 integers to fill up an array, press enter after every number:\n";
for(int i = 0; i < size; i++){
std::cin >> array[i];
}
}
void displayArray(int array[], int size)
{
for(int j = 0; j < size; j++){
std::cout << array[j] << "\t";
}
}
bool isNumberPresent(int array[], int size, int SearchNum)
{
bool isPresent;
for(int k = 0; k < size; k++){
if(array[k] == SearchNum)
isPresent = true;
else
isPresent = false;
}
return isPresent;
}
That last function, which is a bool function, is not performing the way I thought it would. I thought by doing array[k] whatever index k is then it should spit out the element in the array and then with the expression if(array[k] == SearchNum) it should then work as if(element == SearchNum) but that doesn't seem to be the case and the output is always false.
The for loop in your isNumberPresent function will run to the end of the array (until k equals size) unconditionally; in each run of that loop, you set the value of the isPresent variable according to whether or not the current element is a match for searchNum, overwriting the previous value. So, the function, as it stands, will simply return whether or not the last element in the array is the same as the given test number.
You can simplify that function and remove the need for the local variable: if you find a match, then return true immediately; if the loop ends without finding a match, then return false:
bool isNumberPresent(int array[], int size, int SearchNum)
{
for(int k = 0; k < size; k++){
if(array[k] == SearchNum) return true; // Found a match - we can return immediately
}
return false; // We didn't find a match
}
Note, also, that Variable Length Arrays (VLAs) are not part of Standard C++, though some compilers (like GNU g++) support them (they are part of the C language according to the C99 Standard). In your program, as you only use one (fixed) value for the array size, you can conform to Standard C++ simply by qualifying that s is a const:
int main()
{
const int s = 10; //size of array - make this a "const" be 'proper' C++
int A[s]; //array A with size s
//...

How to count duplicated numbers in a sorted array

I am trying to finish a problem where I read a file into the program and output a file with the average, min, max, and the count of how many times that number occurred in the program. However, I cannot figure out how to create an array for duplicated number of the "counts".
If the file that I was trying to read in had the values 19 5 26 5 5 19 16 8 1,
I need the outputted file to read 5---3 times; 8---1 time; 16---1 time; 19--2 times; 26--1 times.
I first sorted my array to read 5 5 5 8 16 19 19 26.
Below is my code with explanations of what I was trying to do:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
using namespace std;
double averageArray(int a[], int length); // user defined function to get average
int maxval(int a[], int length); //user defined function to get max val
int minval(int a[], int length); //user defined function to get min val
void bsort(int arr[], int length);// udf to sort array from min to max
int countArray(int a[], int length); //attempt to create a function to get the number of occurrences of a number that is duplicated
int main()
{
char infilename[16];
int nums[50];//newly created array to read in the numbers from the file
int length(0);//array has a length defined by "length"
ifstream fin;
ofstream fout;
cout << "Please enter an input file name: ";
cin >> infilename;
cout << endl;
fin.open(infilename);
if (fin.fail())
{
cerr << "The file " << infilename << " can't be open!"<<endl;
return 1;
}
cout<<"The output to the file statistics.txt should be as follows: "<<endl;
fout.open("statistics.txt");
fout<<"N"<<"\t"<<"Count"<<endl;
cout<<"N"<<"\t"<<"Count"<<endl;
while (fin >> nums[length])
length++;
bsort(nums, length);
for (int i=0; i<length; i++) {
if (nums[i]==nums[i-1]) {
continue;
}
cout<<nums[i]<<"\t"<<countArray(nums,length)<<endl;
fout<<nums[i]<<"\t"<<endl;
}
cout << "\nAverage: " << averageArray(nums,length) << endl;
cout << "Max: "<< maxval(nums,length)<<endl;
cout << "Min: "<< minval(nums,length)<<endl;
fin.close();
return 0;
}
double averageArray (int a[], int length)
{
double result(0);
for (int i = 0; i < length ; i++)
result += a[i];
return result/length;
}
int maxval(int a[], int length)
{
int max(0);
for (int i=1; i<length; i++)
{
if (a[i]>max)
max=a[i];
}
return max;
}
int minval(int a[], int length)
{
int min(100);
for (int i=1; i<length; i++)
{
if (a[i]<min)
min=a[i];
}
return min;
}
void bsort(int a[], int length)
{
for (int i=length-1; i>0; i--)
for (int j=0; j<i; j++)
if (a[j]>a[j+1])
{
int temp=a[j+1];
a[j+1]=a[j];
a[j]=temp;
}
}
int countArray(int a[], int length)
{
int counter(0);
for (int i=0; i<length; i++){
if (a[i]==a[i+1]) //loop through array and if the number after is the same as the previous number, then count one
counter++;
}
return counter;
}
Though it compiles, the count only shows "3"s as shown in the picture below:
.
Before I give you the solution, please take a moment to remember, you are programming in C++, not C. As such, you ought to use vectors, istream iterators and std::sort. You also ought to use std::map, which easily accomplishes this purpose:
template <typename It>
std::map<int, int> count_occurrences(It it, It end)
{
std::map<int, int> output;
while (it != end) output[*it++]++;
return output;
}
How to combine this with your existing code is left as an exercise for the reader. I suggest you ought to read about iterators.
Your function int countArray(int a[], int length) has no input for the actual number. It always counts how often there are the same numbers behind each other in your array. That happens two times for fives and once for 19 => 3 times.
Solution:
int countArray(int a[], int length, int num)
{
int counter(0);
for (int i=0; i<length; i++){
if (a[i]==num) //loop through array and if the number is the one you are looking for
counter++;
}
return counter;
}
and call you function: countArray(nums, length, nums[i]);
void countArray(int a[], int length)
{
int counter(1);
bool flag(false);
//you take (i+1) index, it can go out of range
for (int i = 0; i < length - 1; i++){
if (a[i]==a[i+1]){ //loop through array and if the number after is the same as the previous number, then count one
flag = true;
counter++;
}
else {
if (flag){
cout<<a[i] << counter << endl;
}
flag = false;
counter = 1;
}
}
}
I didn't code on C for a long time, but I hope it'll help.
This procedure will print you the answer, and you have to call it just once.
I suggest to use std::map which is the best solution to solve your problem. I will try to explain easily the differents steps to do this:
I consider your variables initialized, for instance:
int length = 9;
int nums[length] = {19, 5, 26, 5, 5, 19, 16, 8, 1};
Create the std::map<int,int>, where the key (first int) will be your number and the value (second int) the number of occurence of this number store in the key.
std::map<int,int> listNumber;
Fill your map
// For all numbers read in your file
for(int i=0; i<length; ++i)
{
// Get number value
int n = nums[i];
// Find number in map
std::map<int, int>::iterator it = listNumber.find(n);
// Doesn't exists in map, add it with number of occurence set to 1...
if(it == listNumber.end())
{
listNumber.insert(std::pair<int,int>(n,1));
}
// ... otherwise add one to the number of occurence of this number
else
{
it->second = it->second+1;
}
}
Read the map
// Read all numbers and display the number of occurence
std::cout << "N" << "\t" << "Count" << std::endl;
for(std::map<int, int>::iterator it = listNumber.begin(); it!=listNumber.end(); ++it)
{
std::cout << it->first << "\t" << it->second << std::endl;
}

Causing push_back in vector<int> to segmentaion fault on what seems to be simple operation

I'm working on a program for Project Euler to add all the digits of 2^1000. So far I've been able to track the program segmentation faults when it reaches around 5 digits and tries to push a one onto the vector at line 61 in the function carry().
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class MegaNumber
{
vector<int> data; //carries an array of numbers under ten, would be char but for simplicity's sake
void multiplyAssign(int operand, int index); //the recursive function called by the *= operator
void carry(int index);//if one of the data entries becomes more than ten call this function
public:
void printNumber(); //does what it says on the can
void operator*=(MegaNumber operand);
void operator*=(int operand);
void operator+=(int operand);
MegaNumber(string);
unsigned long int AddAllDigits();//returns the value of all of the digits summed
};
MegaNumber::MegaNumber(string operand)
{
for(int i= operand.size()-1; i>=0;i--) //run it into the memory smallest digit first
{
data.push_back(operand[i]-48); //converts a text char to an int
}
}
void MegaNumber::printNumber()
{
int temp = data.size();
for(unsigned int i=(temp); i>0;--i)
{
cout << (int)data[i-1];
}
}
void MegaNumber::operator*=(int operand)
{
if(operand > 9)
{
cout << "function does not yet deal with large ints than 9";
}
else multiplyAssign(operand, 0);
}
void MegaNumber::multiplyAssign(int operand, int index)
{
data[index] *=operand;
if(index<data.size()) multiplyAssign(operand, index+1);
if(data[index] > 9) carry(index);
}
void MegaNumber::carry(int index)
{
int temp = (data[index] / 10); //calculate the amount to carry
if(data.size()==index+1)
{
data.push_back(temp);//if there is no upper digit push it onto the stack
}
else
{
data[index+1]+=temp; //else add it to the next digit
if(data[index+1]>9) carry(index+1); //rinse and repeat
}
data[index]-=temp*10; //remove what's been carried
}
unsigned long int MegaNumber::AddAllDigits() //does what it says on the can
{
unsigned long int Dagger = 0;
for(int i=0; i<data.size();i++) Dagger+=data[i];
return Dagger;
}
int main()
{
MegaNumber A("2");
A.printNumber();
cout << "\n";
for(unsigned int i=0; i<20; i++) A*=2;
A.printNumber();
cout << "\n";
cout << A.AddAllDigits() << "\n";
cout << "Hello world!" << endl;
return 0;
}
What may be causing this?
You use data[index] before checking if it's a valid index, in multiplyAssign:
data[index] *= operand;
if(index<data.size()) multiplyAssign(operand, index+1);
Also use '0' instead of 48. This is easier, clearer, and less bug-prone.
void MegaNumber::multiplyAssign(int operand, int index)
{
data[index] *=operand;
if(index<data.size()) multiplyAssign(operand, index+1);
if(data[index] > 9) carry(index);
}
index is 0 based, while data.size() is 1 based so to say, meaning data.size() returns number 1 greater than the largest valid index.
So looks like you intention was
if( index < data.size() - 1) multiplyAssign(operand, index+1);
Then it works.
P.S. break your code into lines, whoever has to maintain your code will thank you for that:
if (index < data.size() - 1)
{
multiplyAssign(operand, index + 1);
}
I think the problem could be here: data[index+1]+=temp;
This element could not be exist if index parameter eq. to size of data.
So, my recommendations:
Use Iterators to access std::vector
Check bound conditions if you do not use Iterators