Taking Input to Arrays Issue - c++

I'm creating a console timetable application in which you can create a timetable, change it, and delete it. I'm on the stage of taking the input for the calculator. However, when I run the code, as soon as I finish taking the input, the window just closes. Here is the code:
int input()
{
int numberOfElements;
cout << "How many items do you want in your timetable? ";
cin >> numberOfElements;
char* itemArray[numberOfElements] = {};
for (int i = 1; i <= numberOfElements; i++)
{
cout << "Please enter a session: ";
cin >> itemArray[i];
}
for (int i = 0; i < numberOfElements; i++)
{
cout << itemArray[i] << "\n";
}
return 0;
}
There is some code in the main function as well, but it's irrelevant (only to find out for what day it is). I want you to have a look at the first for loop in the code, where I take in input. When running this code (in a separate window altogether), it closes as soon as I give in the input. Even if I say that I want 3 sessions (or any number), it closes right after I input the first session. In case you were wondering, I already tried replacing
char* itemArray[numberOfElements] = {};
with
char* itemArray[numberOfElements];
Just in case it's useful to anyone, I'm using the MinGW compiler.
Thanks.

In Standard C++ the size of an array must be a compile time constant. So take for example the following statements in your program:
int numberOfElements;
cout << "How many items do you want in your timetable? ";
cin >> numberOfElements;
char* itemArray[numberOfElements] = {};//not standard C++
The statement char* itemArray[numberOfElements] = {}; is not standard C++ because numberOfElements is not a constant expression.
Additionally, you're going out of bounds of the array because of the <= in the for loop instead of <. This leads to undefined behavior.
Better would be to use std::vector<std::string> as shown below:
#include <iostream>
#include<vector>
#include <string>
int main()
{
int numberOfElements;
std::cout << "How many items do you want in your timetable? ";
std::cin >> numberOfElements;
std::vector<std::string> arr(numberOfElements); //create vector of size numberOfElements
for (std::string &element: arr)
{
std::cout << "Please enter the element: ";
std::cin >> element;
}
for (const std::string& element: arr)
{
std::cout << element << "\n";
}
}
Demo.

Related

How Do I Code a Contact List Program in C++ Using Functions & Vectors?

I am trying to write a contact list program in the C++ programming language and I think I have a good base set up for one. The premise of the program is that two vectors of values are entered. One vector for the contact name and another for the phone number. Once a few of these values are taken in by the program, a single contact name is supposed to signify to the program that its corresponding phone number should be outputted.
(Note: The '3' is supposed to tell the program how many values are to be stored in each vector. In this case, it is 3 contact names and 3 phone numbers.)
Ex. Input: 3 Joe 123-5432 Linda 983-4123 Frank 867-5309 Frank
Ex. Output: 867-5309
But I am getting an error message that reads, "Exited with return code -11 (SIGSEGV)." I'm not sure where I could be leaking any memory but maybe I just can't see it.
Any help that can fix this error would be greatly appreciated.
Below is code that I have written so far:
#include <iostream>
#include <vector>
using namespace std;
string GetPhoneNumber(vector<string> nameVec, vector<string> phoneNumberVec, string contactName) {
string theName;
string thePhoneNum;
string theContName;
int N;
int nElements;
cin >> N;
cin >> theName;
cin >> thePhoneNum;
cin >> theName;
cin >> thePhoneNum;
cin >> theName;
cin >> thePhoneNum;
nameVec.push_back(theName);
phoneNumberVec.push_back(thePhoneNum);
cin >> contactName;
nElements = phoneNumberVec.size();
for (int i = 0; i < nElements; i++) {
if (i == N) {
return phoneNumberVec.at(i);
}
}
}
int main() {
vector<string> nameVec;
vector<string> phoneNumberVec;
string contactName;
cout << GetPhoneNumber(nameVec, phoneNumberVec, contactName) << endl;
return 0;
}
The issue is that you are supposed to return a std::string from GetPhoneNumber, but there are code paths where no return is specified.
What happens is that the program has now invoked undefined behavior, as returning no value from a function that's supposed to return a value leads to undefined behavior occurring.
The fix is to return a std::string from the GetPhoneNumber function from all code paths. Namely right here:
for (int i = 0; i < nElements; i++) {
if (i == N) {
return phoneNumberVec.at(i);
}
}
return ""; // or some appropriate string.
}
To prove that this is the issue, if you do not have that return statement, and instead did this:
for (int i = 0; i < nElements; i++) {
if (i == N) {
return phoneNumberVec.at(i);
}
}
std::cout << "There will be a problem" << std::endl;
}
You will see the string,
There will be a problem
outputted, proving you are reaching that point in the function without returning a value.
Here is a live example.
The other issue is that i could never equal N, since a std::vector uses 0-based indexing. If N is 1, then the highest index for i will be 0.
The fix is to compare i to N-1.

