Asking user for const - c++

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.

Related

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';
}

no operator ">>" matches these operands operand types are: std::istream >> double*

I'm trying to dynamically allocate an array from a structure. I've look on a couple of other pages on stackoverflow and tried some some code, but none seems to work for my case. The closest I've found to what I'm doing is here:
C++ dynamic memory allocation with arrays in a structure
For some reason when I use this line of code:
cin >> testsPtr[i].students;
I get the error in the title. I've also tried using:
cin >> testsPtr[i]->students;
How can I have the user enter the data for my program?
Here are the specifications for the programming challenge:
Modify the program of Programming Challenge 1 to allow the user to enter name-score pairs. For each student taking a test, the user types a string representing the name of the student, followed by an integer representing the students score. Modify both the sorting and average-calculating functions so they take arrays of structures, with each structure containing the name and score of a single student. In traversing the arrays, use pointers rather than array indices.
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
void averageScore(double*, int);
void sort(double*, int);
int numScores;
struct studentScores {
double *scores;
string *students;
};
cout << "How many test scores will you be entering?" << endl;
cin >> numScores;
studentScores *testsPtr = new studentScores[numScores];
for (int i = 0; i < numScores; i++) {
cout << "What is the #" << i + 1 << " students name?" << endl;
cin >> testsPtr[i].students;
for (int j = 0; j < numScores; j++) {
cout << "Please enter test score #" << j + 1 << endl;
do {
cin >> testsPtr[j].scores;
if (testsPtr[i].scores < 0) {
cout << "A test score can't be less than 0. Re-enter test score #" << i + 1 << endl;
}
} while (testsPtr[i].scores < 0);
}
}
cout << endl;
/*sort(testsPtr.scores, numScores);
cout << endl;
averageScore(testScores, numScores);
cout << endl;*/
for (int i = 0; i <= numScores; i++) {
cout << testsPtr->students << " test scores are: " << endl;
for (int j = 0; j <= numScores; j++) {
cout << testsPtr->scores;
}
}
delete[] testsPtr;
testsPtr = nullptr;
return 0;
}
Dereference pointer before reading value:
cin >> *(testsPtr[i].students);
But before you have to create object string and reference pointer to it:
testsPtr[i].students = new string;
The fix to your problem is to change your cin line to this cin >> *(testsPtr[i].students); this is because testsPtr[i].students is a pointer so you have to use the deference pointer. Make sure you correctly initialize the members.
Hope this helps.

Converting Program to return a Pointer with a structure

