Difficulty implementing limit to how many integers print on each line C++ - c++

I have seen this question around, but I am having difficulty implementing some of the solutions into my own code.
The program being worked on finds all the prime numbers in an array and times how long it takes to find all the prime numbers. One of the stipulations though is making the program print only 10 numbers per line. I have tried a couple different methods to get this to work, but none of them print how I need them to. Here is the current code:
#include "stdafx.h"
#include <iostream>
#include <time.h>
#include <stdio.h>
using namespace std;
static const int N = 1000;
int main()
{
int i, a[N];
clock_t start = clock();
for (i = 2; i < N; i++) a[i] = i;
for (i = 2; i < N; i++)
if (a[i])
for (int j = i; j*i < N; j++) a[i*j] = 0;
start = clock() - start;
for (i = 2; i < N; i++)
if (a[i]) cout << " " << i;
if ((i = 1) % 10 == 0)
cout << "\n";
printf("\nIt took %d clicks (%f seconds) to find all prime numbers.\n", start, ((float)start) / CLOCKS_PER_SEC);
return 0;
}
I'm sure this is a simple mistake on my own part, or maybe I dont have the proper understanding on how this works. If anyone can shed some light on the subject it would be greatly appreciated, thank you.

Just create a new counter, to count the number of primes found.
int primes = 0;
for (i = 2; i < N; i++) {
if (a[i]) {
primes++;
cout << " " << i;
if ( primes % 10 == 0)
cout << "\n";
}
}

