How to input string array from the structure in this case? - c++

So, I am beginner. I have this code and a few problems. For better understanding, you will need this code:
struct student
{
double marks;
char name[50];
}stud[100],t;
int main()
{
int i,j,n;
cout<<"Enter the number of students: ";
cin>>n;
cout<<"Enter student info as name , marks\n";
for(i=0;i<n;i++)
{
cin>>stud[i].name;
cin>>stud[i].marks;
}
The problem is, instead of this part:
struct student
{
double marks;
char name[50];
}stud[100],t;
There should be this part:
struct student
{
double marks[];
string name[];
}stud[100],t;
But then I don't know how to enter that data into the program because then the cin >> doesn't work.
Task says that when the user enters ' ' (ENTER), the program should finish and show the students print in order.

The marks and name array are dynamic and they are called flexible array members and they are not supported in cpp u can refer to this link Are flexible array members valid in C++? and moreover they are supported in c and u can have atmost one flexible array member and it should be at end
https://www.geeksforgeeks.org/flexible-array-members-structure-c/

I believe this is close to what you want:
//10 marks by students
int m = 10;
struct student
{
double marks[m];
string name;
}stud[100],t;
int main()
{
int i,j,n;
cout<<"Enter the number of students: ";
cin>>n;
for(i=0;i<n;i++)
{
cout<<"Enter student info as name\n";
cin>>stud[i].name;
for(int j=0; j<m; ++j)
{
cout<<"Enter student marks "<<j+1<<endl;
cin>>stud[i].marks[j];
}
}
}

You'll need a second loop. I added constants -- this is good practice so you don't have "magic numbers" in your code. I added a display function to demonstrate that it works!
#include <iostream>
using namespace std;
const int MAX_MARKS = 25;
const int MAX_STR = 50;
const int MAX_STUDENTS = 100;
struct student
{
double marks[MAX_MARKS];
char name[MAX_STR];
}stud[MAX_STUDENTS],t;
int main()
{
int i,j,n;
bool complete = false;
cout<<"Enter the number of students: ";
cin>>n;
for(i=0; i < n && i < MAX_STUDENTS; ++i)
{
complete = false;
cout<<"Enter student info as name , marks\n";
cin>>stud[i].name;
for (j = 0; j < MAX_MARKS; ++j)
{
if (!complete)
{
cout << "Enter mark #" << j+1 << ": ";
if (!(cin >> stud[i].marks[j]))
{
complete = true;
stud[i].marks[j] = -1.0;
cin.clear();
cin.ignore(100, '\n');
}
}
else
stud[i].marks[j] = -1.0; //0.0 is a valid grade so need a different value
}
}
//Added a block for displaying the students
for (i = 0; i < MAX_STUDENTS && i < n; ++i)
{
complete = false;
cout << "Student #" << i+1 << ": " << stud[i].name << endl;
for (j = 0; j < MAX_MARKS && !complete; ++j)
{
if (stud[i].marks[j] == -1.0)
complete = true;
else
cout << "\tMark #" << j+1 << ": " << stud[i].marks[j] << endl;
}
}
}

Related

How to print "The key(element) is not present in your array" when I don't enter a key present in my array when asked for by the computer in my code

Let's say I enter {1,3,3,5} as my array and I input 6 when asked to enter the key whose index I want to know. How do I edit my code to print that "the key entered is not in your array"?
My code is given below:
#include <iostream>
using namespace std;
void linearsearch(int arr[], int n, int key) {
int i;
for (i = 0; i < n; i++) {
if (arr[i] == key) {
cout << " \nthe index is: " << i;
}
}
}
int main() {
int n;
cout << "enter the size of your array : ";
cin >> n;
int arr[n];
cout << "\nenter the keys of your array: ";
for (int i = 0; i < n; i++) {
cin >> arr[i];
}
int key;
cout << "\n enter the key whose index you want to know: ";
cin >> key;
linearsearch(arr, n, key);
}
// You can use a boolean control variable in the void function and when you find the number you can set its value to true and insert an if statement at the end of the loop to check the value of the bool variable, if the, if statement in the loop wasn't executed, meant that the number was not found and the value of the variable was false so it would print the line you were asking about //
#include <iostream>
using namespace std;
void linearsearch(int arr[], int n, int key) {
int i;
bool found = false;
for (i = 0; i < n; i++) {
if (arr[i] == key) {
cout << " \nthe index is: " << i;
found = true;
}
}
if (found == false){
cout << "The key entered is not in your array." << endl;
}
}
int main() {
int n;
cout << "enter the size of your array : ";
cin >> n;
int arr[n];
cout << "\nenter the keys of your array: ";
for (int i = 0; i < n; i++) {
cin >> arr[i];
}
int key;
cout << "\n enter the key whose index you want to know: ";
cin >> key;
linearsearch(arr, n, key);
}

0xC0000005: Access violation writing location 0xCDCDCDCD Dynamic Allocation Error

Getting 0xC0000005: Access violation writing location 0xCDCDCDCD with the code below.
I know I must have not allocated the pointer properly, but I'm not sure where.
I'm trying to have **scoreSet refer to sets of *scores and *scores is to be entered in manually. The names pointer to array is working fine and seems to be allocated properly. The problem is when I try to mimic the same for scoreSet, with the difference being scoreSet is a pointer to an array of pointers scores. I feel like the way I'm trying to dynamically allocate the arrays that this pointer is pointing to is completely wrong.
Basically trying to get something like this to be possible after user input:
scoreSet0 = {22,33,44}
scoreSet1 = {35, 45, 65, 75}
scoreSet3 = {10}
#include <iostream>
#include <string>
using namespace std;
int inputData(string*& names, double**& scores);
int main() {
string *names = nullptr;
double *scores = nullptr;
double **scoreSet = &scores;
int size = 0;
size = inputData(names, scoreSet);
for (int i = 0; i < size; i++) {
cout << *(names+i) << endl;
}
}
int inputData(string*& names, double**& scoreSet) {
int numStudents = 0;
cout << "How many students do you have in the system? ";
cin >> numStudents;
while (numStudents <= 0) {
cout << "Invalid number of students. Please enter number of students: ";
cin >> numStudents;
}
names = new string[numStudents];
cin.ignore(10000, '\n');
for (int i = 0; i < numStudents; i++) {
int numTests = 0;
cout << "Enter the student's name: ";
getline(cin,names[i]);
cout << "Enter how many tests " << *(names + i) << " took: ";
cin >> numTests;
*(scoreSet + i)= new double[numTests]; //Pretty sure this is wrong.
cin.ignore(10000, '\n');
for (int j = 0; j < numTests; j++) { //This loop is causing the error.
cout << "Enter grade #" << j + 1 << ": ";
cin >> *(scoreSet+i)[j];
}
}
return numStudents;
}
Per PaulMcKenzie suggestion, this is how it would roll. It may be a bit much for you to use templates, but if you can... Otherwise create the name and score containers separately. But then you have duplicate code to maintain.
The idea is to keep all your stuff in some kind of order. Note that now the memory management is taken care of in the container.
I dropped handling std::cin and the scores, but it should be much easier for you to code that stuff back without a lot of fluff in the way. At that, develop without std::cin, it is a waste of time. You should write so you can just edit and run.
Also, get out of the habit of using namespace std; It will pay off in the long run.
#define DEV
template<typename T>
struct container {
size_t size;
T* ar;
container(size_t size) :size(size) {
ar = new T[size];
}
~container() { delete[]ar; }
T& operator [](size_t pos) { return ar[pos]; }
};
using names_c = container<std::string>;
using scores_c = container<double>;
size_t inputData(names_c& names, scores_c& scores);
int main() {
container<std::string> names(2);
container<double> scoreSet(2);
auto size = inputData(names, scoreSet);
for (int i = 0; i < size; i++) {
std::cout << names[i] << endl;
}
}
size_t inputData(names_c& names, scores_c& scores) {
#ifdef DEV
size_t numStudents = 2;
names[0] = "tom";
names[1] = "mary";
#else
//do your std::cin stuff
#endif
return names.size;
}
I wasn't going to go there, but. You can extend the concept so that you have containers in containers. Much easier to know what scores go with what student.
struct student_type {
using scores_c = container<double>;
std::string name;
scores_c scores;
};
using student_c = container<student_type>;
I've taken your code, and modified it to work. I've removed your comments, and placed comments in on the lines that I changed.
#include <iostream>
#include <string>
using namespace std;
int inputData( string *&names, double **&scores );
int main() {
string *names = nullptr;
double **scores = nullptr; // Changed to double ** so it's "2D"
// double **scoreSet = &score; // removed, this was unneeded and probably causing problems
int size = 0;
size = inputData( names, scores );
for ( int i = 0; i < size; i++ ) {
cout << *( names + i ) << endl;
}
}
int inputData( string *&names, double **&scoreSet ) {
int numStudents = 0;
cout << "How many students do you have in the system? ";
cin >> numStudents;
while ( numStudents <= 0 ) {
cout << "Invalid number of students. Please enter number of students: ";
cin >> numStudents;
}
names = new string[numStudents];
scoreSet = new double*[numStudents]; // allocate an array of pointers
// cin.ignore( 10000, '\n' ); // Removed from here, placed inside loop
for ( int i = 0; i < numStudents; i++ ) {
cin.ignore( 10000, '\n' ); // placed here so that it always clears before getting the name
int numTests = 0;
cout << "Enter the student's name: ";
getline( cin, names[i] );
cout << "Enter how many tests " << names[i] << " took: "; // simplified
cin >> numTests;
scoreSet[i] = new double[numTests]; // simpliefied left hand side
//cin.ignore( 10000, '\n' ); // not needed
for ( int j = 0; j < numTests; j++ ) {
cout << "Enter grade #" << j + 1 << ": ";
cin >> scoreSet[i][j]; // simplified
}
}
return numStudents;
}

User input into array. I am confused with output

Most of the components for the array are in place.
I am however wondering what code is missing for the output to match what I am trying to do.
I tried searching for similar array coding. I would like to call the function and for the user to input numbers up to 20 different inputs.
#define size 20
using namespace std;
int i;
void Input(int student[]) {
for(int i = 0; i < size; i++)
cout << "Enter The Marks of Subject 2 of student no " << i + 1 << " ";
cin >> student[i];
}
void display(int student[]) {
for(int i = 0; i < size; i++)
cout << student[i];
}
int main() {
int student[size];
Input(student );
display(student);
return 0;
In your Input function:
void Input(int student[]) {
for(int i = 0; i < size; i++)
cout << "Enter The Marks of Subject 2 of student no " << i + 1 << " ";
cin >> student[i];
}
You not using brackets, so the cin >> student[i]; is outside of the loop. The i from the for loop is no longer in scope, so you are using the i here:
int i;
Which is never given a value, which leads to undefined behavior. Add brackets:
void Input(int student[]) {
for(int i = 0; i < size; i++) {
cout << "Enter The Marks of Subject 2 of student no " << i + 1 << " ";
cin >> student[i];
}
}

How do I add a search function to array?

I need to add a function to search in the string array and bring up the user with associated phone number. Though Im lost. Any functions created only bring up the persons name without the number. If not found, it needs to say error.
int main(int argc, char** argv)
{
int i, n, j;
string name[100];
string phone[100];
int index[100];
cout << "How many names and phone numbers do you want to enter? " << endl
<< "Entering 0 ends the program." << endl;
cin >> n;
if (n == 0)
return 0;
for (i = 0; i < n; i++) {
cout << "Please enter a name: ";
cin >> name[i];
cout << "Please enter a phone number: ";
cin >> phone[i];
}
for (i = 0; i < n; i++) {
index[i] = i;
}
for (i = 0; i < n; i++) {
for (j = i + 1; j < n; j++) {
int temp;
if (phone[index[i]] > phone[index[j]]) {
temp = index[i];
index[i] = index[j];
index[j] = temp;
}
}
}
cout << "These entries are in ascending order by phone number: " << endl;
cout << "Name"
<< " "
<< "Phone Number" << endl;
for (i = 0; i < n; i++) {
cout << name[index[i]] << " " << phone[index[i]] << endl;
}
return 0;
}
This code should work for you (if i understood the question)
int search(string name[], string searchedName){
for(int i=0; i<100; i++){
if(searchedName == name[i])
return i; //Returns the position of the person, which is also the index of his phone number
}
return -1; //If -1 is returned it means there is no such name an "searchedName" in the vector
}
You can call this function like this
int main(){
/* all the stuff you already have inside here */
string nameToSearch;
cout<<"Insert the name of the person you want to see the number of"<<endl;
cin>>nameToSearch;
int position = search(name, nameToSearch);
if(position == -1)
cout<<"Sorry, "<<nameToSearch<<" is not in our list"<<endl;
else
cout<<"The phone number of "<<nameToSearch<<" is "<<phone[position]<<endl;
return 0;
}
Of course this is pretty basic and you can make it better, hope it helps!

Dynamically Allocated Structures

So i am having troubles here. The program works perfectly fine when i enter in 1 for numStudents but get a segmentation fault: 11 when i enter anymore that 1 for numstudents. Am i doing something wrong with the dynamic allocation? I am just lost have done everything i can think of.
#include <iostream>
#include <string>
#include <cstdlib>
#include <iomanip>
using namespace std;
//Structure Declaration
struct Student
{
string name;
long long ID;
double *score;
};
//Function prototypes
void calcAvg (int loc, Student test[], double average[], int tests);
int main()
{
int numStudents, numTests; //Get from user
double *averages; //For Dynamic allocation of averages
Student *info; //For Dynamic Allocation
cout << "Enter the number of students you will enter ";
cin >> numStudents;
info = new Student[numStudents];
averages = new double[numStudents];
cout << "\nEnter the number of tests that were taken by the students ";
cin >> numTests;
info->score = new double[numTests];
for(int s = 0; s < numStudents; s++)
{
cout << "Enter student #" << (s+1) << "'s name ";
cin.ignore();
getline(cin, info[s].name);
cout << "Enter " << info[s].name << "'s ID number ";
cin >> info[s].ID;
cout << endl;
for(int t = 0; t < numTests; t++)
{
cout << "\nEnter " << info[s].name << "'s score for test #" <<(t+1) << " ";
cin >> info[s].score[t];
while(info[s].score[t] > 100 || info[s].score[t] < 0)
{
cout << "The score you entered is invalid, try again. ";
cin >> info[s].score[t];
}
}
calcAvg(s, info, averages, numTests);
}
return 0;
}
void calcAvg (int loc, Student test[], double average[], int tests)
{
double total = 0;
for(int i = 0; i < tests; i++)
{
total += test[loc].score[i];
}
average[loc] = total/tests;
cout << average[loc] << endl;
}
You need to repeat this for each student
info->score = new double[numTests];
So you could move it into the loop:
for(int s = 0; s < numStudents; s++)
{
info[s].score = new double[numTests];
...
}
But all this is very error prone - I suggest you look into structures that can handle all this for you like std::vector.