Can someone explain what i need to do in order to convert this program to return a pointer in the enterCubScouts function, I've tried everything i know of and nothing is working. I Read something about useing -> instead of the normal * but I'm kind of confused. Do you use -> in tandem with * or just ->.
#include <iostream>
using namespace std;
struct CubScouts
{
string name;
int schoolGrade;
string denName;
};
CubScouts *enterCubScouts(CubScouts *scouts[], int);
void printCubScouts(CubScouts scouts[], int);
int main()
{
int numScouts;
cout << "\n\nHow many cub scouts are in your pack?\n";
cin >> numScouts;
cin.ignore();
CubScouts scouts[numScouts];
enterCubScouts(scouts, numScouts);
printCubScouts(scouts, numScouts);
return 0;
}
CubScouts *enterCubScouts(CubScouts *scouts[],int size)
{
for(int x=0; x<size; x++)
{
cout << "\nCUB SCOUT " << x+1 << ": \n";
cout << "NAME: ";
getline(cin, scouts[x].name);
cout << "\n\nGRADE (1-5): ";
cin >> scouts[x].schoolGrade;
cout << "\n\nDEN NAME: ";
cin.ignore();
getline(cin, scouts[x].denName);
cin.sync();
}
return *scouts; // This needs to be a pointer
}
http://www.functionx.com/cpp/examples/returnpointer.htm
CubScouts * enterCubScouts(CubScouts *scouts[], int size)
Maybe?
I think you just need to add an asterisk
Going to try this in a c++ compiler; can't believe I don't have one on this machine
This worked for me:
CubScouts * enterCubScouts(CubScouts scouts[], int size)
{
for (int x = 0; x<size; x++)
{
cout << "\nCUB SCOUT " << x + 1 << ": \n";
cout << "NAME: ";
getline(cin, scouts[x].name);
cout << "\n\nGRADE (1-5): ";
cin >> scouts[x].schoolGrade;
cout << "\n\nDEN NAME: ";
cin.ignore();
cin.sync();
}
return scouts; // This needs to be a pointer
}
void printCubScouts(CubScouts scouts[], int size)
{
for (int x = 0; x<size; x++)
{
cout << scouts[x].name << " " << scouts[x].denName << " " << scouts[x].schoolGrade;
}
}
not sure if it's doing what you want it to
You don't even use the returned value so you might as well make it void.
This line:
CubScouts *enterCubScouts(CubScouts *scouts[],int size)
should be:
CubScouts *enterCubScouts(CubScouts scouts[],int size)
(and update the prototype, too). The way you have it currently, should generate a compiler error. Also , this line:
CubScouts scouts[numScouts];
should generate a compiler error, because arrays cannot have run-time size in C++. Try invoking your compiler in standard mode. If it seems to work for you, I'd still advise using standard containers instead of your compiler extension, as we do have a document that describes exactly how standard containers have to work.
Anyway... logically it doesn't make a lot of sense to return a pointer to a scout; since your function has no code to detect input failure. What would main() do with this pointer?
If you added some error-checking then you could return a pointer indicating the end of the list of scouts that were entered successfully, e.g.
return scouts + size;
This compiles at least -- not sure what the print is/ supposed to do:
#include <iostream>
using namespace std;
struct CubScouts
{
string name;
int schoolGrade;
string denName;
};
CubScouts *enterCubScouts(int x);
//void printCubScouts(CubScouts*[], int);
int main()
{
int numScouts;
cout << "nnHow many cub scouts are in your pack?n";
cin >> numScouts;
cin.ignore();
CubScouts *scouts[numScouts];
for(int x=0; x<numScouts; x++){
scouts[x] = enterCubScouts(x);
}
//printCubScouts(scouts, numScouts);
return 0;
}
CubScouts *enterCubScouts(int x)
{
CubScouts *scout = new CubScouts;
cout << "nCUB SCOUT " << x+1 << ": n";
cout << "NAME: ";
getline(cin, scout->name);
cout << "nnGRADE (1-5): ";
cin >> scout->schoolGrade;
cout << "nnDEN NAME: ";
cin.ignore();
getline(cin, scout->denName);
cin.sync();
return scout; // This needs to be a pointer
}

Function taking an array filled with structures, and returning a bigger array with the same structures

#include <iostream>
#include <string>
using namespace std;
struct FriendInfo
{
string name;
int last_day;
};
FriendInfo GrowArray(FriendInfo friend_list,int sizing);
int main()
{
int initial_friends;
cout << "How many friends would you like to add--> ";
cin >> initial_friends;
FriendInfo friends[initial_friends];
for (int i = 0; i < initial_friends;i++)
{
cout << "What is your friend's name?--> ";
cin >> friends[i].name;
cout << "When was the last time you talked to " << friends[i].name << " ?--> ";
cin >> friends[i].last_day;
}
for (int i = 0; i < initial_friends;i++)
cout << friends[i].name << " " << friends[i].last_day << "\n";
cout << "What would you like to do now?\n1. Add another friend?\n2. Update one of yourfriends?\n3. Sort friends by day?4. Quit.\n--> ";
int option;
cin >> option;
while (option != 4)
{
if (option == 1)
{
friends = GrowArray(friends,initial_friends);
cout << "What is your new friend's name?--> ";
cin >> friends[initial_friends].name;
cout << "When was the last time you talked to " << friends[initial_friends].name << " ?--> ";
cin >> friends[initial_friends].last_day;
}
}
}
FriendInfo GrowArray(FriendInfo friend_list, int sizing)
{
FriendInfo new_list[sizing + 1];
for (int i = 0;i < sizing;i++)
{
new_list[i].name = friend_list[i].name;
new_list[i].last_day = friend_list.last_day;
}
return new_list;
}
This program put structures into an array that hold a friend's name, and the last day they talked to them. One of the options later on is to add another friend. The function GrowArray takes the initial array with the friends and the days, makes another array with an extra spot and copies the original array into the new one. But when I use the function I get this error --> error: could not convert '(FriendInfo*)(& friends)' from 'FriendInfo*' to 'FriendInfo'. What's wrong?
You can't reassign friends like that since it's not a pointer, it's an array.
Even if you could, what you're doing isn't safe since GrowArray just creates a new array on the stack which will be destroyed when the function returns.
You should either use new and delete to create and destroy the arrays (you can then then pass them around as pointers), or preferably, use std::vector which handles all this stuff for you.