for (i = 2; i < N; i++)
if (a[i]) cout << " " << i;
if ((i = 1) % 10 == 0)
cout << "\n";
What this snippet does is not at all what you want it to do. If your whitespace is any indication, it looks like you expect this all to be nested in the same for loop. However, it's actually processed like this:
for (i = 2; i < N; i++) if (a[i]) cout << " " << i;
if ((i = 1) % 10 == 0) cout << "\n";
In other words, two completely separate statements. The first one goes through every element of a[i] and outputs them with a space. When that loop is done to completion, the second statement then checks a condition and adds a newline (that check is also broken, but I'll get into that later).
In order to break after every tenth element, the newline check needs to be processed for each element, or at least each element printed, rather than at the end.
So as written, what you seem to expect would actually be something like:
for (i = 2; i < N; i++) {
if (a[i]) cout << " " << i;
if ((i = 1) % 10 == 0)
cout << "\n";
}
The braces { } are important here, since they ensure that all the enclosed statements are part of the for loop and processed for each iteration, not just the single statement immediately following it.
Which brings up the second issue: That newline check does not do what you think it does. From your explanation, what you want is for the check to trigger on every tenth value printed, and add a newline. However, if ((i = 1) % 10 == 0)…doesn't do that. At all.
Rather than triggering on every tenth value, all if ((i = 1) % 10 == 0 does is set i to 1 (which will really break your for loop) and then never trigger since i = 1 will always return 1 anyway. It's just a convoluted way to do exactly what you don't want.
As Amadeus mentions, one easy way to implement this is just to use a counter that increments every time you print a value, and test against that instead:
for (i = 2; i < N; i++) {
if (a[i]) {
cout << " " << i;
primes++;
if (primes % 10 == 0)
cout << "\n";
}
}
Again, note the braces enclosing the three statements for the if (a[i]) clause. This ensures the increment and newline check only happen every time a value is actually printed, rather than for every iteration of the for loop.

Related

Why isn't break good enough?

C++
When I first ran this code with a different input value of 881, 643, 743, etc... which are all primes numbers, I got a result of "True" but when I input a higher number like 804047277, it came back as "True" when it should have been "False"
#include <iostream>
int main(){
int num;
std::cin >> num;
for(int i = 2; i < num; i++){
if(num % i == 0){
std::cout << "True" << std::endl;
break;
}
else{
std::cout << "False" << std::endl;
break;
}
}
return 0;
}
I corrected my code (The code below) and received the correct answer, which was "False"
#include <iostream>
int main(){
int num;
std::cin >> num;
for(int i = 2; i < num; i++){
if(num % i == 0){
std::cout << "True" << std::endl;
break;
return 0;
}
else{
std::cout << "False" << std::endl;
break;
}
}
return 0;
}
Shouldn't the break in the if statement stop the loop overall? I am just trying to understand why the break wasn't good enough, and I had to return 0;
I would correct your code like following (see description afterwards):
Try it online!
#include <iostream>
int main() {
int num = 0;
std::cin >> num;
for (int i = 2; i < num; ++i)
if (num % i == 0) {
std::cout << "True (Composite)" << std::endl;
return 0;
}
std::cout << "False (Prime)" << std::endl;
return 0;
}
Input:
804047277
Output:
True (Composite)
As it is easy to understand, your program is intended to check primality and compositness of a number.
Mistake in your program is that you show False (Prime) when division by a very first i gives non-zero remainder. Instead, to actually check primality, you need to divide by all possible i and only if ALL of them give non-zero, then number is prime. It means that you shouldn't break or show False on very first non-zero remainder.
If ANY of i gives zero remainder then given number by definition is composite. So unlike the Prime case, this Composite case should break (or return) on very first occurance of zero remainder.
In code above on very first zero remainder I finish program showing to console that number is composite (True).
And only if whole loop finishes (all possible divisors are tested) then I show False (that number is prime).
Regarding question if break; is enough to finish a loop, then Yes, after break loop finishes and you don't need to return 0; after break, this return statement never finishes.
Also it is well known fact that it is enough to check divisibility until divisor equal to Sqrt(num), which will be much faster. So your loop for (int i = 2; i < num; ++i) should become for (int i = 2; i * i <= num; ++i) which is square times faster.

Program Compiles, Runs, but doesn't end in DevC++

I wrote a program to sum all odd numbers less than or equal to N. It's not the most efficient or eloquent program, but it works in the compiler on Codepad.org and does not work in DevC++. Usually when a program I wrote is stuck in some kind of infinite loop the program crashes in DevC++ and Windows stops it and lets me know.
Here, the program compiles and runs, but just sits with the cursor blinking and does nothing. Windows doesn't stop it, nothing happens, the program doesn't finish, no matter for how long I let it sit. I'm guessing this is a problem with DevC++ unless it's a problem with my code that Codepad overlooks. Will anyone explain to me what is happening here?
Here is my code:
#include <iostream>
using namespace std;
int odd(int N)
{
int i;
int sum = 0;
for(i = 0; i <= N; ++i)
{
while((i % 2) != 0)
{
sum = sum + i;
}
}
return sum;
}
int main()
{
int N;
cout << "Pick a value: ";
cin >> N;
cout << "The sum of all numbers <= to " << N << " is: " << odd(N);
return 0;
}
I've made the suggested change to an if-statement and the same problem is occuring:
#include <iostream>
using namespace std;
int odd(int N)
{
int i;
int sum = 0;
for(i = 0; i <= N; ++i)
{
if ((i % 2) != 0)
{
sum = sum + i;
}
}
return sum;
}
int main()
{
int N;
cout << "Pick a value: ";
cin >> N;
cout << "The sum of all odd numbers <= to " << N << " is: " << odd(N);
return 0;
}
while((i % 2) != 0)
{
sum = sum + i;
}
This is a infinite loop.Because if (i % 2 != 0) is true then the program will increment sum again and again.What you are probably looking to do is have an if statement instead of while
Seems like the edit is working, please try deleting the old output file and rebuilding and re-compile the entire program.
The output seems to be as follows:
Pick a value: 52
The sum of all odd numbers <= to 52 is: 676
Process exited after 1.034 seconds with return value 0
Press any key to continue . . .
make sure the window of the previous run is closed else the compiler will not recompile but just runs the previous version before you changed it.you may see this as an error stated at bottom in debug mode.
the while() is an infinite loop because i is not changed inside the while() or its {} so use if

C-string assignment using for loop

I think this is a relevant topic, while browsing this forum and tutorial I have tweaked my c-string to the proper format(I think) but there's just one topic missing. How can we take an integer, using a for loop, and assign the c-string values from the integer.
I'm just focusing on the integer to binary part right now and I'm sure my number manipulation is solid. However, my prof said we needed to assign the binary values to a c-string. And I'm trying this, it's telling me I'm using a const char and a char* via the compiler. I'm not sure how this is happening, or how to prevent it.
Here's my source code:
//sample integer to binary
#include <iomanip>
#include <iostream>
#include <iomanip>
#include <cstring>
using namespace std;
int main()
{
int num; //the number a user enters
int rem; //the remainder, the 1 and 0 of the binary number
int x; //a variable to store the number after division
char binary[10]; //c-string initialized to 10, perhaps that is too many.
cout << "Enter a number: ";
cin >> num;
for (int i = 0; i < 10; i++)
{
x = num / 2;
cout << x << endl; //this shows that the code is working
rem = num % 2;
cout << num << endl; //this also shows the code is working
char r = (char)rem; //These two lines of code are
strcpy(binary[i], r); //preventing compilation
cout << binary[i] << endl; // this is diagnostic
num = x;
}
cout << "The number " << num << " is " << binary[5] << " in binary.\n";
return 0;
}
Thanks you two, I've been able to make this work (almost).
I'm still getting some unexpected behavior, and I'm not sure how big to initialize the array to, I don't think that it would matter too much, but I don't know exactly how big of numbers the graders use to test.
Anyways, here's the new code:
#include <iomanip>
#include <iostream>
#include <iomanip>
#include <cstring>
using namespace std;
int main()
{
int num; //the number a user enters
int rem; //the remainder, the 1 and 0 of the binary number
int x; //a variable to store the number after division
char binary[5] = {'0', '\0'}; //c-string initialized to 10, perhaps that is too many.
cout << "Enter a number: ";
cin >> num;
for (int i = 0; i < 10; i++)
{
x = num / 2;
//cout << x << endl; //this shows that the code is working
rem = num % 2;
//cout << num << endl; //also shows the code is working
binary[i] = '0' + rem; //not sure what this is doing, but it works.
//cout << binary[i] << endl; // this is diagnostic
num = x;
}
cout << "The number " << num << " is " << binary << " in binary.\n";
return 0;
}
And here's the output:
Enter a number: 5
The number 0 is 1010000000# in binary.
It should show the number, the initial number, and say 101, without the 0's and the # sign.
strcpy is for copying entire NUL-terminated string. If you want to set just one character, you can use =.
binary[i] = r;
However, if you want the line cout << binary[i] to work right, or to treat binary as a C string later, you need to store ASCII digits:
binary[i] = '0' + r;
Don't forget to add a terminating NUL to your string, right now it isn't a C-style string at all.
The arguments to strcpy() are char*, not char. The second argument must point to a null-terminated string, but r is just a single character. To assign a character to an element of an array, do:
binary[i] = r;
But you don't want the binary value of rem, you want the character that represents that binary value. It should be:
char r = '0' + rem;
In order to print binary as a string, you need to give it a null terminator. Since you're putting 10 digits into the string, you need to declare an extra character to hold the terminator, and initialize it with zeroes so it will be terminated properly.
char binary[11] = {0};
And if you want to print the whole string, you shouldn't reference binary[5], you should print the whole array:
cout << "The number " << num << " is " << binary << " in binary.\n";
In addition to problems already pointed out, you get binary digits in the reverse order. You have to count significant digits in your binary representation and reverse characters when you're done.
You didn't initialize the character buffer correctly that's why you are getting garbage in the print out.
As for the buffer size, you need as many characters as there are bits in the integer type you are converting plus one more for the terminating '\0', so for a 32-bit number you need 33 character size buffer. And that's important because if you overrun your buffer, quite nasty things will happen.
And one more note: I assume that numbers you are supposed to convert to a string representation are unsigned, so be explicit about it. Below is a quick and dirty implementation with some minimal error checking:
char *unsigned_to_binstr (unsigned n, char *binary, int buf_len)
{
int i, j;
if (buf_len < 2)
return NULL;
i = 0;
do {
binary[i++] = '0' + n % 2;
n /= 2;
} while (n && i < buf_len);
for (j = 0; j < i / 2; ++j) {
char temp = binary[j];
binary[j] = binary[i-j-1];
binary[i-j-1] = temp;
}
binary[i] = '\0';
return binary;
}
After everyone's comments, and my own research via my textbook I was able to formulate a somewhat working function. However, in the process I began to wonder about the garbage problem, so my solution.. Truncate! I added if clauses (tried to think of a loop representation but didn't get any ideas) and at the end I just use the length provided via if clauses and subtract 1, which should give me the appropriate bit size for the number. Using what basic c++ knowledge we've covered in class this is the solution I came up with, however crude and inefficient it might be!
I want to thank all of you, I couldn't have gotten past the point I was stuck at if it weren't for you!
Here's my rough final revision:
//sample integer to binary
#include <iostream>
using namespace std;
int main()
{
int num; //the number a user enters
int rem; //the remainder, the 1 and 0 of the binary number
int x; //a variable to store the number after division
int l; //length of c-string function
cout << "Enter a number: ";
cin >> num; //user input
if ((num == 1) || (num == 0)) // the following 17 lines of code are to truncate the string size.
l = 2;
if ((num > 1) && (num < 4))
l = 3;
if ((num >= 4) && (num <= 7))
l = 4;
if ((num >= 8) && (num <= 15))
l = 5;
if ((num >= 16) && (num <= 31))
l = 6;
if ((num >= 32) && (num <= 63))
l = 7;
if ((num >= 64) && (num <= 127))
l = 8;
if ((num >= 128) && (num <= 255))
l = 9;
if ((num > 255))
cout << "This number is too large for this string\n"; // I don't think the binary sequence should be larger than 16 bits.
char binary[l]; //c-string initialized to size according to the truncation rules above
for (int i = l - 1; i > 0; i--) //goes in reverse order, as binary counts from bottom to top.
{
x = num / 2;
rem = num % 2;
num = x;
binary[i] = '0' + rem; // added an
}
for (int i = 0; i <= l-1; i++)
{
cout << binary[i];
}
cout << " in binary.\n";
return 0;
}

Beginner c++ array and loop?

Trying to reverse the order of the characters input. I'm getting really close but no cigar.
#include <iostream>
using namespace std;
const int MAX = 10;
int main()
{
char a[MAX], next;
int index = 0;
cout << "Please enter in up to 10 letters ending with a period: " << endl;
cin >> next;
while((next != '.') && (index < 10))
{
a[index] = next;
index++;
cin >> next;
//cout << " " << next << endl;
}
int numbers_used = index;
for(index = 0; index <= numbers_used; index++)
{
a[index] = a[numbers_used -1];
numbers_used--;
cout << a[index] << " " << endl;
}
}
I'm getting everything but the last switch and even though my code is not as clean I'm failing to see where I'm going wrong.
The book code is:
for(index = numbers_used -1; index >= 0; index--)
cout<<a[index];
cout<< endl;
and why is it index = numbers_used - 1 ?? Since numbers_used was set to index and index was initialized at 0 and not 1 wouldn't I want to run the loop "numbers_used" amount of times? What am I missing?
Try this:
char* flip(char* str, int len) {
for(int x=0; x<(len/2); x++) {
swap(str[x], str[len-x-1]);
}
return str;
}
As of right now, after you get to the middle of the string, you'll have overwritten the values that you would need to copy to the second half. With a string like "FooBarBiz", your code will produce the following over iterations (I've put spaces in to try and make things clearer):
1: FooBarBiz
2: z ooBarBiz
3: zi oBarBiz
4: ziB BarBiz
5: ziBr arBiz
6: ziBra rBiz
7: ziBrar Biz
...
The code I posted however, uses the c++ swap function to swap the complimentary values, that way there are no lost values (we're not doing any overwriting), and you won't need to store the whole string in a placeholder variable. Does this make sense?
If you want to reverse the list you have to start from the last element and decrease the index .
You can approach this in at least two different ways. You can reverse the order of the string and then print, or you can leave the original string unmodified and simply print in reverse. I'd recommend the latter approach, in which case all you'd need to do is to change your last for loop to this:
for(index = 0; index < numbers_used; index++)
{
cout << a[numbers_used-index-1] << " " << endl;
}
Wouldn't it be easier this way ?
#include<iostream>
#include<string>
using namespace std;
const int MAX = 5;
int main()
{
char a[MAX], next;
int index = 0;
bool period = false;
cout << "Please enter in up to 10 letters ending with a period: " << endl;
for(int i = 0; i < MAX && !period; i++)
{
cin >> next;
if(next != '.')
{
a[i] = next; // put the value into the array
index++;
}
else
period = true;
}
for(int i = index - 1; i >= 0 ; i--)
{
cout << a[i] << " ";
}
cout << endl;
return 0;
}
The problem can be solved by using the iterators from the standard library. The BidirectionalIterator as for example offered by std::string, std::list or std::vector can be traversed in both directions.
Using a std::string the solution could be:
#include <iostream>
#include <string>
using namespace std;
int main(int, char**) {
char n = 0;
string a;
while (n != '.' && a.size() < 10) {
cin >> n;
if (n != '.') {
a.push_back(n);
}
}
for (string::reverse_iterator it = a.rbegin(); it != a.rend(); ++it) {
cout << *it << endl;
}
}
I will start by saying: use std::string instead of C-style strings - it's universally less messy and more flexible.
Still, let's go with C-style strings since that's how you are attempting to do it and apparently your textbook also.
I won't comment on the way the user input is read, because I'm not sure if it's copied from the textbook (yikes!!) or you've done it yourself either way I find it to be pointless and wrong because it can lead to several problems. Note that the given book solution only prints out the characters in the reversed order and doesn't reverse the character array itself. You are apparently trying to reverse it.
Your solution is decrementing the numbers_used variable inside the for loop itself. This is a very bad idea since that variable is used in the conditional statement of the for loop. This means the loop will stop before it has iterated over the whole array. Even if the loop worked properly you still wouldn't have reversed the array since once this line executes
a[index] = a[numbers_used -1];
the original value of a[index] is overwritten and forgotten.
I'll try and write a simple solution to reverse a character array for a beginner:
#include <iostream>
#include <cstring> //getline, strlen
using namespace std;
const int MAX_LETTERS = 10;
int main() {
char a[MAX_LETTERS + 1]; //since it's zero terminated
cout << "Enter at most " << MAX_LETTERS << "characters (anything over " <<
MAX_LETTERS << " will be truncated):\n";
cin.getline(a, MAX_LETTERS + 1);
int length = strlen(a); //returns length of input
int last_char = length - 1;
//reverse array
for (int i = 0; i < length / 2; i++) {
char temp = a[i];
a[i] = a[last_char];
a[last_char] = temp;
last_char--;
}
//print array
for (int i = 0; i < length; i++)
cout << a[i];
return 0;
}
Read this tutorial on C style strings, it will help you a lot.
The last for loop in your code is
int numbers_used = index;
for(index = 0; index <= numbers_used; index++)
{
a[index] = a[numbers_used -1];
numbers_used--;
cout << a[index] << " " << endl;
}
If we consider 10 letters abcdefghij and according to your code the numbers_used=10after first loop.So in second loop
//In for loop
//index=0
a[index]=a[numbers_used-1]; // a[0]=a[9] => a[0]=j
numbers_used--; //numbers_used=9;
//index=1
a[index]=a[numbers_used-1]; //a[1]=a[8] => a[1]=i
numbers_used--; //numbers_used=8;
//index=2
a[index]=a[numbers_used-1]; //a[2]=a[7] => a[1]=h
numbers_used--; //numbers_used=7;
//index=3
a[index]=a[numbers_used-1]; //a[3]=a[6] => a[1]=g
numbers_used--; //numbers_used=6;
//index=4
a[index]=a[numbers_used-1]; //a[4]=a[5] => a[4]=f
numbers_used--; //numbers_used=5;
//index=5
a[index]=a[numbers_used-1]; //a[5]=a[5] => a[5]=e
numbers_used--; //numbers_used=4;
// index=6 and numbers_used becomes 4 => index <= numbers_used condition is violated
so you will out of for loop.
This is why u cant get through. And in the second code i,e in the Book.
for(index = numbers_used -1; index >= 0; index--)
cout<<a[index];
cout<< endl;
The numbers_used value is 10 but a[9] is the last value in the array so index is assigned to numbers_used-1. so that you can print from a[9] to a[0].

Wrong looping/Reading C++

I am just learning C++. I wrote a program that shows the repeated letters in a string (I also have to count how many times it the letter gets repeated). The thing is when I run my code to get the repeated letters from the sentence. It runs okay for some but not some. For example: "hi there" runs good returning h and e, but something like "people are nice" returns peeeeee.The repeated letter should be shown only once. Point the problem out to me please. I assumed it had to do with the looping but can't figure it out exactly.
void repeatWord(string sentence)
{
for(int i=0; i<sentence.length(); i++)
for(int j=i+1; j<sentence.length(); j++)
if((!isspace(sentence[i]))&&(sentence[i] == sentence[j])){
cout<<sentence[i]<<endl;
}
return;
}
The problem is your inner loop. It displays the letter once every time it's encountered. Also, you do not break out of the loop after seeing a duplicate, so you get an exponential mess.
A better way is to just record how many times you've seen a letter. That requires just one loop and an array:
int count[256] = {0};
for( int i = 0; i < sentence.length(); i++ ) {
char c = sentence[i];
if( isalpha(c) && count[c]++ == 1 ) cout << c;
}
Instead of the array, you can use std::set. That would be more appropriate if you were handling Unicode. However, we're just dealing with a char here, which is 8 bits on almost every architecture you're likely to be practising on.
A little bonus of doing it this way is that you compute the letter frequencies. You can output these as follows:
for( int c = 0; c < 256; c++ ) {
if( count[c] ) cout << (char)c << " : " << count[c] << endl;
}
If you want to output case-insensitive counts, one way to do it is like this:
for( int c = 'a'; c <= 'z'; c++ ) {
int total = count[c] + count[toupper(c)];
if( total ) cout << (char)c << " : " << total << endl;
}
Getting rid of repeating letters is easy: just insert into a <set> or delete the letters after you see them. Inserting into a set is more efficient however:
set<char> letters;
for(int i=0; i<sentence.length(); i++)
for(int j=i+1; j<sentence.length(); j++)
if((!isspace(sentence[i]))&&(sentence[i] == sentence[j])){
letters.insert(sentence(i));
}
for(auto &i : letters)
cout << i << endl;