Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 15 days ago.
Improve this question
Here is my program, it is using c++ and I done it on MacOS VSCode.
Library:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <string>
#include <iomanip>
using namespace std;
Function:
float* read_data(int& size){
int a_size = 0;
static float a[10];
float* temp = a;
cout << "Please enter values, and press 'Q' when finished: ";
for (int i = 0; i < size; i++){
cin >> a[i];
if (cin.fail()){
break;
}else{
a_size++;
}
}
cin.clear();
size = a_size;
return temp;
}
Main function:
int main(){
int size1 = 10;
int size2 = 10;
int size3 = 0;
float array[10];
float addarray[10];
float longarray[20];
float* ptr = array;
float* addptr = addarray;
float* longptr = longarray;
cout << fixed << setprecision(2);
ptr = read_data(size1);
cout << setw(15) << "Original array" << setw(5) << "=" << setw(5) << "{ " << *ptr;
for (int i = 0; i < size1; i++){
cout << ", " << *(ptr + i);
}
cout << " }" << endl;
for (int i = 0; i < size1; i++){
*(longptr + size3) = *(ptr + i);
size3++;
}
addptr = read_data(size2);
for (int i = 0; i < size2; i++){
*(longptr + size3) = *(addptr + i);
size3++;
}
cout << setw(15) << "New array" << setw(5) << "=" << setw(5) << "{ " << *longptr;
for (int i = 0; i < size3; i++){
cout << ", " << *(longptr + i);
}
cout << " }" << endl;
return 0;
}
The main objective of the program was to prompt the user for an array, maximum of 10 elements. Prompting the user was done using the float* read_data(int& size) function.
The program would echo or print out the inputted array.
After that, the user was prompt for a second time using the same function to get another array of elements, in this case is a list of float values.
Then, the program would use a dynamic data allocation (DMA) technique to combine the two array into one long array. The new array will be printed out and the program is terminated.
Problem
As I said before, the program are supposed to prompt the user for inputs every time the read_data() were called.
I called the function twice. It did run twice, but failed to prompt the user for input the second time around.
I thought the problem was due to the cin.fail() arguments. That is why I tried to mess with the cin.ignore() and cin.clear() either by removing them or only using one of them.
I am honestly at lost on what is the root of the problem.
The heart of the issue is that you want users to enter 'Q', a char, into your float variable.
Here's a small example:
#include <iostream>
int main() {
int a;
std::cin >> a;
if (std::cin.fail()) {
std::cout << "Fail.\n";
} else {
std::cout << "All clear.\n";
}
std::cin >> a;
std::cout << (2 * a) << '\n';
}
Output:
~/tmp
❯ ./a.out
Q
Fail.
0
~/tmp
❯ ./a.out
3
All clear.
3
6
So, you can see that you were on the right track. The issue is that if std::cin did fail, you are now responsible to clean up your mess.
std::cin.clear() is a good start. It resets the fail flag bits. But the stream is still in a bad state. What you haven't done is clean it up completely.
You're calling std::cin.ignore(), but leaving the parameter list empty.
Something like this is best practice:
#include <iostream>
#include <limits>
int main() {
int a;
std::cin >> a;
if (std::cin.fail()) {
std::cout << "Fail.\n";
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cin.clear();
} else {
std::cout << "All clear.\n";
}
std::cin >> a;
std::cout << (2 * a) << '\n';
}
Output:
~/tmp
❯ ./a.out
Q
Fail.
3
6
While that should fix address the question, your code is still fundamentally broken.
EDIT
Here's a mini-code review:
#include <iostream>
#include <algorithm> // These includes
#include <cmath> // are
#include <cstdlib> // not
#include <string> // used
#include <iomanip>
using namespace std; // Bad practice
// You should not attempt to return a C-style array
float* read_data(int& size){ // Why is the size being passed by reference?
int a_size = 0;
static float a[10]; // Not doing what you think
float* temp = a;
cout << "Please enter values, and press 'Q' when finished: ";
for (int i = 0; i < size; i++){ // Formatting; should be ") {"
cin >> a[i];
if (cin.fail()){ // Addressed above; root cause of your question
break;
}else{
a_size++;
}
}
cin.clear();
size = a_size;
return temp;
}
// While I assume the goal of the assignment is to get familiar with pointers,
// This assignment is trivial with vectors.
int main(){
int size1 = 10; // If declared const/constexpr, you'd only need one **
int size2 = 10; // These are bad names
int size3 = 0; // Front loading declarations is bad practice.
float array[10]; // ** And could use that variable here to avoid the magic number
float addarray[10];
float longarray[20]; // Not dynamic per your requirements.
float* ptr = array; // Still not dynamic, also unnecessary given the prior declarations
float* addptr = addarray;
float* longptr = longarray;
cout << fixed << setprecision(2);
ptr = read_data(size1);
// The first cout is not good, what do you think *ptr will print?
cout << setw(15) << "Original array" << setw(5) << "=" << setw(5) << "{ " << *ptr;
for (int i = 0; i < size1; i++){
cout << ", " << *(ptr + i); // The pointers can still use array syntax
}
cout << " }" << endl;
for (int i = 0; i < size1; i++){
*(longptr + size3) = *(ptr + i);
size3++;
}
addptr = read_data(size2);
for (int i = 0; i < size2; i++){
*(longptr + size3) = *(addptr + i);
size3++;
}
// As soon as you start repeating yourself, consider writing a function.
// The logic will only live in one place, and only need to be changed in
// one place.
cout << setw(15) << "New array" << setw(5) << "=" << setw(5) << "{ " << *longptr;
for (int i = 0; i < size3; i++){
cout << ", " << *(longptr + i);
}
cout << " }" << endl;
return 0;
}
A lot going on that is less than great. The biggest flub appears to be the static array. static in this scenario extends the lifetime of the variable until the end of the program. So, when you call this function the second time, you overwrite the first array with the second because there's only ever one array for every call of that function. In the future, I would refrain from grabbing random code online and just dumping it in your program unless you know what it does.
Now, let's move on to a working solution.
The first thing I'm going to do is state the requirements as I understood them.
Have the user enter data to fill two arrays of floats.
Each array should hold a maximum of ten elements.
The user enters "Q" to indicate that they are finished entering data.
Print the first array.
Tack the second array on to the end of the first, in a dynamic fashion.
Print the combined array.
Anytime you get an assignment, your first task should be to restate the problem in your own words. This will clarify requirements and you will demonstrate to yourself that you understand the problem to be solved.
What makes this interesting is the "Q" to quit. Note that I'm using double quotes. We will read all of our data as strings, and we have to convert to float as needed.
std::stof() exists, but it's not as simple as just calling it. That function can throw exceptions, and we want to ensure that only actual float values get converted.
So we'll wrap that call in a function of our own. Here's an example:
#include <exception>
#include <iostream>
#include <string>
class bad_user_input : public std::exception {
const char* what() const noexcept override {
return "User input was not valid.";
}
};
float convert_string_to_float(const std::string& val) {
std::size_t marker = 0;
float f = 0.0f;
try {
f = std::stof(val, &marker);
} catch(...) {
throw bad_user_input();
}
// Was the entire value entered a float?
if (marker != val.length()) {
throw bad_user_input();
}
// Getting here means a valid float was entered.
return f;
}
int main() {
float f = 0.0f;
// Test the function
try {
f = convert_string_to_float("5.6");
} catch(...) {
std::cerr << "Issue.\n";
}
std::cout << f << "\n\n";
f = 0.0f;
try {
f = convert_string_to_float("5.6cat");
} catch(...) {
std::cerr << "Issue.\n";
}
std::cout << f << "\n\n";
f = 0.0f;
try {
f = convert_string_to_float("Q");
} catch(...) {
std::cerr << "Issue.\n";
}
std::cout << f << '\n';
}
Output:
❯ ./a.out
5.6
Issue.
0
In convert_string_to_float
stof: no conversion
Issue.
0
Now that we can convert strings to floats, with guarantees, we are ready to read values. To test that we're reading correctly, we also want to be able to print our arrays:
#include <exception>
#include <iostream>
#include <string>
class bad_user_input : public std::exception {
const char* what() const noexcept override {
return "User input was not valid.";
}
};
float convert_string_to_float(const std::string& val) {
std::size_t marker = 0;
float f = 0.0f;
try {
f = std::stof(val, &marker);
} catch(...) {
throw bad_user_input();
}
// Was the entire value entered a float?
if (marker != val.length()) {
throw bad_user_input();
}
// Getting here means a valid float was entered.
return f;
}
void read_array_from_user(float* arr, int& size, const int maxCapacity, std::istream& sin = std::cin) {
size = 0;
std::string input;
while (size < maxCapacity && std::getline(sin, input)) {
if (input == "Q" || input == "q" || input.length() == 0) {
return;
}
try {
arr[size] = convert_string_to_float(input);
} catch(const std::exception& e) {
std::cerr << "Bad input. Reason: " << e.what() << "\nTry again.\n";
continue;
}
++size;
}
}
void print_array(float* arr, int size, std::ostream& sout = std::cout) {
sout << "{ ";
for (int i = 0; i < size; ++i) {
sout << arr[i] << (i == size - 1 ? " " : ", ");
}
sout << "}\n";
}
int main() {
constexpr int maxArrayCapacity = 10;
float arrayOne[maxArrayCapacity];
int arrayOneSize = 0;
read_array_from_user(arrayOne, arrayOneSize, maxArrayCapacity);
print_array(arrayOne, arrayOneSize);
}
Output:
~/tmp
❯ ./a.out
1
2
3
4
q
{ 1, 2, 3, 4 }
~/tmp took 3s
❯ ./a.out
1
2
Q
{ 1, 2 }
~/tmp took 2s
❯ ./a.out
1
2
3
4
5
6
{ 1, 2, 3, 4, 5, 6 }
~/tmp took 4s
❯ ./a.out
1
2
3
4
5
6
7
8
9
0
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }
~/tmp took 5s
❯ compilecpp tmp_repair.cpp
~/tmp
❯ ./a.out
1
2
3
4
5
6
7
8
9
0
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }
~/tmp took 4s
❯ ./a.out
1
2
3
q
{ 1, 2, 3 }
~/tmp took 2s
❯ ./a.out
1
2b
Bad input. Reason: User input was not valid.
Try again.
2
3
Q
{ 1, 2, 3 }
~/tmp took 3s
❯ ./a.out
1
2
3
Q
{ 1, 2, 3 }
~/tmp took 2s
❯ ./a.out
1
2
3
{ 1, 2, 3 }
So, we can read an array with a maximum of 10 values. The reading is robust enough to handle typos or obviously bad input. But we don't have to read 10 values, it's the maximum. We keep track of the actual size ourselves.
Take note on how simple the main() function is because we put our sub-tasks into their own functions.
Reading the second array only requires a few lines in our main() now.
int main() {
constexpr int maxArrayCapacity = 10;
float arrayOne[maxArrayCapacity];
int arrayOneSize = 0;
read_array_from_user(arrayOne, arrayOneSize, maxArrayCapacity);
print_array(arrayOne, arrayOneSize);
float arrayTwo[maxArrayCapacity];
int arrayTwoSize = 0;
read_array_from_user(arrayTwo, arrayTwoSize, maxArrayCapacity);
print_array(arrayTwo, arrayOneSize);
}
Easy-peasy there. Now we need to combine the arrays "dynamically."
We know the sizes of our two arrays, so we know the size of the final array. Now we just need to allocate the memory on the heap. I'm not going to use new, which is what I assume you're supposed to do. My reasoning is that C++ has had better methods for managing dynamic allocations since 2011.
#include <memory>
// ...
int main() {
constexpr int maxArrayCapacity = 10;
float arrayOne[maxArrayCapacity];
int arrayOneSize = 0;
read_array_from_user(arrayOne, arrayOneSize, maxArrayCapacity);
print_array(arrayOne, arrayOneSize);
float arrayTwo[maxArrayCapacity];
int arrayTwoSize = 0;
read_array_from_user(arrayTwo, arrayTwoSize, maxArrayCapacity);
print_array(arrayTwo, arrayTwoSize);
int combinedArraySize = arrayOneSize + arrayTwoSize;
// This is considered dynamic; it's allocated on the heap
auto combinedArray = std::make_unique<float[]>(combinedArraySize);
int idx = 0;
for (int i = 0; i < arrayOneSize; ++i) {
combinedArray[idx] = arrayOne[i];
++idx;
}
for (int i = 0; i < arrayTwoSize; ++i) {
combinedArray[idx] = arrayTwo[i];
++idx;
}
print_array(combinedArray.get(), combinedArraySize);
}
Output:
~/tmp
❯ ./a.out
1
2
q
{ 1, 2 }
3
4
5
q
{ 3, 4, 5 }
{ 1, 2, 3, 4, 5 }
Hopefully, the most gnarly stuff is over where you get the user input, mostly due to the requirement that users can enter a letter to signal they're done. And that makes sense since now you have to do type conversions. Other languages like python make it possible with a lot less LOC (Lines Of Code) on your part. The task itself is not difficult, but ensuring users behave is a whole other beast. If you're allowed to assume well-behaved input will always be provided, you can simplify the code quite a bit.
Doing an exercise to find the mean and mode of a list of numbers input by a user. I have written the program and it works, but I'm wondering if my function 'calcMode' is too large for this program. I've just started looking into functions which is a first attempt. Would it be better to write smaller functions? and if so what parts can I split? Im pretty new to C++ and also looking if I can improve this code. Is there any changes I can make to make this run more efficient?
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int calcMean(vector<int> numberList)
{
int originNumber = numberList[0];
int nextNumber;
int count = 0;
int highestCount = 0;
int mean = 0;
for (unsigned int i = 0; i <= numberList.size() - 1; i++)
{
nextNumber = numberList[i];
if (nextNumber == originNumber)
count++;
else
{
cout << "The Number " << originNumber << " appears " << count << " times." << endl;
count = 1;
originNumber = nextNumber;
}
}
if (count > highestCount)
{
highestCount = count;
mean = originNumber;
}
cout << "The Number " << originNumber << " appears " << count << " times." << endl;
return mean;
}
int main()
{
vector<int> v;
int userNumber;
cout << "Please type a list of numbers so we can arrange them and find the mean: "<<endl;
while (cin >> userNumber) v.push_back(userNumber);
sort(v.begin(), v.end());
for (int x : v) cout << x << " | ";
cout << endl;
cout<<calcMean(v)<<" is the mean"<<endl;
return 0;
}
One thing to watch out for is copying vectors when you don't need to.
The function signature
int calcMode(vector<int> numberList)
means the numberList will get copied.
int calcMode(const & vector<int> numberList)
will avoid the copy. Scott Meyer's Effective C++ talks about this.
As an aside, calling is a numberList is misleading - it isn't a list.
There are a couple of points that are worth being aware of in the for loop:
for (unsigned int i = 0; i <= numberList.size()-1; i++)
First, this might calculate the size() every time. An optimiser might get rid of this for you, but some people will write
for (unsigned int i = 0, size=numberList.size(); i <= size-1; i++)
The size is found once this way, instead of potentially each time.
They might even change the i++ to ++i. There used to a potential overhead here, since the post-increment might involve an extra temporary value
One question - are you *sure this gives the right answer?
The comparison nextNumber == originNumber is looking at the first number to begin with.
Try it with 1, 2, 2.
One final point. If this is general purpose, what happens if the list is empty?
Would it be better to write smaller functions?
Yes, you can make do the same job using std::map<>; which could be
a much appropriate way to count the repetition of the array elements.
Secondly, it would be much safer to know, what is the size of the
array. Therefore I suggest the following:
std::cout << "Enter the size of the array: " << std::endl;
std::cin >> arraySize;
In the calcMode(), you can easily const reference, so that array
will not be copied to the function.
Here is the updated code with above mentioned manner which you can refer:
#include <iostream>
#include <algorithm>
#include <map>
int calcMode(const std::map<int,int>& Map)
{
int currentRepetition = 0;
int mode = 0;
for(const auto& number: Map)
{
std::cout << "The Number " << number.first << " appears " << number.second << " times." << std::endl;
if(currentRepetition < number.second )
{
mode = number.first; // the number
currentRepetition = number.second; // the repetition of the that number
}
}
return mode;
}
int main()
{
int arraySize;
int userNumber;
std::map<int,int> Map;
std::cout << "Enter the size of the array: " << std::endl;
std::cin >> arraySize;
std::cout << "Please type a list of numbers so we can arrange them and find the mean: " << std::endl;
while (arraySize--)
{
std::cin >> userNumber;
Map[userNumber]++;
}
std::cout << calcMode(Map)<<" is the mode" << std::endl;
return 0;
}
Update: After posting this answer, I have found that you have edited your function with mean instead of mode. I really didn't get it.
Regarding mean & mode: I recommend you to read more. Because in general, a data set can have multiple modes and only one mean.
I personally wouldn't split this code up in smaller blocks, only if i'd want to reuse some code in other methods. But just for this method it's more readable like this.
The order of excecution is aroun O(n) for calc which is quite oke if you ask me
In the following program:
#include <iostream>
using namespace std;
int main(){
int i = 99;
for(int i = 1; i <= 10; i++)
{
cout << i << endl;
}
cout << endl << endl;
cout << i << endl;
return 0;
}
I am not getting an error on compilation.
My question is why this is happening.
The int variable i was declared twice. The first time i was declared in the main() function and thus its scope will be this whole main() function including the for loop. The second time i was declared with the for loop and thus its scope will be only the for loop. So, now inside the scope of the for loop there exists two int variablesi. Shouldn't this be a cause of error? And if not why?
Second thing is the output I am getting:
1
2
3
4
5
6
7
8
9
10
99
I also don't understand the output. Why after the execution of the for loop, the value of i that is being printed is 99 and not 10.
You can define variables with the same names in different scopes. The first variable i is defined in the scope of the main function. In the loop there is another implied nested and anonymous scope for the variables you declare for the loop.
For the compiler, the code
for(int i = 1; i <= 10; i++)
{
cout << i << endl;
}
is more or less equivalent to
{
int i;
for(i = 1; i <= 10; i++)
{
cout << i << endl;
}
}
I've encountered a problem while trying to create a code which converts decimal numbers to binary, using functions. At first I created the code using only main function and it worked fine, but decided to modify it to use function. I believe code is written right, however when I try to cout my answer I get a big number like 115120160758866453687091316369641637416.
This is the code
#include <iostream>
#include <math.h>
using namespace std;
int* unsigned_dec(int dec_M) { //function for converting absolute part of numbers
int bin[8] = { 0,0,0,0,0,0,0,0 };
int ind = 7;
int arr_ind = 0;
for (int base = (int)abs(dec_M); base > 0; base = base / 2) {
if (base % 2 == 0) {
bin[arr_ind] = 0;
ind--;
}
else {
bin[arr_ind] = 1;
ind--;
}
arr_ind++;
}
return bin;
}
int main() {// main function
int dec_N;
cin >> dec_N;
int* bin_main = unsigned_dec(dec_N); //we are not sure if we are assigning the returned value of function to array in correct
for (int i = 0; i <= 7; i++) {
cout << bin_main[i];
}
cout << endl;
return 0;
}
then I tried to change the cout code to
cout << bin_main[0] << bin_main[1] << bin_main[2] << bin_main[3] << bin_main[4] << bin_main[5] << bin_main[6] << bin_main[7] << endl;
And this worked fine.
Then I wrote the same 2nd variant of cout in other way
cout << bin_main[0];
cout << bin_main[1];
cout << bin_main[2];
cout << bin_main[3];
cout << bin_main[4];
cout << bin_main[5];
cout << bin_main[6];
cout << bin_main[7];
cout << endl;
and my code started to cout the same strange number. I think that all 3 ways of couts are almost the same (especially 2 and 3), but don't understand what makes it not to work.
int bin[8] = { 0,0,0,0,0,0,0,0 };
is allocated on stack. You should either allocate bin on heap
auto bin = std::unique_ptr<int, std::default_deleter<int[]>>(new int[8]);
or even better, use std::vector
you are returning pointer to local array of intbin[] in unsigned_dec. This array on stack of function unsigned_dec will get invalidated once another function from main gets called i.e cout operator .
As others have already mentioned: A function should never return a pointer to a local variable. Local variable is not valid when the function returns.
A better way is to use a vector and just make the function return the vector.
Something like:
#include <iostream>
#include <math.h>
using namespace std;
//function for converting absolute part of numbers
vector<int> unsigned_dec(int dec_M) {
vector<int> bin; // Create a vector
bin.resize(8, 0); // Fill it with 8 elements initialized to zero
int arr_ind = 0;
// Note: added check for arr_ind being valid
for (int base = (int)abs(dec_M); base > 0 && arr_ind < 8; base = base / 2) {
if (base % 2 == 0) {
bin[arr_ind] = 0;
}
else {
bin[arr_ind] = 1;
}
arr_ind++;
}
return bin; // Return the vector
}
int main() {
int dec_N;
cin >> dec_N;
vector<int> bin_main = unsigned_dec(dec_N);
for (int i = 0; i < bin_main.size(); i++) {
cout << bin_main[i];
}
cout << endl;
return 0;
}
I wrote a function within my code that should create some sort of matrices. It is fine when the size is small, but when it gets bigger, it crashes at the middle of this function without giving any information. I did that with both debug and release mode and same thing happened. Any idea on what can be wrong? Someone suggested me it could be buffer overrun.
In this function when kl.mechelms get bigger than a certain number, it crashes. The following code uses a function and gets a 3 by 3 matrix and stores it in kl.scoff which size is [3][3][kl.mechelms][kl.mechelms]. The problem happens when kl.mechelms are like bigger than 7000, but we need far more than that for our code.
Could the function Calc_3D which I use within this part cause the problem? I think it shouldn't since it just reads some values.
for (int z = 0;z<3;z++) {
for (int q = 0;q<3;q++) {
kl.scofsarr[z][q] = new double *[kl.mechelms];
}
}
for (int i = 0;i<kl.mechelms;i++) {
cout << "element " << i << "of " << kl.mechelms << endl;
kl.comments << "element " << i << "of " << kl.mechelms << endl;
for (int z = 0;z<3;z++) {
for (int q = 0;q<3;q++) {
kl.scofsarr[z][q][i] = new double[kl.mechelms];
}
}
for (int j = 0;j<kl.mechelms;j++) {
Calc_3D(i,j, kl.elmx[j], kl.elmy[j], kl.elmz[j], kl.anglemat[j], kl.dip[j], kl.elmx[i],kl.elmy[i],kl.elmz[i],
kl.elma[i],kl.rectza,kl.anglemat[i],kl.dip[i], kl.G, kl.v, kl.scofs, kl.rdepth);
for (int z = 0;z<3;z++) {
for (int q = 0;q<3;q++) {
kl.scofsarr[z][q][i][j] = kl.scofs[z][q];
}
}
}
}