The use of arrays within structures - c++

I'm currently studying C++ on a book I bought a month ago. So now here I am, studying the new chapter that talks about structures.
The book gives a problem: Write a program that allows a user to enter high scores of a game, keeping tracking of the name
of the user and the score. Add the ability to show the highest score for each user, all scores for a
particular user, all scores from all users, and the list of users.
My problem is... how to store a lot of scores of the same player, using a structure.
I thought something like this:
struct my_string
{
string name;
int score[100];
int lvp;
};
Declaring an array, within a structure, it's something that can be done? I'm not entirely sure.
After that, in the main function, I declared an array of my_string type.
Like this:
my_string name_score[100];
I was thinking about using 2 counters, one that is related to the name, and the other related to the scores. Something like this:
name_score[0].score[2];
So, this piece of code should give me back the third score, of the first name (player).
Am I saying nonsense, or this can be done?

Seems to me that you are exactly right! That should work perfectly.
Basically your first closed brackets will give you the player and the .score[] will give you their entry.

So this code is valid code:
#include <iostream>
#include <string>
struct my_string
{
std::string name;
int score[100];
int lvp;
};
int main()
{
my_string name_score[100];
//Initializing of data in name_score assumed here
std::cout << name_score[0].score[2] << std::endl ;
}
Since this is C++ you may want to consider using std::vector<int> score as opposed to int score[100] or even std::array if you are using C++11 they are both superior to old C style array. The same thing goes for my_string although you might want to pick a more descriptive name.

Related

Telephone directory program using 2D array in c++

I have been given following assignment
Write a simple telephone directory program; contain two dimensional arrays in which you have hard code names and telephone number. Then declare a simple character array. You have to prompt user to enter any name, which you want to search. This name should be store in this character array, then search this name from the two dimensional array. If number is found against entered name then program should display the number against this name, and if not found then program should display the message that name is not registered.
Here is my code but i could not get the number when i search for the name. I am new to coding so i am having trouble making this code work. Help is appreciated.
#include <iostream>
#include <conio.h>
using namespace std;
int getPhone(int p[5][10],int row, int col, char key[10],char n[5][10]);
int main() {
int i,j;
char search[10];
const int r = 5;
const int c = 10;
int element;
int phone[r][c] =
{
42-5429874,
42-5333156,
42-9824617,
42-9927562,
42-6238175
};
char name[r][c] = {"shazia","zara","sana","ahmad","maha"};
cout<<"\nEnter name to find in directory : ";
cin>>search[r];
element = getPhone(phone,r,c,search,name);
cin.get();
return 0;
}
int getPhone(int p[5][10],int row,int col,char key[10], char n[5][10]) {
int i, j;
for(i=0;i<row;i++)
for(j=0;j<col;j++)
p[5][10] = p[i][j];
if(key[j] = n[5][10])
cout<<"The desired number is: "<<p[i][j]<<endl;
else if(key[j]!=n[5][10])
cout<<"Sorry! This name is not registered.";
return p[i][j];
}
Your code contains several mistakes. Let's examine them.
for(i=0;i<row;i++)
for(j=0;j<col;j++)
p[5][10] = p[i][j];
Here, you make no change on your array, because just the value of p[5][10] is changed. Furthermore, you access an invalid memory zone, because array indexes go from 0 to size - 1 in C++. So last index is p[4][9].
if(key[j] = n[5][10])
In C++, comparing two values needs two =, because only one is an affectation that results the if to be always true. A tip to remember: two values to compare need two =.
else if(key[j]!=n[5][10])
The same than before, you access invalid memory zone. And are you sure that j is valid, e.g less than 10 ? If not, you do double invalid access.
cin>>search[r];
As search is an array of char, you do an input of only a single char there, which I think is not what you want and that can leads to segfault.
int phone[r][c] =
{
42-5429874,
42-5333156,
42-9824617,
42-9927562,
42-6238175
};
Your array is not good, a simple 1-dimension array is enough, not 2-dimensions. Furthermore, 42-54.. does a subtraction, and I think is not what you want.
There are others mistakes. But why not using C++ abstractions, like std::vector, or std::string? Your life would get so much easier. But I guess you have an old teacher that never took time to learn C++ news, or that is not a good teacher.
As a beginner, I suggest you to read C++ Primer and Programming: Principles and Practice Using C++ to introduce you both programming and modern C++.

Array Function. Would appreciate a little clarification

