I am trying to make functions to call in the main function, trying to keep "main" as clean as possible.
so I made a function to get the size array from the user then the user enters the elements of the function, but I got stuck at the linear search function, so want help "Still absolute beginner"
#include <iostream>
using namespace std;
int* Array_Elements () {
static int arr [5] {}, i, size;
cout << "Enter Array size: ";
cin >> size;
cout << "Enter Array Elements: " << endl;
for (i=0; i<size; i++) {
cin >> arr[i];
}
return arr;
}
void Array_Search (int arr [], int n) {
int temp = -1;
for (int i = 0; i < 5; i++) {
if (arr [i] == n) {
cout << "Element found at position: " << i + 1 << endl;
temp = 0;
break;
}
}
if (temp == -1) {
cout << "No Element Found" << endl;
}
}
int num () {
cout << "Please enter an element to search" << endl;
int num;
cin >> num;
return num;
}
int main () {
Array_Search (Array_Elements(), num());
return 0;
}
... trying to keep "main" as clean as possible.
Ok, thats a good motivation. Frankly, I find your main rather confusing. You try to do 3 seperate steps in one line and probably tripped over unspecified evalutation order of the function parameters. I have to admit, I don't remember if or in what version of C++ the order of evaluation of function parameters is specified. And I suggest you to not even try to remember it. Instead write code that does seperate steps in seperate steps.
Your main could look like this:
int main() {
auto arr = Array_Elements();
int number = num();
Array_Search(arr,number);
}
Even without a definition of Array_Elements(), num() or Array_Searcher one can get a rough idea of the three steps made here.
Next, global state is not clean. Your Array_Elements () cannot reasonably be called twice:
int* first_array = Array_Element();
int* second_array = Array_Element();
Both pointers would point to the same arr. The second call to Array_Element will overwrite what the first call assigned.
static int arr [5] {} as workaround to passing arrays around is a hack. It isn't the right way to solve that problem. Sloppy speaking it isn't any cleaner than a sphagetti main.
Use std::array when you want a stack allocated array with size known at compile time and std::vector for dynamic arrays. They can be passed between functions and you need not keep track of the size seperate from the array:
std::vector<int> Array_Elements() {
std::cout << "Enter Array size: ";
unsigned size = 0;
std::cin >> size;
std::vector<int> result(size);
std::cout << "Enter Array Elements: \n";
for (auto& element : result){
std::cin >> element;
}
return result;
}
The loop is a range based for-loop. In a nutshell, it iterates all elements in result and element is a reference to the elements.
Get acustomed to standard algorithms. They aren't doing something that you could not write yourself. Though, they help to write cleaner code, because instead of having several lines of code that all deal with one thing, "find an element", we can have one function call with a meaningful name: std::find.
void Array_Search(const std::vector<int>& arr,int n){
auto it = std::find(arr.begin(),arr.end(),n);
if (it == arr.end()) {
std::cout << "No Element Found\n";
} else {
std::cout << "Element found at position: " << (it - arr.begin()) << "\n";
}
}
In case the element was not found it returns the end iterator. When it does find the element we can calculate the index from an iterator by subtracting the begin iterator.
Live Demo
Lets jump right in, my suggestion to keep the main as clean as possible is to use a class then instantiate its object then use the object to call class methods in the main. This is best practice.
Your code confuses the compiler, in that the function num() precedes the function Array_Elements() in terms of order of evaluation. And I believe you want it the other way around.
Here's how to fix it: Remove the function num(), and make the following changes to your code
int* Array_Elements(int size) {
int* arr, i;
cout << "Enter Array Elements: " << endl;
arr = new int[size];
for (i=0; i<size; i++) {
cin >> arr[i];
}
return arr;
}
void Array_Search (int *arr, int size) {
int temp = -1, num;
cout << "Please enter an element to search" << endl;
cin >> num;
for (int i = 0; i < size; i++) {
if (arr [i] == num) {
cout << "Element found at position: " << i + 1 << endl;
temp = 0;
delete [] arr;
break;
}
}
if (temp == -1) {
cout << "No Element Found" << endl;
}
}
int main () {
int size;
cout << "Enter Array size: ";
cin >> size;
Array_Search(Array_Elements(size),size);
return 0;
}
Related
This is a linear search algorithm and I am a newbie programmer....Why is the "return i" statement not returning i (printing it on console)?? Is it because the computer considers this as "end the program successfully" because the value of i > 0 (I mean is it acting like "return 0" statement??) how to solve this issue??
#include <iostream>
int linearSearch(int n, int arr[], int num);
int main() {
int n, num, arr[n];
std::cout << "Enter Array Size: ";
std::cin >> n;
std::cout << "Enter Array: ";
for(int i = 0; i < n; i++) {
std::cin >> arr[i];
}
std::cout << "Enter Num to Search in Array: ";
std::cin >> num;
linearSearch(n, arr, num);
}
int linearSearch(int n, int arr[], int num) {
for(int i = 0; i < n; i++) {
if(arr[i] == num) {
std::cout << "Found at Index: ";
return i; //this should return index i but program ends before printing i to console
}
}
std::cout << "...Not Found...";
return -1;
}
Why is the "return i" statement not returning i (printing it on console)??
Thats a misunderstanding common among beginners. Returning something from a function and printing something to the console are two different things.
Not every value you return from a function will be displayed on the console. If you use other languages with an interpreter you may be used that the result of all statements appears on the console. But you aren't running an interpreter.
In your function
return i;
is completely fine to return the value. It does work!
In your main
linearSearch(n, arr, num);
You call the function and ignore the returned value. If you want the value returned from the call to appear on the console you need to write code for that. For example:
int x = linearSearch(n,arr,num);
if (x != -1) std::cout << "index = " << x;
You have to write std::cout << linearSearch(n, arr, num); as last line in your main function.
When you found the index, you forgot to print the output to the console:
if(arr[i] == num) {
std::cout << "Found at Index: ";
return i; //this should return index i but program ends before printing i to console
}
And since you didn't instruct it to print, it doesn't print ;-)
This should do the job:
if(arr[i] == num) {
std::cout << "Found at Index: " << i << std::endl;
return i; //this will return index i after printing it to the console
}
Btw, you can't allocate the neccessary memory for arr when you don't know the size.
int n, num, arr[n]; // you don't know the size
std::cout << "Enter Array Size: ";
std::cin >> n;
you need to re-arrange it and allocate dynamically once you know the size (and delete once it is no longer used):
int n, num;
std::cout << "Enter Array Size: ";
std::cin >> n;
*arr = new int[n];
int main() {
int n, num;
std::cout << "Enter Array Size: ";
std::cin >> n;
*arr = new int[n];
...
linearSearch(n, arr, num);
delete arr;
}
#include <iostream>
#include <array>
#include <algorithm>
void *swap(int arr[], int size);
void *swap(int arr[], int size) {
int i,j,temp;
for(int i{0}; i < size; i++) {
for(int j{i+1}; j < size; j++) {
if(arr[i] > arr[j]) {
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
std::cout <<"The numbers in ascending order are: ";
for(int i{0}; i < size; i++)
std::cout << arr[i] << " ";
}
void average_score(int arr[], int size);
void average_score(int arr[], int size) {
int average {0};
for(int i{0}; i < size; i++) {
average+=arr[i];
}
std::cout << "\nThe average is: " << average / size << std::endl;
}
int main() {
int *test_scores = nullptr;
int n;
std::cout <<"Enter Size: ";
std::cin >> n;
test_scores = new int[n];
int i = 0;
int student_scores;
while(i < n) {
std::cout << "Enter Student " << i+1 << " Test Score: ";
std::cin >> student_scores;
test_scores[i] = student_scores;
i++;
}
swap(test_scores,3);
average_score(test_scores,3);
}
The assignment is also asking me to instead of stepping through the arrays, use pointers rather than array subscripts. I have already created a program where it takes in the test scores and calculates the average and sorts it into ascending order, now I just need to create a display of the student's name right next to their score. Any thoughts or helpful advice that I can use to help me build this program?
In C++ you have a data container called struct that may help you with that. (You can also use classes, but I don't think they are necessary here).
A possible struct for this problem may be declared like this:
struct student {
int grade;
string name;
};
In your main program you could change the test_scores array for a vector, which is more helpful as its size can be modified.
std::vector<student> test_scores(n);
If you want to access the attributes of your student struct you would do so by using the dot operator.
int a = test_scores[0].grade;
string s = test_scores[0].name;
You are given this error because you try to add an int into a student vector. "no matching function call" means that the compiler does not know how to transform the integer into a student. To fix it, I recommend you to ask for the name instead of only asking for the score, so you may add the following code:
student s;
for (int i = 0; i < n; ++i) {
std::cout << "Enter Student " << i+1 << " Name and Test Score: " << endl;
std::cin >> s.name >> s.grade;
test_scores[i] = s; // Don't use test_scores.push_back(s) here, if you do so,
// you would increase its size by 1 and add the element s at the end of the vector.
}
In your average_score function, you should change the int arr[] parameter for a vector <student> &arr and average += arr[i] for average += arr[i].score. The & in &arr is important because it passes the parameter as reference so that its elements are not copied into the function, which is very unnefficient.
Your swap function should be void instead of void *. Also, try using the sort function of the algorithm library. The sorting code you implemented has quadratic cost over the vector length, which is very unefficient if you have a lot of students.
The strange problem appears in my program. It is working, but in debugging it shows the "Exception thrown" in random places at the outputting
cout<<"Average value:"<<u3.apr();
_getch();
Sometimes, it even throws this error after the main function (Behind the {})
It is quite annoying because the program just closes after 3 seconds because of these errors.
(Maybe that's because of class, but I'm trying to learn it ;) )
Have tried already changing lines order, rewriting class name and array name.
#include <iostream>
#include <conio.h>
using namespace std;
class vid
{
private:
int i, j;
double rez, sum=0;
public:
int size;
double *arr = new double[size];
double apr()
{
for (i = 0; i < size; i++)
{
sum += (*(arr + i));
}
return sum / size;
}
};
int main()
{
vid u3;
cout << "Enter array length:";
cin >> u3.size;
for (int i = 0; i < u3.size; i++)
{
cout << "Enter array's " << i << " element:" << endl;
cin >> *(u3.arr+i);
}
cout << "Your array:" << endl;
for (int i = 0; i < u3.size; i++)
{
cout << *(u3.arr + i) << "\t";
}
cout << endl;
cout<<"Average value:"<<u3.apr();
_getch();
}
Thanks for any help ;)
arr is initialised when u3 is constructed.
But you didn't populate u3.size until later.
So, your array has indeterminate length (which is already UB), and your accesses later may be invalid.
You're going to have to manage your class's member a bit more cleverly!
Such classes generally have a "resize" function that performs the allocation per the requested size. Don't forget to safely kill any prior allocation, transplanting data if necessary. You can find online plenty of examples of a vector implementation.
Certainly renaming classes and randomly re-ordering the lines of your program's source code is not going to solve anything.
u3.size is not set until after u3 is constructed. By setting u3.size you can avoid this compiler-time error.
It seems that as an alternative solution, you might want to consider how to get rid of the new call and the need to write a destructor that will delete arr.
By creating a constructor that takes a size parameter AND by switching arr to a std::vector, you can allow the class to hold the vector and handle memory allocation and deallocation:
#include <iostream>
#include <vector>
using namespace std;
class vid
{
private:
int i, j;
double rez, sum=0;
public:
int size;
std::vector<double> arr;
// constructor requires size to be passed in;
// constructor initializes the arr array with the passed in size to zeroes.
vid(int argSize) : size(argSize), arr(argSize, 0.0){ }
double apr()
{
for (i = 0; i < size; i++)
{
sum += arr[i];
}
return sum / size;
}
};
int main()
{
uint size;
cout << "Enter array length:";
cin >> size;
vid u3(size);
for (int i = 0; i < u3.size; i++)
{
cout << "Enter array's #" << i << " element:" << endl;
cin >> u3.arr[i];
}
cout << "Your array:" << endl;
for (int i = 0; i < u3.size; i++)
{
cout << u3.arr[i] << "\t";
}
cout << endl;
cout<<"Average value:"<<u3.apr();
char ch;
cin >> ch;
}
So I have written a function that should simply add the values of each element stored in two separate arrays, and save them to a third array.
I don't understand what the issue is, I am simply adding together the value of the int stored at the location referenced by each of my pointers, and saving it to my third, empty, array.
My code compiles just fine, but when I loop to print the contents of my third array (which should contain the sum of the two previous arrays elements at their respective indexes) it just prints a bunch of memory addresses. What gives?
EDIT: I fixed my while loop to perform the arithmetic, and everything is working well. My working code is below. Hope it helps someone else.
#include<iostream>
#include<stdlib.h>
using namespace std;
void arrayAdd(int firstArray[], int secondArray[], int targetArray[], int size){
int *firstPtr = firstArray;
int *secondPtr = secondArray;
int *tragetPtr = targetArray;
while (firstPtr <= &firstArray[size - 1] ){
//add the first two array elements
*tragetPtr = (*firstPtr + *secondPtr);
// point to the next location
*firstPtr++;
*secondPtr++;
*tragetPtr++;
}
}
int main() {
int totalElements;
const size_t ARRAY_SIZE = 50;
int firstIntegerArray[ARRAY_SIZE];
int secondIntegerArray[ARRAY_SIZE];
int thirdIntegerArray[ARRAY_SIZE];
cout << "Please enter the total number of elements for your array: ";
cin >> totalElements;
for(int i = 0; i < totalElements; i++){
cout << "Please enter a value for the first array at index " << i << ": ";
cin >> firstIntegerArray[i];
}
for(int i = 0; i < totalElements; i++){
cout << "Please enter a value for the second array at index " << i << ": ";
cin >> secondIntegerArray[i];
}
//run our arrayAdd function
arrayAdd(firstIntegerArray, secondIntegerArray, thirdIntegerArray, totalElements);
cout << "The conents of your two arrays added together is; " << endl;
for(int i = 0; i < totalElements; i++){
cout << thirdIntegerArray[i] << ", ";
}
return 0;
}
A local array decays to a pointer when it is passed to a function, so you can't use sizeof on it anymore. Indeed this:
void arrayAdd(int firstArray[]) {
int *firstPtr = firstArray;
std::cout << "sizeof(firstArray) == " << sizeof(firstArray) << std::endl;
std::cout << "sizeof(firstPtr) == " << sizeof(firstPtr) << std::endl;
}
int main() {
int test[] = {1,2,3,4,5,6,7,8,9,0};
arrayAdd(test);
return 0;
}
Prints:
sizeof(firstArray) == 8
sizeof(firstPtr) == 8
on my 64 bit machine.
Casting int[] to int* doesn't change anything since it already became a pointer as an argument. You should pass the size of the array to the method or, since you are working with C++, use an std::array or std::vector which will just solve any problem.
I wrote a program for my assignment that involves pointers and dynamic allocation for an array, I am getting a runtime error and the program crashes, there are no compiling errors. Here is the program :
array.h :
#include <iostream>
using namespace std;
void readArray(float*, int &);
void PrintArray(float*, int);
array.cpp :
#include "array.h"
void readArray(float* array, int &size)
{
array = new float[size];
cout << endl;
cout << "Enter the array elements, use spaces: ";
for (int i = 0; i < size; i++)
{
cin >> array[i];
}
cout << endl;
}
void PrintArray(float * array, int size)
{
for (int i = 0; i < size; i++)
{
cout << array[i] << " ";
}
cout << endl;
}
main.cpp :
#include "array.h"
int main()
{
int size = 0;
cout << "How many elements would you like to enter? ";
cin >> size;
cout << endl;
float *array = NULL;
readArray(array,size);
cout << "The array size is " << size << endl;
PrintArray(array, size);
return 0;
}
Sample Output :
How many elements would you like to enter? 3
Enter the array elements, use spaces: 4.0 5.0 6.0
The array size is 3
Crashes here
Can someone let me know what the problem is with the PrintArray function?
The parameter array of readArray() is passed by value, so array in main() remains NULL even if you changed it in readArray(). To make it be passed by reference. In addition, size doesn't need be passed by reference.
change
void readArray(float* array, int &size)
to
void readArray(float*& array, int size)
Q: Can someone let me know what the problem is with the PrintArray function?
A: Your PrintArray function is fine.
The problem is that you never pass the array you've allocated outside of readArray.
BETTER:
float *
readArray(int size)
{
float* array = new float[size];
cout << endl;
cout << "Enter the array elements, use spaces: ";
for (int i = 0; i < size; i++)
{
cin >> array[i];
}
cout << endl;
return array;
}
int main()
...
float *array = readArray(size);
...
NOTES:
If you declared a prototype for readArray() in array.h, you'll need to update it.
There are many ways to accomplish this, but the basic problem is you need ** (a pointer to a pointer) instead of * if you allocate your array inside the function. I believe passing the array pointer back as a function return is arguably the cleanest solution.
IMHO...