Passing dynamic arrays to recieve inputs in separate functions - c++

I would like to pass dynamic arrays to functions and receive user input. Currently I'm using the following code:
#include <iostream>
using namespace std;
struct make
{
int part;
int graph;
int like;
};
int z;
int *p = new int [z];
void inpart( make x[],int *fig)
{
cout << "Input part\n";
cin >> x[*fig].part;
}
void ingraph(make x[],int *tig)
{
cout << "Input graph\n";
cin >> x[*tig].graph;
}
void inlike(make x[],int *gig)
{
cout << "Input like\n";
cin >> x[*gig].like;
}
int main()
{
cout << "Input array count\n";
cin >> z;
make p[z];
for (int i=0; i < z; i++)
{
inpart(p,&z);
ingraph(p,&z);
inlike(p,&z);
}
for (int i=0; i < z; i++)
{
cout << "the result is\n";
cout << p[z].part << ", ";
cout << p[z].graph << ", ";
cout << p[z].like << "\n";
}
}
My input 1,1,1 for all the structure objects should output 1,1,1. However, the answer I receive is 1,0,2. Why?

Firstly, you shouldn't trying to initialize a static buildin array in run-time:
Your implementation is wrong here:
cout<< "Input array count\n";
cin>>z;//initialized in run-time
make p[z]; // wrong, need to be allocated with new
make* example = new make[z]; // Ok!
Secondly, you're trying to read and write out of bounds of the created array. It's Undefined behaviour. When you're creating an array with size N, chunk of the memory will be allocated to which you can have access by index. In your case from 0 to z or [0,z), excluding z. To sum up, your cycle should look like this:
for (int i = 0; i < z; i++) {
inpart(p,&i);
ingraph(p,&i);
inlike(p,&i);
}
Actually u've made a lot of mistakes in your code, but I feel like you will understand this later when continue learning.

Related

C++ can't call same function twice with different parameters

