for loop not running, trying to iterate backwards through array elements - c++

To practice using pointers and arrays i'm trying to do a simple program capable of converting a binary input to denary.. i think i have a good idea for the logic but i haven't even got round to trying to implement it because im struggling to get my for loop running!
It seems silly but i know the code inside the for loop works fine outside of it, so it must be something wrong with the condition..? im trying to start at the back of the char array (navigating using pointers) and output each char(as an int) up to the first element.
So the desired output is "0 - 1 - 0 - 1 -"
#include <iostream>
using std::cout;
using std::endl;
//prototypes
void binaryToDenary(const char* input, int& inputLength);
int main(){
const char binaryInput[] = {1,0,1,0};
int inputLength = sizeof(binaryInput)/sizeof(binaryInput[0]);
binaryToDenary(binaryInput, inputLength);
return 0;
}
void binaryToDenary(const char* input, int& inputLength){
//testing some stuff--- this all works as expected
//cout << input[2] << " " << (int)*(input+2) << " " << inputLength <<endl;
int i;
for(i = inputLength; i < 0; i--){
cout << (int)*(input+i) << " - ";
}
}

Your for loop should be this:
for(i = inputLength -1 ; i >= 0; i--)
{
cout << (int)*(input+i) << " - ";
}
There are two problems in your code:
i = inputLength which should be i = inputLength -1
i < 0 which should be i >= 0
Also, change the second parameter type from int & to int:
void binaryToDenary(const char* input, int inputLength) //now its better!
The type int& reduces the use cases, and benefits almost nothing. If you use int &, then all of these would give compilation error:
const int inputLength = sizeof(binaryInput)/sizeof(binaryInput[0]);
^^^^ note this
binaryToDenary(binaryInput, inputLength); //compilation error
binaryToDenary(binaryInput, sizeof(binaryInput)/sizeof(binaryInput[0])); //error
binaryToDenary(binaryInput, 4); ////compilation error
So use int, and all of the above would compile fine!

Array indexes start from zero, so the last element is at inputLength - 1. With i < 0 you exit from the loop immediately as that never be true...
for(i = inputLength - 1; i >= 0; i--){
cout << (int)*(input+i) << " - ";
}

for(i = inputLength; i < 0; i--)
will run only if inputLength is less than 0, which is not possible?
You need:
for(i = (inputLength-1); i >= 0; i--)
^^^^^^^^^^^^^^ ^^

C arrays are 0 based so a valid index is given by
(0 <= i) && (i < array_length)
In your program, this means that the position of the last digit in your initialization should be inputLength - 1 and the loop condition should be i >= 0.
(As for why you loop is not running, at the start you have i == inputLength, so i is positive, failing the i < 0 condition immediately).

You want to run as long as i is bigger (or maybe equal) to zero. You were trying to run the loop as long as i was less than zero, and beginning with a value greater than zero results to that you never enter the loop.
for(i = inputLength; i > 0; i--){
cout << (int)*(input+i) << " - ";
}

You must check for iteration loop variable i to be positive..
However you should use a STL iterator on the binary input vector and not loop on it's content in a c fashion, if you want to practice C++, possible solution could be:
vector<char> binaryInput;
binaryInput.push_back(1);
binaryInput.push_back(0);
binaryInput.push_back(1);
binaryInput.push_back(0);
vector<char>::iterator it;
for ( it=myvector.begin() ; it < myvector.end(); it++ ){
cout << " " << *it << endl; //or whatever you need to do with vector content
}

Related

Program only works with inclusion of (side effects free) cout statements?