How to determine number of values added to vector in C++?

I'm trying to build a little task using C++ in which I need to allow the user to determine up front how many gross_paychecks they would like to place in a vector called 'gross_paychecks_vector'.
So far this is what I have:
vector<double> gross_paychecks_vector (5);
double gross_paychecks;
// Add 5 doubles to vector
cout << "Please enter an integer" << endl;
cin >> gross_paychecks;
for(gross_paychecks = 0; gross_paychecks <= gross_paychecks_vector; ++gross_paychecks ){
cin >> gross_paychecks;
}
Right now I'm somewhat lost because I'm not sure whether to switch the vector to something like vector<double> gross_paychecks {} because it throws an error in the for loop.
Also I'm not sure how to go with the for loop (should I actually use a for-loop or something else?). I need to accept input from the user as long as it has not met the numbers of gross_paychecks that he/she has specified.
You probably want this:
vector<double> gross_paychecks_vector; // initially the vector is empty
...
cout << "How many paychecks:" << endl;
cin >> gross_paychecks;
for (int i = 0; i < gross_paychecks; i++)
{
double value;
cin >> value;
gross_paychecks_vector.push_back(value); // add new value to vector
}
// display values in vector
for (auto & value : gross_paychecks_vector)
{
cout << value << "\n";
}
Additionally. If you want to use modern C++ features, you would use:
#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
int main()
{
std::vector<double> grossPaychecks{};
std::cout << "How many paychecks:\n";
size_t numberOfPaychecks{0};
std::cin >> numberOfPaychecks;
// Read all data
std::copy_n(std::istream_iterator<double>(std::cin),numberOfPaychecks, std::back_inserter(grossPaychecks));
// Print all data
std::copy(grossPaychecks.begin(), grossPaychecks.end(), std::ostream_iterator<double>(std::cout,"\n"));
return 0;
}

I'm having trouble dynamically allocating my struct

I created a simple program to help me understand how to Dynamically Allocate a structure. I want the program to gets 5 names and 5 accounts from the user, and display the names and the accounts. I know a pointer is like a reference variable, the only differences instead of passing the value, it passes the address of the variable. I set a breaking point for line 23 ("getline(std::cin,clientPtr[count].name);"), line 25 ("std::cin.ignore(std::numeric_limits::max(),'\n');"),
line 27 ("std::cin >>clientPtr[count].accounts;"), line 40 ("std::cout <<"Name:" << clientPtr[count].name;"), line 41 ("std::cout <<"Name:" << clientPtr[count].name;"),line 31( showInfo(&client);). When I debugged it shows that line 41 is not executing. It should display the names and the accounts of each client. In this case it's not. I'm not sure why, just a little background on me, I'm new to C++, as well with using the debugger. I'm using xcode 8.2 and the debugger I am using is lldb. I'm here to learn, so anything will help. Thanks.
#include <iostream>
#include <limits>
struct BankInfo
{
std::string name;
std::string accounts;
};
void showInfo(BankInfo*);
int main()
{
BankInfo client;
BankInfo* clientPtr=nullptr;
clientPtr = new BankInfo[5];
for(int count =0; count < 5; count++)
{
std::cout << "Enter your name:";
getline(std::cin,clientPtr[count].name);
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
std::cout << "Enter you account number:";
std::cin >>clientPtr[count].accounts;
}
showInfo(&client);
return 0;
}
void showInfo(BankInfo* clientPtr)
{
for(int count =5; count < 5; count++)
{
std::cout <<"Name:" << clientPtr[count].name;
std::cout <<"Account:" << clientPtr[count].accounts;
}
}
You are handing the wrong thing to showInfo(). You have two variables.. a single BankInfo variable and a dynamic allocated array with size 5.
You want to iterate over the latter and not the former.
Changing showInfo(&client);to showInfo(clientPtr); should do the trick perhaps?
So I fixed the solution I made several mistakes, but thank you for the suggestion. Here's what I did.
#include <iostream>
#include <limits>
struct BankInfo
{
std::string name;
std::string accounts;
};
void showInfo(BankInfo*);
int main()
{
BankInfo client;
BankInfo* clientPtr=nullptr;
clientPtr = new BankInfo[5]; //Allocate an array of BankInfo struct on the heap
for(int count =0; count < 5; count++)
{
std::cout << "Enter your name:";
getline(std::cin,clientPtr[count].name); // stores the value in the name member
std::cout << "Enter you account number:";
std::cin >>clientPtr[count].accounts; // stores the value in accounts member
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
}
showInfo(clientPtr);
delete [] clientPtr;
clientPtr = nullptr;
return 0;
}
void showInfo(BankInfo* clientPtr)
{
for(int count =0; count < 5; count++)
{
std::cout <<"\nName:" << clientPtr[count].name; // dereference the pointer to the structure
std::cout <<"\nAccount:" << clientPtr[count].accounts; // dereference the pointer to the structure
}
}
for(int count=1 ; count<=5 ; count++)
{
//do your stuff here
}