How to use a dynamically sized array of structs?

I have to make my homework. It is console application which uses an array of structs that keep information about a computer(brand, year of manufactoring, weight and inventory number). So I wrote a completely working program, but I want to use a dynamic array, because I dont know how many records the user will input.
Is there way to do this. To add new records in array until the user say n/N? Any suggestions?
This is my version of program:
#include "stdafx.h"
#include <iostream>
using namespace std;
struct ComputerInfo
{
char computerMark[20], invertarNumber[6];
unsigned int year;
float weight;
};
ComputerInfo computerArray[300];
ComputerInfo AddComputers(ComputerInfo compterArray[], int counter)
{
cout << "Enter mark of the computer: ";
cin >> computerArray[counter].computerMark;
cout << "Enter year of establish: ";
cin>> computerArray[counter].year;
while ((computerArray[counter].year < 1973)
|| (computerArray[counter].year > 2013))
{
cout << "INVALID YEAR!!!" << endl;
cout << "Enter year of establish: ";
cin>> computerArray[counter].year;
}
cout << "Enter computer weidth: ";
cin >> computerArray[counter].weight;
cout << "Enter computer invertar number(up to six digits): ";
cin >> computerArray[counter].invertarNumber;
return computerArray[counter];
}
void ShowRecords()
{
int counter = 0;
while (computerArray[counter].year != 0)
{
cout << "Mark: " << computerArray[counter].computerMark << endl;
cout << "Year: " << computerArray[counter].year << endl;
cout << "Weidth: " << computerArray[counter].weight << endl;
cout << "Inv. number: " << computerArray[counter].invertarNumber << endl << endl;
counter++;
}
}
void MoreThanTenYearsOld(ComputerInfo computerArray[])
{
int counter = 0;
float counterOldComputers = 0;
float computerPer = 0;
while (computerArray[counter].year == 0)
{
if (computerArray[counter].year <= 2003)
{
counterOldComputers++;
}
counter++;
}
computerPer = counterOldComputers / 3;
cout << endl;
cout << "Percantage of old computers is: " << computerPer << endl;
}
int main()
{
int counter = 0;
float computerPer = 0;
char answer = 'y';
for (int i = 0; i <= 299; i++)
{
strcpy(computerArray[i].computerMark,"");
}
while((answer == 'Y') || (answer == 'y'))
{
computerArray[counter] = AddComputers(computerArray, counter);
cout << endl;
cout << "Do you want to enter more records (Y/N): ";
cin >> answer;
cout << endl;
counter++;
}
MoreThanTenYearsOld(computerArray);
return 0;
}
Yes. Instead of your array, use
std::vector<ComputerInfo> computerArray;
and you can add as many objects as you want:
ComputerInfo c;
// read the data
computerArray.push_back(c);
now, computerArray[0] will have the info in c.
You'll need to #include <vector>.
Also, instead of char computerMark[20] you can use a std::string.
You have two options:
1) Use std::vector instead of an array. This is a very powerful tool and certainly worth learning how to use.
2) Dynamically allocate the array and resize it as you add more items. Basically this means writing your own version of std::vector. This is a good way to strengthen your programming skills. You will learn what goes into writing standard classes and functions. However, I advise using std::vector in more serious programming because it has already been thoroughly tested and debugged.