So I've been working on problem 15 from the Project Euler's website , and my solution was working great up until I decided to remove the cout statements I was using for debugging while writing the code. My solution works by generating Pascal's Triangle in a 1D array and finding the element that corresponds to the number of paths in the NxN lattice specified by the user. Here is my program:
#include <iostream>
using namespace std;
//Returns sum of first n natural numbers
int sumOfNaturals(const int n)
{
int sum = 0;
for (int i = 0; i <= n; i++)
{
sum += i;
}
return sum;
}
void latticePascal(const int x, const int y, int &size)
{
int numRows = 0;
int sum = sumOfNaturals(x + y + 1);
numRows = x + y + 1;
//Create array of size (sum of first x + y + 1 natural numbers) to hold all elements in P's T
unsigned long long *pascalsTriangle = new unsigned long long[sum];
size = sum;
//Initialize all elements to 0
for (int i = 0; i < sum; i++)
{
pascalsTriangle[i] = 0;
}
//Initialize top of P's T to 1
pascalsTriangle[0] = 1;
cout << "row 1:\n" << "pascalsTriangle[0] = " << 1 << "\n\n"; // <--------------------------------------------------------------------------------
//Iterate once for each row of P's T that is going to be generated
for (int i = 1; i <= numRows; i++)
{
int counter = 0;
//Initialize end of current row of P's T to 1
pascalsTriangle[sumOfNaturals(i + 1) - 1] = 1;
cout << "row " << i + 1 << endl; // <--------------------------------------------------------------------------------------------------------
//Iterate once for each element of current row of P's T
for (int j = sumOfNaturals(i); j < sumOfNaturals(i + 1); j++)
{
//Current element of P's T is not one of the row's ending 1s
if (j != sumOfNaturals(i) && j != (sumOfNaturals(i + 1)) - 1)
{
pascalsTriangle[j] = pascalsTriangle[sumOfNaturals(i - 1) + counter] + pascalsTriangle[sumOfNaturals(i - 1) + counter + 1];
cout << "pascalsTriangle[" << j << "] = " << pascalsTriangle[j] << '\n'; // <--------------------------------------------------------
counter++;
}
//Current element of P's T is one of the row's ending 1s
else
{
pascalsTriangle[j] = 1;
cout << "pascalsTriangle[" << j << "] = " << pascalsTriangle[j] << '\n'; // <---------------------------------------------------------
}
}
cout << endl;
}
cout << "Number of SE paths in a " << x << "x" << y << " lattice: " << pascalsTriangle[sumOfNaturals(x + y) + (((sumOfNaturals(x + y + 1) - 1) - sumOfNaturals(x + y)) / 2)] << endl;
delete[] pascalsTriangle;
return;
}
int main()
{
int size = 0, dim1 = 0, dim2 = 0;
cout << "Enter dimension 1 for lattice grid: ";
cin >> dim1;
cout << "Enter dimension 2 for lattice grid: ";
cin >> dim2;
latticePascal(dim1, dim2, size);
return 0;
}
The cout statements that seem to be saving my program are marked with commented arrows. It seems to work as long as any of these lines are included. If all of these statements are removed, then the program will print: "Number of SE paths in a " and then hang for a couple of seconds before terminating without printing the answer. I want this program to be as clean as possible and to simply output the answer without having to print the entire contents of the triangle, so it is not working as intended in its current state.
There's a good chance that either the expression to calculate the array index or the one to calculate the array size for allocation causes undefined behaviour, for example, a stack overflow.
Because the visibility of this undefined behaviour to you is not defined the program can work as you intended or it can do something else - which could explain why it works with one compiler but not another.
You could use a vector with vector::resize() and vector::at() instead of an array with new and [] to get some improved information in the case that the program aborts before writing or flushing all of its output due to an invalid memory access.
If the problem is due to an invalid index being used then vector::at() will raise an exception which you won't catch and many debuggers will stop when they find this pair of factors together and they'll help you to inspect the point in the program where the problem occurred and key facts like which index you were trying to access and the contents of the variables.
They'll typically show you more "stack frames" than you expect but some are internal details of how the system manages uncaught exceptions and you should expect that the debugger helps you to find the stack frame relevant to your problem evolving so you can inspect the context of that one.
Your program works well with g++ on Linux:
$ g++ -o main pascal.cpp
$ ./main
Enter dimension 1 for lattice grid: 3
Enter dimension 2 for lattice grid: 4
Number of SE paths in a 3x4 lattice: 35
There's got to be something else since your cout statements have no side effects.
Here's an idea on how to debug this: open 2 visual studio instances, one will have the version without the cout statements, and the other one will have the version with them. Simply do a step by step debug to find the first difference between them. My guess is that you will realize that the cout statements have nothing to do with the error.