I have a C++ program that calls the same function tempGauge() twice. It hits the first call then skips the second call and goes to userData() and gives me the error "finished with exit code 6". when I comment out the first call the second call works as expected and ends with the exit code 0.
int tempGuage(int &array, int &actDay);
void userData();
int main() {
const int totalTemp(10);
int firstDay[totalTemp];
int secondDay[totalTemp];
int dayOne = 1;
int dayTwo = 2;
tempGauge(firstDay[totalTemp], dayOne);
tempGauge(secondDay[totalTemp], dayTwo);
userData();
return 0;
}
int tempGauge(int &array,int &actDay)
{
int i;
int maxTemps;
for(i=1;i < maxTemps;++i)
{
cout << "Enter # of temps on DAY " << actDay <<":";
cin >> maxTemps;
if(maxTemps <=0||maxTemps>=11)
{
cout << "Enter at least 1 but no more than 10. Try again.";
}
else
{
cout << "Enter the " << maxTemps << " temps(s):";
cin >>array;
i++;
}
}
return array;
}
Your code has undefined behavior.
Both of your calls to tempGuage() are passing in invalid int& references in the 1st parameter, as the [totalTemp] index is accessing an int that is beyond the bounds of each array. So, even if tempGauge() worked properly (which it doesn't), it would be filling in invalid memory. Since you clearly want to fill the arrays, you need to change [totalTemp] to [0] instead so you start filling at the beginning of each array rather than at the end.
Inside of tempGauge(), maxTemps is uninitialized when entering the loop, so the number of iteration is indeterminate. But, even if it weren't, the statement cin >>array; does not read in an entire array, like you are expecting. Even if it could, it would not know how many ints to read, since array is declared as a reference to a single int and you can't pass maxTemps to operator>>. You would need a loop to read each int individually, which you are trying to do, but you are not looping correctly. And also, cin >> array would need to be changed to cin >> array[i];, which won't work unless int &array is changed to either int (&array)[10] or int *array. In which case, main() would then have to be updated accordingly, by dropping the [0] when passing in each array.
With that said, try this instead:
#include <limits>
const int totalTemp = 10;
int tempGuage(int (&array)[totalTemp], int actDay);
void userData();
int main()
{
int firstDay[totalTemp] = {};
int secondDay[totalTemp] = {};
tempGuage(firstDay, 1);
tempGuage(secondDay, 2);
userData();
return 0;
}
int tempGuage(int (&array)[totalTemp], int actDay)
{
int maxTemps;
cout << "Enter # of temps on DAY " << actDay << ":";
do
{
if (!(cin >> maxTemps))
{
cout << "Invalid input. Try again.";
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
else if ((maxTemps <= 0) || (maxTemps > totalTemp))
{
cout << "Enter at least 1 but no more than " << totalTemp << ". Try again.";
}
else
{
cout << "Enter the " << maxTemps << " temps(s):";
for(int i = 0; i < maxTemps; ++i)
{
while (!(cin >> array[i]))
{
cout << "Invalid input for temp " << i+1 << ". Try again.";
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}
break;
}
}
while (true);
return maxTemps;
}
void userData()
{
//...
}
Live Demo

How to use pointers into structure

I have a structure sportist
struct sportist{
string name;
string surname;
int goals;
string tim;
}
Here is the function that should read the values.
void read(sportist x[],int n)
{
int i;
for(i=0;i<n;i++)
{
cout<<"************************************************"<<endl;
cout<<"Name:";
cin>>x[i].name;
cout<<endl<<"Surname:";
cin>>x[i].surname;
cout<<endl<<"Goals :";
cin>>x[i].goals;
cout<<endl<<"Name of the team:";
cin>>x[i].tim;
}
My question is how can I use pointers, because I need to? My attempt:
void read(sportist* x,int n)
{
int i;
for(i=0;i<n;i++)
{
cout<<"************************************************"<<endl;
cout<<"Name:";
cin>>x->name;
cout<<endl<<"Surname:";
cin>>x->surname;
cout<<endl<<"Goals :";
cin>>x->goals;
cout<<endl<<"Name of the team:";
cin>>x->tim;
}
}
What I want is to sort the sequence of athletes and teams by the number of goals and print them on the screen to sort them in a popup order. But it shows me errors when I debug.
you should pay attention to one point when you are using array x[i] with i increasing ,you are traversing the array ,but with pointer you should move pointer so it would point to next elements of array.You should use x++;.
look:
void read(sportist* x, int n)
{
int i;
for (i = 0; i < n; i++)
{
cout << "************************************************" << endl;
cout << "Name:";
cin >> x->name;
cout << endl << "Surname:";
cin >> x->surname;
cout << endl << "Goals :";
cin >> x->goals;
cout << endl << "Name of the team:";
cin >> x->tim;
x++;
}
}
if you miss x++; each time you will write entered data in first element of array.
Also note in function you are declaring this array of sportist , if you declare sportist* x instead of sportist x[num] ,you have to allocate memory for it too.

C++ Pointer Array Won't Accept More Values

please, why this pointer array won't accept more than 5 values?
Doing excercises from Prata's C++ book, but got stuck on this.
//ex2_numrow -- showing entered numbers til zero is entered
#include <iostream>
using namespace std;
int main()
{
int n = 0;
int num = 0;
int* entered = new int[1];
do
{
cout << "Enter number: ";
cin >> num;
entered[n] = num;
cout << "Your numbers: ";
for (int i = 0; i <= n; i++)
{
cout << entered[i] << " ";
}
cout << endl << endl;
n++;
} while (num);
delete[] entered;
return 0;
}
The code int* entered = new int[1]; gives you a pointer to an array of size one!
It is very unwise (i.e., undefined behaviour) to then try to write values outside of that array. The best case is that your code will crash before it causes any serious issues.
As an aside, the set of use cases for raw pointers is fast dwindling in C++, you should generally be looking at smart pointers instead.
I say "generally" because, if your intent is to have a resizable array, even smart pointers won't help that much. What will help is a little thing I like to call std::vector :-) You should probably look into using that for your immediate purpose.
For example, this program accepts positive numbers, adding them to a vector, then printing them out:
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers;
int num;
do {
std::cout << "Enter number: ";
std::cin >> num; // should probably check for errors in real code
if (num >= 0) {
numbers.push_back(num);
}
} while (num >= 0);
std::cout << "You entered:";
for (int num: numbers) {
std::cout << ' ' << num;
}
std::cout << '\n';
}

How to explain Segmentation fault sometimes happening when dynamically allocating 2D array?

I want to have a function that initializes simple Grid (2d array) with Columns and Rows, each position (cell) is then the size of struct.
I found a solution that accomplishes this in main function but when done in any other function, after running half-way through it crashes with segmentation fault before it prints the Grid (unlike in the last paragraph).
However, if printing the Grid is added directly behind the initializing part, the code works normally afterwards and all faults disappear.
I suspect that main does not now that Position array was initialized but I am passing it as pointer so, what am I doing wrong?
The following code is divided to two parts. First has the segmentation fault, second does not. The only difference is that in the second part, the for-cycles for printing out the grid are inside function that initializes the 2d array.
//SEGMENTATION FAULT
void CreateMap (struct GameGrid *Position, int &Dim_x, int &Dim_y)
{
cout << "Lets create the game map." << endl;
cout << "Enter number of Columns: ";
cin >> Dim_x;
cout << "Enter number of Rows: ";
cin >> Dim_y;
Position = new GameGrid[Dim_x * Dim_y];
}
int main()
{
struct GameGrid *Position = NULL;
int Dim_x;
int Dim_y;
CreateMap(Position, Dim_x, Dim_y);
for (int y=0; y < Dim_y; y++)
{
cout << setw (20);
for (int x=0; x < Dim_x; x++)
{
cout << Position[x*Dim_y + y].Element;
cout << char(32);
}
cout << endl;
}
delete[] Position;
return 0;
}
//NO FAULTS
void CreateMap (struct GameGrid *Position, int &Dim_x, int &Dim_y)
{
cout << "Lets create the game map." << endl;
cout << "Enter number of Columns: ";
cin >> Dim_x;
cout << "Enter number of Rows: ";
cin >> Dim_y;
Position = new GameGrid[Dim_x * Dim_y]
for (int y=0; y < Dim_y; y++)
{
cout << setw (20);
for (int x=0; x < Dim_x; x++)
{
cout << Position[x*Dim_y + y].Element;
cout << char(32);
}
cout << endl;
}
}
int main()
{
struct GameGrid *Position = NULL;
int Dim_x;
int Dim_y;
CreateMap(Position, Dim_x, Dim_y);
delete[] Position;
return 0;
}
The Grid should look something like this for dimensions Dim_x=6 and Dim_y=6 (chosen by end-user).
A A A A A A
A A A A A A
A A A A A A
A A A A A A
A A A A A A
A A A A A A
Also when the printing the grid is done two times (once in the function CreateMap and once in main), it prints them both times, then freezes for 10 secs and dies.
In your CreateMap function:
void CreateMap (struct GameGrid *Position, int &Dim_x, int &Dim_y)
{
// ...
Position = new GameGrid[Dim_x * Dim_y];
}
This modifies the Position local variable only, it does not alter the caller's value supplied to that argument.
What you need is to re-work this:
GameGrid *CreateMap(const int Dim_x, const int Dim_y)
{
// ...
return new GameGrid[Dim_x * Dim_y];
}
Where that returns a value you can capture:
int main()
{
int x, y;
cout << "Lets create the game map." << endl;
cout << "Enter number of Columns: ";
cin >> x;
cout << "Enter number of Rows: ";
cin >> y;
GameGrid *Position = CreateMap(x, y);
// ...
}
Do all your input/output outside of these functions. Remember your SOLID Principles, give that function one job and one job only. Input and allocation are two jobs.
Even better: Make a constructor instead of these CreateX functions. This is C++ and you can take full advantage of that.
As always:
Whenever you're having strange behaviour, step through your code in a debugger to see what the values of various variables are as it executes.
Although you're using a pointer as a parameter, you are still passing-by-value.
When trying to pass-by-reference the pointer itself is not changed but the object at the address it points to is updated.
So to update the pointer you need a pointer to the pointer or a reference to a pointer. Otherwise, often as has been answered, the return is used to return an updated pointer.

Asking user for const

There is my friend's code. It works, but we would like to ask our user how many times he wants to type informations. Simplier, We don't know how to ask my user for N ("const int N = 3" line). We've tried changing "const int" into "int", but then an error shows up "expression must have a constant value".
#include <iostream>
using namespace std;
struct T_dane_ksiazki
{
char imie[15];
char nazwisko[30];
char tytul[45];
int rokwydania;
int nrwydania;
};
void WCZYTAJ_dane(T_dane_ksiazki& dane) /*wczytanie informacji o książce*/
{
cout << "\nimie autora: ";
cin >> dane.imie;
cout << "nazwisko autora: ";
cin >> dane.nazwisko;
cout << "tytul ksiazki: ";
cin >> dane.tytul;
cout << "rok wydania: ";
cin >> dane.rokwydania;
cout << "numer wydania: ";
cin >> dane.nrwydania;
}
void WYSWIETL_dane(T_dane_ksiazki dane) /*wczytanie informacji o książce*/
{
cout << "\nimie autora: " << dane.imie;
cout << "\nnazwisko autora: " << dane.nazwisko;
cout << "\ntytul ksiazki: " << dane.tytul;
cout << "\nrok wydania: " << dane.rokwydania;
cout << "\nnumer wydania: " << dane.nrwydania << "\n";
}
const int N = 3;
int Zapytajka()
{
cout << N<< "\n";
return 1;
}
int main()
{
T_dane_ksiazki daneq[N];
Zapytajka();
cout << "Podaj informacje o ksiazkach: \n";
for (int i = 0; i<N; i++)
{
WCZYTAJ_dane(daneq[i]);
}
cout << "\n\nInformacje o ksiazkch: \n";
for (int i = 0; i<N; i++)
{
WYSWIETL_dane(daneq[i]);
}
cout << "\nKoniec programu. Nacisnij ENTER";
cin.ignore(); cin.get();
return 1;
}
C++ only supports arrays whose size is constant. However, if you want a non-constant size, you can use vector, which was designed specifically for this purpose.
Example:
#include <vector>
...
int main()
{
Zapytajka();
cout << "Podaj informacje o ksiazkach: \n";
int n;
cin >> n;
std::vector<T_dane_ksiazki> daneq(N); // moved here and modified
for (int i = 0; i<N; i++)
{
WCZYTAJ_dane(daneq[i]);
}
...
}
I changed an array to a vector, and moved its definition to after the value of n is determined. I also changed N to n because it's no longer a constant, and it's a common convention to allocate lower-case names to variables.
Edit: I missed that it is a C++ question. The answer for C++ is that you should use a C++ container, probably a vector. These containers are the reason that the variable length arrays introduced in C in 1999 discussed below do not exist in C++: There is no real need for them. (There is a discussion whether to introduce something like it but it has non-trivial implications for the type system.)
You can have variable length arrays in C99 programs (for gcc: compile with "-std=c99"). That is, you can make N a non-const and the program should still compile and run properly (I didn't check every detail, but it looks pretty straightforward).
In pre-99 C you have to allocate dynamically with malloc or simply define an array which is big enough for the biggest conceivable number and use only part of it.