I have a question regarding a school lab assignment and I was hoping someone could clarify this a little for me. I'm not looking for an answer, just an approach. I've been unable to fully understand the books explanations.
Question: In a program, write a function that accepts three arguments: an array, the size of the array, and a number n.
Assume that the array contains integers. The function should display
all of the numbers in the array that are greater than the number n .
This is what I have right now:
/*
Programmer: Reilly Parker
Program Name: Lab14_LargerThanN.cpp
Date: 10/28/2016
Description: Displays values of a static array that are greater than a user inputted value.
Version: 1.0
*/
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
void arrayFunction(int[], int, int); // Prototype for arrayFunction. int[] = array, int = size, int = n
int main()
{
int n; // Initialize user inputted value "n"
cout << "Enter Value:" << endl;
cin >> n;
const int size = 20; // Constant array size of 20 integers.
int arrayNumbers[size] = {5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24}; // 20 assigned values for the array
arrayFunction(arrayNumbers, size, n); // Call function
return 0;
}
/* Description of code below:
The For statement scans each variable, if the array values are greater than the
variable "n" inputted by the user the output is only those values greater than "n."
*/
void arrayFunction(int arrayN[], int arrayS, int number) // Function Definiton
{
for (int i=0; i<arrayS; i++)
{
if (arrayN[i] > number)
{
cout << arrayN[i] << " ";
cout << endl;
}
}
}
For my whole answer I assume that this:
Question: In a program, write a function that accepts three arguments: an array, the size of the array, and a number n. Assume that the array contains integers. The function should display all of the numbers in the array that are greater than the number n .
is the whole assignment.
void arrayFunction(int[], int, int); is probably the only thing you could write. Note however that int[] is in fact int*.
As others pointed out don't bother with receiving input. Use something along this line: int numbers[] = {2,4,8,5,7,45,8,26,5,94,6,5,8};. It will create static array for you;
You have parameter int n but you never use it.
You are trying to send variable to the function arrayFunction but I can't see definition of this variable!
Use something called rubber duck debugging (google for it :) ). It will really help you.
If you have some more precise question, ask them.
As a side note: there are better ways of sending an array to the function, but your assignment forces you to use this old and not-so-good solution.
Would you use an if else statement? I've edited my original post with the updated code.
You have updated question, then I update my answer.
First and foremost of all: do indent your code properly!!!
If you do that, your code will be much cleaner, much more readable, and it will be much easier understandable not only for us, but primairly for you.
Next thing: do not omit braces even if they are not required in some context. Even experienced programmers only rarely omit them, so as a beginner you should never do so (as for example with your for loop).
Regarding if-else statement the short answer is: it depends.
Sometimes I would use if (note: in your case else is useless). But other times I would use ternary operator: condition ? value_if_true : value_if_false; or even a lambda expression.
In this case you should probably settle for an if, as it will be easier and more intuitive for you.
Aside from the C++ aspect, think about the steps you need to do to figure out if a number is greater than a certain value. Then do that for all the numbers in the array, and print out the number if it's greater than n. Since you have a 'for' loop, it looks like you already know how to do a loop and compare numbers in C++.
Also, it looks like in your arrayFunction you are trying to input values? You can't input a whole array's worth of values in a single statement like you appear to be trying (also, 'values' is not the name of any variable in arrayFunction, so that would not be recognized when you try to compile it).

How do I go about editing the variables in a struct array?

I've Googled, asked my classmates, and finally asked my professor about this particular problem, but I haven't achieved a solution yet. I'm hoping someone here can help me out.
Basically, I need to make an array of structs that will contain 4 pieces of information per struct: country name, country population, country area, and country density. This information will be written to the structs in the array from a .txt document. This info will then be written onto the console from said array.
Unfortunately, in attempting to write anything to the structs in the array, I get 2 errors. "Cannot convert from 'const char[8]' to 'char [30]'" and "no operator '[]' matches these operands, operand types are: CountryStats [int]". These errors both refer to the line:
countries[0].countryName = "A";
Keep in mind that I have only started to use structs and this is the first time I've used them in an array. Also, I must use an array, as opposed to a vector.
Here's my code:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
struct CountryStats;
void initArray(CountryStats *countries);
const int MAXRECORDS = 100;
const int MAXNAMELENGTH = 30;
struct CountryStats
{
char countryName[MAXNAMELENGTH];
int population;
int area;
double density;
};
// All code beneath this line has been giving me trouble. I need to easily edit the
// struct variables and then read them.
int main(void)
{
CountryStats countries[MAXRECORDS];
initArray(*countries);
}
void initArray(CountryStats countries)
{
countries[0].countryName = "A";
}
As of now I am just attempting to figure out how to write information to a struct within the array and then read the information off of it onto the console. Everything else should fall into place after I find the solution to this.
Oh, and one final note: I have not quite learned the function of pointers (*) yet. I am still relatively new to C++ as my past programming education has been primarily in Java. Any and all inclusions of pointers in this code have been influenced by my classmates and professor in the pursuit of solving this problem.
Thanks in advance!
Two problems
void initArray(CountryStats countries)
must be:
void initArray(CountryStats *countries)
And you must use strcpy to copy c style string. (but i suggest to use c++ string instead of char[])
strcpy(countries[0].countryName,"A");
But I say again, use c++ features like vector<> and string.
You are not defining a definition for:
void initArray(CountryStats *countries);
but for:
void initArray(CountryStats countries);
in which countries is not an array. Since no operator[] is defined for CountryStats, the expression countries[0] fails to compile.
Since you cannot use std::vector (for some weird reasons), I'd suggest you to use an std::array:
template<std::size_t N>
void initArray(std::array<CountryStats, N>& ref) {
for (std::size_t i = 0; i < N; i++)
// initialize ref[i]
}
Of course, if you feel masochist, you can also use a C-style array:
void initArray(CountryStats* arr, int size) {
for (int i = 0; i < size; i++)
// initialize arr[i]
}
But you'll, probably, need to provide the dimension of the array as a second parameter.