Trying to create a better loop for naming array elements

I have started studying arrays and have just started making some practice but I am having some problems with using loops to name the elements inside of a specific array.
I was trying to make this piece of code that assigned the numbers from 1 up to 12(to resemble the months of the year) to the ints inside of the array, this is what I came up with:
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
int array[12];
for (int i = 0; i < 12;) {
cout << "Month number " << i + 1 << endl;
array[i] = (i++);
}
return 0;
}
What I don't like about this is the fact that I had to leave the increment/decrement space inside of the for loop empty. I had initially tried making the code look something like this:
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
int array[12];
for (int i = 0; i < 12; i++) {
cout << "Month number " << i + 1 << endl;
array[i] = i++;
}
return 0;
}
But this way, even if the first element of the array came out correct, the subsequent ones didn't. I think the reason for this is that the i++ in the last statement of the loop makes the value of i increment but I couldn't find a way around it without having to add another line with i-- or doing as I did in the first code I posted.
Could anyone offer me a hand in understanding how to make it so that i can store the value of i, incremented by one, inside of that specific array element, without incrementing it for the whole loop(if it is possible)?
I know there are ways around it, just like I showed in the first code i posted, but it's something that's bugging me and so I would like to make it more visually pleasing.
Please, keep in mind that I am just a beginner :)
Thanks in advance for the answers, and sorry for the long question.
Edit: Apparently, coding like this:
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
int array[12];
for (int i = 0; i < 12; i++) {
cout << "Month number " << i + 1 << endl;
array[i] = i + 1;
}
cout << array[4] << endl;
return 0;
}
makes it so that the program works correctly and looks like I wanted, but I can't comprehend why it does :(
Edit 2: Apparently, as UnholySheep pointed out, I missed on the fact that + 1 does not modify the value of the integer, while ++ does.
Thanks to everyone that answered and explained how ++ and +1 work!
Simply do i+1 again.
for (int i = 0; i < 12; i++)
{
cout << "Month number " << i + 1 << endl;
array[i] = i + 1;
}
Now it's obvious you actually want to start at 1 and go to 12, so this seems somewhat better with less repetition:
for (int i = 1; i <= 12; i++)
{
cout << "Month number " << i << endl;
array[i-1] = i;
}
EDIT: As for your edit, the reason why this works is because i++ operator works on the particular i variable. It increments that existing i by one, making it so that the next time you access i, it will be 1 more than it was before.
Writing i+1, on the other hand, creates a completely new, temporary, variable (actually a constant). So when you write
array[i] = i+1;
you're saying that you want i to remain unchanged, but you want to create a new number, one bigger than i, and put that new number into the array.
You can even write it out longer to be completely explicit:
int newNumber = i+1;
array[i] = newNumber;
for (int i = 0; i < 12; i++) {
cout << "Month number " << i + 1 << endl;
array[i] = i+1;
}
No reason to increment i in the loop

how to convert an for loop to while loop c++