Stumped on array creation program

For a program I must use an array and not vector. I have to take in user's input, and it's a indefinite amount of them. The user can type in 5 values, or 50. I am absolutely stumped as to how to go about doing this. Using a for loop for example:
Int a[10];
Int b;
For (int i=0; i<10; i++)
{
Cout<<"enter values:";
Cin>>b;
A[i]=b;
}
With this I can take an array of 10 of user defined variables but how would I go about making it a dynamic size? Thank you for the help!
The size of a static array must be known at compile time, otherwise you must use a dynamic array. For example
#include <iostream>
int main()
{
// Determine how many total entries are expected
int entries;
std::cout << "How many values do you want to enter?" << std::endl;
std::cin >> entries;
// Allocate a dynamic array of the requested size
int* a = new int[entries];
// Populate the array
for (int i = 0; i < entries; ++i)
{
std::cout << "enter a value: ";
std::cin >> a[i];
std::cout << std::endl;
}
// Clean up your allocated memory
delete[] a;
return 0;
}

How to use a sentinel to trigger end of vector?

I'm new to programming (in general) and C++ (in particular). I'm learning vectors and am trying to write a simple program that:
allows the user to enter a vector of students' test scores
when the user types the sentinel (-1 in this case), the vector terminates
outputs a tally of the student's grades
Here's my code:
#include "stdafx.h"
#include <iostream>
#include <vector>
using namespace std;
const int SENTINEL = -1;
vector<int> studentGrades = { 0 };
int myInput;
int main()
{
do
{
cout << "Please enter a student's grade: ";
cin >> myInput;
if (myInput < 1000)
{
studentGrades[myInput]++;
}
studentGrades.push_back(myInput);
} while (myInput != SENTINEL);
cout << "\n";
for (int i = 0; i < 1000; i++)
cout << i << " grade(s) of " << studentGrades[i] << endl;
return 0;
}
Two questions:
1) Can anyone provide guidance on why this code is only allowing me to enter one student's grade?
2) Is the for loop that compute the "tally" correct?
Thanks in advance for taking a look,
Ryan
* REVISED CODE *
# JCx - this is the revised code:
#include "stdafx.h"
#include <iostream>
#include <vector>
using namespace std;
const int SENTINEL = -1;
vector<int> studentGrades = { 0 };
int myInput;
int main()
{
do
{
cout << "Please enter a student's grade (or -1 to QUIT): ";
cin >> myInput;
if (myInput < 1000)
{
studentGrades.at(myInput)++;
}
studentGrades.push_back(myInput);
} while (myInput != SENTINEL);
cout << "\n";
for (int i = 0; i < 1000; i++)
cout << i << " grade(s) of " << studentGrades.at(myInput) << endl;
return 0;
}
and, I'm seeing this error:
Unhandled exception at 0x7707C42D
Microsoft C++ exception: std::out_of_range at memory location 0x0035F890
There's more than one problem. The attempt to access studentGrades[-1] when the users enters your sentinel value, and the fact that the default vector only contains an entry for 0 and the use of push_back.
Let's just walk through some of the problems:
User runs program. User enters 100. studentGrades[100] is out of range. Undefined behaviour occurs as the vector only has one element.
User runs program, enters -1 studentGrades[-1] is out of range.
User runs program, enters 0. studentGrades[0] is in range, incremented to 1. studentGrades.push_back(1) adds an element to the vector studentGrades[1] is now also equal to 1.
As a great starting point, if you swap your subscript vector references for the vector at method as I've shown below you will get out-of-range errors which will help (a lot). The code below still needs work but at least you'll have run-time errors instead of odd behaviour.
int main()
{
do
{
cout << "Please enter a student's grade: ";
cin >> myInput;
if (myInput < 1000)
{
studentGrades.at(myInput)++;
}
studentGrades.push_back(myInput);
} while (myInput != SENTINEL);
cout << "\n";
for (int i = 0; i < 1000; i++)
cout << i << " grade(s) of " << studentGrades.at(myInput) << endl;
return 0;
}
I think if I was implementing this I'd be using std::map instead of a vector. It would let you have a studentGrade[1000] without having to allocate memory for studentGrade[0] to [999] first.
However as you are learning about std::vector check out vector::resize to set the vector big enough for the required elements, std::vector::size to find out whether you need to increase the size. You could then ditch the push_back.
References
vector::at http://www.cplusplus.com/reference/vector/vector/at/
vector::size http://www.cplusplus.com/reference/vector/vector/size/