Segmentation fault in File I/O

I have written a code to read a file, store it in a structure and just display it. But somehow it is giving me a segmentation fault and I dont know why. Can someone please help me?
Output:
file: /home/neel/map2.txt
file opened
Start Intersection
a->road: 4
a->roadId[0]: 1
a->lane[0][0]: 2
a->lane[0][1]: 2
a->roadId[1]: 2
a->lane[1][0]: 2
a->lane[1][1]: 2
a->roadId[2]: 3
Segmentation fault
Code:
#include <iostream>
#include <fstream>
#include <stdio.h>
using namespace std;
struct Intersection
{
unsigned short road;
long long int *roadId;
short *lane[2];
};
int main(int argc, char** argv)
{
std::ifstream file;
cout<<"file: "<<argv[1]<<endl;
file.open(argv[1], std::ios::in);
cout<<"file opened"<<endl;
while (!file.eof())
{
cout<<"Start Intersection"<<endl;
Intersection *a = new Intersection;
file>>a->road;
a->roadId = new long long int[a->road];
a->lane[0] = new short[a->road];
a->lane[1] = new short[a->road];
cout<<"a->road: "<<a->road<<endl;
for (int i=0; i<a->road; i++)
{
file>>a->roadId[i];
cout<<endl<<"a->roadId["<<i<<"]: "<<a->roadId[i]<<endl;
file>>a->lane[i][0];
cout<<"a->lane["<<i<<"][0]: "<<a->lane[i][0]<<endl;
file>>a->lane[i][1];
cout<<"a->lane["<<i<<"][1]: "<<a->lane[i][1]<<endl;
}
cout<<"Intersection inserted"<<endl;
delete a;
}
}
Text file:
4
1
2
2
2
2
2
3
2
2
4
2
2
Your lane is an array of 2 elements, however when i reaches 2 in your inner loop you are trying to print a->lane[2][0], which doesn't exist.
file>>a->lane[i][0]; //wrong
file>>a->lane[i][1]; //wrong
The indices should be reverse:
file>>(a->lane[0][i]); //correct
file>>(a->lane[1][i]); //correct
I added brackets just for clarity.
Besides, there is memory leak in your program. There should be as many delete as there are new statements, to ensure that there is no memory leak. So write these:
delete [] a->roadId;
delete [] a->lane[0];
delete [] a->lane[1];
delete a; //you've written only this!
Note delete a should be the last statement when deallocating the memory!
I don't mean to be nasty, but this code has enough problems it's almost difficult to decide which ones to start with.
using namespace std;
Here's the first red flag. About all I can say is that using namespace std; is a poor idea. With other namespaces it can be acceptable, but with std, it should always be avoided (IMO).
struct Intersection
{
unsigned short road;
long long int *roadId;
short *lane[2];
};
This strikes me as a pretty poorly designed structure. std::vector is a good thing. Use it. Rather than just a structure of dumb data, you might want to consider defining operator>> for your structure type, so you can read one directly. Even if you don't do that, from the way you're using it, what you really want is something more like:
struct road {
long long Id;
short lane[2];
};
struct Intersection {
int road_count;
road *roads;
};
Then, rather than a couple of parallel arrays all the same size that have to be walked in parallel, you get a a number of roads, each with its own data. std::vector is still better though.
int main(int argc, char** argv)
{
std::ifstream file;
cout<<"file: "<<argv[1]<<endl;
file.open(argv[1], std::ios::in);
Rather than defining an ifstream object and then opening it separately, you should normally plan on passing the name to the ctor so it's defined and opened in a single operation, something like:
std::ifstream file(argv[1]);
But, you also normally want to add a bit of error checking so you only attempt to use the command line argument as a file name if one has been passed, something like this:
if (argc < 2) {
std::cerr << "Usage: your_command <filename>\n";
return EXIT_FAILURE;
}
Then you'd have the code to define the ifstream.
while (!file.eof())
Here's another major problem. A loop of this form is essentially always wrong (including this case, from the looks of things).
cout<<"Start Intersection"<<endl;
Intersection *a = new Intersection;
There seems to be no reason to allocate this dynamically. Are you, perhaps, a recovering (or perhaps not recovering) Java or C# programmer? Java requires that all objects of user defined classes be allocated dynamically, but C++ does not.
file>>a->road;
a->roadId = new long long int[a->road];
a->lane[0] = new short[a->road];
a->lane[1] = new short[a->road];
cout<<"a->road: "<<a->road<<endl;
for (int i=0; i<a->road; i++)
{
file>>a->roadId[i];
cout<<endl<<"a->roadId["<<i<<"]: "<<a->roadId[i]<<endl;
file>>a->lane[i][0];
cout<<"a->lane["<<i<<"][0]: "<<a->lane[i][0]<<endl;
file>>a->lane[i][1];
cout<<"a->lane["<<i<<"][1]: "<<a->lane[i][1]<<endl;
}
I'd prefer to separate the code for reading data from the code for displaying data. Except for things like homework (or debugging) you rarely want to display lots of raw data as you're reading it. In any case, the reading code should normally reside in the operator>> for that class, and the display code in operator<< for the class.
cout<<"Intersection inserted"<<endl;
This seems to be an outright falsehood. You haven't actually inserted an Intersection into anything.
delete a;
When you quit allocating the Intersection dynamically, you'll be able to eliminate this as well. If you insist on handling all the dynamic allocation by hand, you need to delete the components before this to avoid having memory leaks (another reason to prefer to std::vector).
I know that may sound pretty negative, and that leaves me a bit torn. On one hand, I'd really like to suggest better ways to do things. At the same time, this looks enough like homework that I'm extremely hesitant to just post better code either. I've tried to include a few hints about better ways, but realize they're probably not quite as specific as you'd like -- I apologize for that, but given that it's probably homework I don't think I can be a lot more specific.

how do you add value in runtime to structural arrays (in c++)

This question was migrated 12 years ago.
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int main (){
int a,b;
b = 0;
cout<<" this is a family profiling program to test my knowledge of structural arrays. ";
cin>> a;
struct p {
char name[20];
int age;
char hobby[40];
char favcolor[15];
};
p family[2];
**cin.getline(family.name[0]);**
cout<<"enter the name of family member"<<b+1;
I am trying to use this code to create a family profiling program, i know how to add value to an array or structural array during compiler time but not to use cin or cin.getline to add a value to to a specific value in a specific structure of an array.
please respond with a simple answer; Im still new to programming.(my attempt is bolded
If you insist on using an array, the easiest way to do this (add elements to a fixed-size array) would be to copy everything to a NEW array, including the new item.
A much better way would be to use a dynamic structure, such as a linked list. The standard template library and the boost library have many ways to help you here, but you could also easily implement a simple linked list on your own (or find code for it).
As Mike Chess said, this is probably best asked on http://www.stackoverflow.com
(also, to get your code formatted nicely, edit your post, select the code section, and click the button with the ones and zeros icon just above the text area)
Firstly, you'll find it much easier to write reliable code if you use std::string instead of character arrays. You were nearly on the right track though: instead of family.name[0] try family[0].name, then getline will work with std::string as below...
struct p
{
std::string name;
// other stuff...
};
if (getline(std::cin, family[0].name))
{
// it worked!
...
}
The "high performance" and old school option is to use realloc like this.
p * family = malloc(sizeof(p)*2);
family = realloc(family, sizeof(p)*13);
Of course this doesn't invoke constructors, and is not really acceptable in C++ generally. So your best option is.
#include <list>
using namespace std;
...
list<p> family;
p blah;
family.push_back(blah);
That's a linked list so it's perfect for datasets of unknown length. Same code can be used for an STL vector, which if you predict the size of your input in advance well enough will give you a performance boost.