I'm trying to convert a for loop to while loop in c++ and do some checking for duplicates in a random number generator for generating lotto numbers so far all the stuff i'm trying seems to make the compiler very unhappy and I could really use a few pointers. It's the for loop in the Harray() function that feeds the Balls[] array
that i want to convert to a while loop.
#include<iostream>
#include<cstdlib> // to call rand and srand.
#include<ctime> // to make rand a bit more random with srand(time(0)) as first call.
#include<iomanip> // to manipulate the output with leading 0 where neccesary.
using namespace std;
// Hrand() function create and return a random number.
int Hrand()
{
int num = rand()%45+1; // make and store a random number change 45 for more or less Balls.
return num; // return the random number.
}
// Harray() function create and fill an array with random numbers and some formatting.
void Harray()
{
int Balls[6]; // change the number in Balls[6] and in the for loop for more or less nrs. a row.
for(int x=0; x<=6; x++) //the loop to fill array with random numbers.
{
int a; // made to pass the Balls[x] data into so i can format output.
int m = Hrand(); // calling the Hrand() function and passing it's value in int m.
Balls[x] = m; // throwing it into the array tought i did this because of an error.
a = Balls[x]; // throwing it into int a because of an type error.
cout<<"["<<setfill('0')<<setw(02)<<a<<"]"; //format output with leading 0 if neccesary.
}
cout<<endl; // start new row on new line.
}
// Main function do the thing if compiler swallows the junk.
int main() // start the program.
{
int h; // int to store user cchoice.
srand(time(0)); // make rand more random.
cout<<"How many rows do you want to generate?"<<endl; // ask how many rows?
cin>>h; // store user input.
for(int i=h; h>0; h--) // produce rows from user input choice.
{
Harray(); // calling Harray function into action.
}
return 0; // return zero keep the comipler happy.
}
I would like to always have six diffrent numbers in a row but i don't see how to get there with the for loops i think the while loop is way to go but am open to any suggestion that will work. I'm just starting with c++ i might have overlooked some options.
int x=0;
while(x<6)
{
int a;format output.
int m = Hrand();value in int m.
Balls[x] = m; because of an error.
a = Balls[x];
cout<<"["<<setfill('0')<<setw(02)<<a<<"]";
x++;
}
Here, I also fixed a bug. Since Balls has 6 elements, the last element will be 5. Thus you want x<6 instead of x<=6. That goes for the for loop too.
One drawback of while loops is that you cannot declare local variables with them.
First of all, you should realize that the difference between a for loop and a while loop is mostly syntactic--anything you can do with one, you can also do with the other.
In this case, given what you've stated as your desired output, what you probably really want is something like this:
std::vector<int> numbers;
std::set<int> dupe_tracker;
while (dupe_tracker.size() < 6) {
int i = Hrand();
if (dupe_tracker.insert(i).second)
numbers.push_back(i);
}
The basic idea here is that dupe_tracker keeps a copy of each number you've generated. So, you generate a number, and insert it into the set. That will fail (and return false in retval.second) if the number is already in the set. So, we only add the number to the result vector if it was not already in the set (i.e., if it's unique).
How convert for-loop to while-loop
#include <iostream>
class T545_t
{
// private data attributes
int j;
public:
int exec()
{
// A for-loop has 3 parameters, authors often fill 2 of them with magic
// numbers. (magic numbers are usually discouraged, but are expected
// in for-loops)
// Here, I create names for these 3 for-loop parameters
const int StartNum = 2;
const int EndNum = 7;
const int StrideNum = 2;
std::cout << std::endl << " ";
for (int i = StartNum; i < EndNum; i += StrideNum ) {
std::cout << i << " " << std::flush;
}
std::cout << std::flush;
// A while-loop must use / provide each of these 3 items also, but
// because of the increased code-layout flexibility (compared to
// for-loop), the use of magic numbers should be discouraged.
std::cout << std::endl << " ";
j = StartNum;
do {
if (j >= EndNum) break;
std::cout << j << " " << std::flush;
j += StrideNum;
} while(true);
std::cout << std::flush;
std::cout << std::endl << " ";
j = StartNum;
while(true) {
if (j >= EndNum) break;
std::cout << j << " " << std::flush;
j += StrideNum;
}
std::cout << std::flush;
std::cout << std::endl << " ";
j = StartNum;
while(j < EndNum) {
std::cout << j << " " << std::flush;
j += StrideNum;
}
std::cout << std::endl;
return 0;
}
}; // class T545_t
int main(int , char** )
{
T545_t t545;
return(t545.exec());
}
Ask me where 'j' is declared?
This code is marked as C++, so in this case, I have declared 'j' in the private data attribute 'section' of this class definition. That is where you'd look for it, right?
If your c++ code does not have class, what's the point?

Any suggestions to why this loop isn't executing?

