C++, Array - Windows Error Crash but no Compiler Error - c++

Ok so here's my code. I'm getting no errors in the compiler, however when I run this program it lets me input 2 names then crashes with a Window's Error. What in the heck am I doing wrong?!
#include <iostream>
using namespace std;
//declaration of variables
int i; // Loop Counter
int x; // Number of Family Members
int main()
{
string FamilyName[x]; // Array of Names
cout << "Enter Number of Family Members" <<endl;
cin >> x;
for (i = 0 ; i < x ; i++){
cout << "Enter Family Member's Name: " <<endl;
cin >> FamilyName[i];
}
for (i = 0 ; i < x ; i++){
cout << FamilyName[i] <<endl;
}
return 0;
}

You can solve the problem in two ways, allocate the array to a large size(x should be initialized...and it should be a constant value) and then the code becomes:
#include <iostream>
#include <string>
using namespace std;
//declaration of variables
int i; // Loop Counter
const int x = 500; // MAX Number of Family Members
int main()
{
string FamilyName[x]; // Array of Names
int count;
cout << "Enter Number of Family Members" <<endl;
cin >> count;
for (i = 0 ; i < count ; i++){
cout << "Enter Family Member's Name: " <<endl;
cin >> FamilyName[i];
}
for (i = 0 ; i < count ; i++){
cout << FamilyName[i] <<endl;
}
return 0;
}
Or use dynamic memory allocation to read the number of family member first and then do the allocation:
int main()
{
int count;
cout << "Enter Number of Family Members" <<endl;
cin >> count;
auto FamilyName = new string[count];
for (i = 0 ; i < count ; i++){
cout << "Enter Family Member's Name: " <<endl;
cin >> FamilyName[i];
}
for (i = 0 ; i < count ; i++){
cout << FamilyName[i] <<endl;
delete[] FamilyName;
}
Hope this helps

You are not allocating any memory to your string array, on this line string FamilyName[x]; // Array of Names x is not defined. It also may be a good idea to set a max array size or have some way of pushing on to the end of the array.

The size of your array should be constant.
Maybe use a vector of strings since vectors can grow dynamically.
string name;
vector<string> FamilyName;
for(int i = 0; i < x; i++)
{
cin >> name;
FamilyName.push_back(name);
}
Either that or give your array a constant size larger than any family size you might encounter.
string FamilyName[100];
if you wouldn't ever get a family with over 100 members.

You need to either allocate reasonable memory for FamilyName or use STL:
string[] FamilyName;
//after get x
FamilyName = new string[x];
or
vector<string> FamilyName;
cin << temp_string;
FamilyName.push_back(temp_string);

Related

Missing integer when printing out from array after certain length

I have the following code:
#include <iostream>
using namespace std;
int main()
{
int length = 0;
int arrA[length];
cout << "Enter the length : ";
cin >> length;
cout << "Enter " << length << " integers for array : ";
for(int i = 0; i < length; i++)
{
cin >> arrA[i];
}
cout << "Array A : ";
for(int i = 0; i < length; i++)
{
cout << arrA[i] << " ";
}
cout << endl;
}
The above require the user to input the length of array followed by the integers that will be store in array. It work but the printing of the array value is incorrect when I input length 8 and above.
Working
Enter the length : 7
Enter 7 integers for array : 7 6 5 4 3 2 1
Array A : 7 6 5 4 3 2 1
Not working
Enter the length : 8
Enter 8 integers for array : 8 7 6 5 4 3 2 1
Array A : 8
Could this be due to memory issue or something?
int length = 0;
int arrA[length];
This creates an array of size zero
cout << "Enter the length : ";
cin >> length;
This sets the length variable to a value entered by the user but doesn't change the size of arrA which has already been created.
You obviously think that when the length variable changes that the array arrA will change as well, but this is not true.
Because you are accessing elements of an array which has zero size the behaviour of your program is undefined.
In addition this whole approach is incorrect because
int length;
...
int arrA[length];
is not legal C++. Because length is a variable this is a variable length array or VLA. VLAs are legal in C but are not legal in C++.
The best way to write this code in C++ is to use a vector. A vector is the C++ improvement on a C array.
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int length;
cout << "Enter the length : ";
cin >> length;
vector<int> arrA(length);
...
int length = 0;
int arrA[length];
This is not valid C++.
What you may want to do is:
int *arrA = new int[length];
after cin >> length.
You will have to free the pointer later with delete[] arrA;
It is not due to a memory issue. But because variable length arrays are not part of the C++ standard.
length is a variable length array.
Read more about variable length arrays
Here
Here is the code if you do not want to use a vector. I would suggest not to use this for multifarious reasons. But go ahead and knock yourself out.
#include <iostream>
using namespace std;
int main()
{
int length = 0;
int *arrA = new int [length];
cout << "Enter the length : ";
cin >> length;
cout << "Enter " << length << " integers for array : ";
for (int i = 0; i < length; i++)
{
cin >> arrA[i];
}
cout << "Array A : ";
for (int i = 0; i < length; i++)
{
cout << arrA[i] << " ";
}
delete[] arrA;
cout << endl;
return 0;
}

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

Some weird exception throws

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

Printing Multidimensional Array C++

How do I print out this multi-dimensional vector? I just can't figure out what to put as a condition in the inner loop in my print section in the code below. I can't seem to figure out how to loop through the array to print grades. Any help would be appreciated.
#include <iostream>
using namespace std;
int main()
{
int course, grades;
int** crsgrd;
// get inputs and asign grades
cout << "Enter number of courses: ";
cin >> course;
crsgrd = new int * [course];
for (int c = 0; c < course; c++) {
cout << "Enter number of grades: ";
cin >> grades;
crsgrd[c] = new int[grades];
for(int g = 0; g < grades; g++) {
cout << "Enter your grade: ";
cin >> crsgrd[c][g];
}
}
// print grade report
for(int c = 0; c < course; c++) {
for(int g = 0; g <= ?????????; g++)
cout << crsgrd[c][g] << " ";
cout << endl;
}
// free the array
for(int i = 0; i < course; i++)
delete [] crsgrd[i];
delete [] crsgrd;
return 0;
}
g < crsgrd[c].size()
Alternatively, you could create your own size function if this is some kind of assignment that doesn’t allow built in functions.
You have created a 2D array, not a standard vector. Arrays do not store their length, so you have to either come up with a way to store the length or switch to another type of storage container.
Here is an example that stores the number of grades as the first element of the array for a given course:
#include <iostream>
using namespace std;
int main()
{
int course, grades;
int** crsgrd;
// get inputs and asign grades
cout << "Enter number of courses: ";
cin >> course;
crsgrd = new int * [course];
for (int c = 0; c < course; c++) {
cout << "Enter number of grades: ";
cin >> grades;
crsgrd[c] = new int[grades + 1]; // extra cell for # of grades
crsgrd[c][0] = grades;
// start storing grades at cell [c][1] as the first cell has the length
for(int g = 1; g < grades+1; g++) {
cout << "Enter your grade: ";
cin >> crsgrd[c][g];
}
}
// print grade report
for(int c = 0; c < course; c++) {
cout<< "Course #" << c+1 << " grades:" << endl;
// use first element as limit for for loop.
// Be sure to print one more element as we have an extra cell
// at the end.
for(int g = 1; g < crsgrd[c][0] + 1; g++)
cout << crsgrd[c][g] << " ";
cout << endl;
}
// free the array
for(int i = 0; i < course; i++)
delete [] crsgrd[i];
delete [] crsgrd;
return 0;
}

why does my counter increase according to the lens of char input in C++

I'm picking up on C++ recently and is trying to code a program which prompts for names for a defined no. of times and inserts each of the input into an array of size-5. The problem happened when I tried to run the following code, my counter, i increases according to the no of len the user input. Why is that so?
#include <iostream>
using namespace std;
int main(){
const int SIZE = 5;
char name[SIZE];
int i;
for (i = 0; i < SIZE; i++){
if (strlen(name) <= 50) {
cout << "Enter a name: \n";
cin >> name[i];
}
}
for (i = 0; i < SIZE; i++){
cout << name[i] << endl;
}
return 0;
}
Output:
if (strlen(name) <= 50) {
You should not call strlen on array which is not initialized.
Use array of strings otherwise
cout << name[i] << endl;
refers to i-th character, not entire string. Or if you want to go with char arrays, you'd need a two dimensional array.
I thing what you indended to do was :
#include <iostream>
using namespace std;
int main(){
const int SIZE = 5;
string names[SIZE];
int i;
for (i = 0; i < SIZE; i++){
cout << "Enter a name: \n";
string name;
cin>>name;
if (strlen(name) <= 50) {
cin >> names[i];
}
}
for (i = 0; i < SIZE; i++){
cout << name[i] << endl;
}
return 0;
}
UNTESTED
The second for loop, which does the output, does this in single characters, incrementing i each time.
To output the string all at once assign a string pointer to name[0] and send that to cout.