I have written the function below, which groups charterers together before encountering a space and saves each group in a vector, once a space is encountered it should look for another group and do the same thing over and over!
My debugging so far indicates that the for loop within the if statement is not executing for some reason.
char const* MathematicaLib::IsThisAnEquation(char const* equation){
// execute PEMDAS here
vector <char const*> SeperatedValues;
char *TempGH = "";
int temp = 0;
int SOG = 0; //start of group
//cout << equation[2] << endl; // used to test whether the funcion is reading the input parameter
for (int j = 0; j < strlen(equation); j++)
{
if (isspace(equation[j])) {
//cout << "processing" << endl; // used to confirm that its reading values until a space is encountered
for (int n = SOG; n < j - 1; n++){
TempGH[temp] = equation[n];
temp++;
SOG = j + 1; //skip charecter
cout << "test"; //this does not print out meaning that the loop dosen't execute
}
temp = 0;
SeperatedValues.push_back(TempGH);
}
}
for (unsigned int p = 0; p < SeperatedValues.size(); p++){ // used for debugging only
cout << SeperatedValues[p] << endl;
cout << "This should be reading the vector contents" << endl;
}
return "";
}// end of IsThisAnEquation
Assume that the value I am passing to the function is "123 1", also assume that the first character of the parameter is never a space. This means that when a space is detected then n == 0 AND j-1 == 2 (j-1 indicates the end of the group of characters while n = the start) the loop should cause the characters in position 0 to 2 (123) to be pushed into the vector, thus j is not == 0 or -1.
The loop is not directly embedded under the first for loop rather it is under the if statement, shouldn't this force to only execute if the condition within the if statment is true? rather than follow the rules of embedded loops execution?
Any suggestions to why this loop isn't executing?
I have reviewed the code over and over to spot any logical errors, but I couldn't find any so far!
My bad if (isspace(equation[j]) was the root of all evil, this condition was not being met because std::cin >> equation does not register spaces, replacing it with this std::getline(std::cin, equation); managed to solve the problem, the for loop now executes.
Thanks to #PaulMcKenzie and #Joachim Pileborg for pointing out the issue of modifying string literals.
Sorry I didn't mention that I was passing the parameter through std::cin>> !

Vector substring out of range

I'm currently working on a problem and I've been stumped on an error for about 3 hours now. Thus, I've given up being hard headed and I'm looking to the internet to see if someone else's wealth of knowledge can help to solve my problem.
A jist of the program, it takes in input from the command line of any number of numbers. It inserts them into a vector and then performs a series of statistical analysis' on the data set.
Currently, I'm having difficulty with the quintiles function (as my teacher says or "quantiles" for those of you looking it up on Wikipedia).
Logically, my code should work. However, it's seeming to hit an out of range error two before the actual end of the vector that I've created.
Heres the function followed by the functions called inside:
string quintile(vector<double> v) {
ostringstream oss;
oss << "Quintile means" << endl;
vector<unsigned> quintile{ 0 };
// get range of quintiles and insert into vector
for (unsigned i = 1; i <= 5; ++i)
quintile.push_back((v.size() * 0.2) * i);
// get the mean for each quintile
for (unsigned i = 0; i < 5; ++i)
oss << "Q" << (i + 1) << ": " << mean_sized(v, quintile[i], quintile[i + 1]) << " (" << quintile[i] << ".." << quintile[i + 1] << ")" << endl;
return oss.str();
}
double mean_sized(vector<double> v, int first, int last) {
double mean = 0.0;
vector<double> sub;
for (unsigned i = v[first]; i < v[last]; ++i)
sub.push_back(v[i]);
return (accumulate(sub.begin(), sub.end(), mean) / sub.size());
}
Any input is much appreciated as I'm seriously stumped.. I'm going to move on to the last function and hopefully by the time I'm done someone will have graced me with the knowledge to solve that issue.
Thanks!
This loop is wrong:
for (unsigned i = v[first]; i < v[last]; ++i)
sub.push_back(v[i]);
You're using the values in the vector as the range of indexes. You should just be using the range from first to last:
for (unsigned i = first; i <= last; i++) {
sub.push_back(v[i]);
}
P.S. See Why is it considered a bad practice to omit curly braces?