This question already has answers here:
For loop prints an extra comma
(9 answers)
Closed 2 years ago.
I want to find prime numbers in a given range.
The output number must be separated by a comma.
#include <iostream>
using namespace std;
int main()
{
int i,j,lower, upper;
cin >> lower;
cin >> upper;
for (i = lower + 1; i < upper; i++)
{
for (j = 2; j < i; j++)
{
if (i % j == 0)
{
break;
}
}
if (j == i)
{
cout << i ;
cout << ",";
}
}
}
Input:11 20
Output must be : 13,17,19
but my code prints an extra comma and it is not just between the numbers. Would you please help me?!
Instead of printing the result right away, you can store it in a vector, so you know exactly how many numbers you want to print. Then you print your vector this way :
std::vector result;
std::string output = "";
for (size_t i = 0; i < result.size(); ++i) // Notice the ++i, not i++
{
if (i != 0)
output += ", ";
output += result[i];
}
If you don't want to store your result in a vector, you can define a boolean firstResult to true if you don't have printed a coma yet, then to false when you have printed the first result, and you print the coma before the number.
int main()
{
bool firstResult = true;
[...]
if (j == i)
{
if (!firstResult)
cout << ",";
firstResult = false;
cout << i ;
}
}
Related
I don't know how to use the find() function to check if a string contains a substring, then the program should print out all Words, and "Contains" if Sentence contains at least one of them. Can anyone help me out? My usage of find() sets A always to true. Thanks for help
#include <iostream>
#include <string>
using namespace std;
string Words, Sentence, buf;
int i, n, j = 0;
string arr[20];
bool A;
int main() {
cout << "Words separated by slashes";
cin >> Words;
cout << "Sentence";
cin >> Sentence;
for (i = 0; i <= Words.length(); i++)
{
if (Words[i] != '/')
{
buf = buf + Words[i];
}
else
{
arr[n] = buf;
n = n + 1;
buf = "";
}
}
for (j = 0; j <= n; j++)
{
cout << arr[j] << "\n";
if (Sentence.find(arr[j]) != string::npos)
{
A = true;
}
}
if (A == true)
{
cout << "Contains.";
}
else
{
enter code herecout << "Does not contain.";
}
}
There are a few bugs and issues in this code I think, but the biggest is the for loops all go too far by one.
for (i = 0; i <= Words.length(); i++)
and
for (j = 0; j <= n; j++)
should be
for (i = 0; i < Words.length(); i++)
and
for (j = 0; j < n; j++)
The valid indexes for a string, vector or array are zero upto but not including the size of the string, vector or array.
This mistake causes the bug that you see. Suppose you have two words in arr, e.g. arr = { "stack", "overflow", "", "", ... } . Because you go around the for loop one too many times you end up searching for arr[2] which equals "". This search always succeeds because every string contains the empty string. And so you always set A to true.
I'm trying to convert an histogram with absolute values to an histogram showing the relative frequency of letters in a string, written by the user. The letters frequency should be represented by *. So, if the letter "A" is 1% of a string, there should be two *. 1% = two *.
When trying to calculate the frequency, the output is zero. I don't really understand why.
I've tried to search the internet, but I can't really find something that helps me. I guess I'm stuck, both in my head and coding.
This is the code for my three functions:
void berakna_histogram_abs(const string inm, int arr[ANTAL_BOKSTAVER]){
int i, j = 0;
while (inm[i] != '\0'){
if (inm[i] >= 'a' && inm[i] <= 'z'){
j = inm[i] - 'a';
++arr[j];
}
if (inm[i] >= 'A' && inm[i] <= 'Z'){
j = inm[i] - 'A';
++arr[j];
}
i++;
}
}
void abs_till_rel(int arr[ANTAL_BOKSTAVER], int (&ree)[ANTAL_BOKSTAVER]){
for(int i = 0; i < ANTAL_BOKSTAVER; i++) {
ree[i] = arr[i] / 26;
printf("%c %lf \n", i + 'a', ree[i]);
}
for (int x = 0; x < ANTAL_BOKSTAVER; x++){
}
}
void plotta_histogram_rel(int (&ree)[ANTAL_BOKSTAVER]){
cout << "Frekvensen av bokstäver i texten är: " << endl;
for (int i = 0; i < ANTAL_BOKSTAVER; i++){
cout << char(i + 'a') << " : " << ree[i] << endl;
}
}
I'm not allowed to do any calculations in the third function, that is only for writing the histogram. The whole program is pretty big, if you'd like, I'll provide all the code.
Any help forward is much appreciated.
Thanks!
So, you have some errors that need to be corrected. You do not pass the array as reference in the first function. You pass it by value. So all modifications that will be done to that arra in the first function berakna_histogram_abs will not be visible to the outside world.
You need to do the same as in you other functions -->
void berakna_histogram_abs(const std::string inm, int (&arr)[ANTAL_BOKSTAVER]) {
By the way, the string should also be passed as reference. Anyway. Not so important.
Next problem. You forgot to initialize variable i to 0 in your first function. So, it will have some random value and the program will fail, becuase you access some random index with inm[i].
In your calculation function abs_till_rel you are using the wrong formular. You need to multiply with 100 to get integer results between 0 and 100 for the percentage. And you divide by 26, which makes the result relative to the amount of the number of letters in an alphabet. My guess is that you want to have the relations to the number of letters in the string.
For that, you first need to calculate all counts of letters to get the overall count. Like for example with:
int sum = 0;
for (int i = 0; i < ANTAL_BOKSTAVER; i++) sum += arr[i];
and then divide by this sum, like so:
ree[i] = (arr[i] * 100) / sum;
And to output the histogram, you can simply build a string with stars, using the std::string constructor number 2
Your updated program would look like this:
#include <iostream>
#include <string>
#include <stdio.h>
constexpr int ANTAL_BOKSTAVER = 26;
void berakna_histogram_abs(const std::string inm, int (&arr)[ANTAL_BOKSTAVER]) {
int i = 0, j = 0;
while (inm[i] != '\0') {
if (inm[i] >= 'a' && inm[i] <= 'z') {
j = inm[i] - 'a';
++arr[j];
}
if (inm[i] >= 'A' && inm[i] <= 'Z') {
j = inm[i] - 'A';
++arr[j];
}
i++;
}
}
void abs_till_rel(int arr[ANTAL_BOKSTAVER], int(&ree)[ANTAL_BOKSTAVER]) {
int sum = 0;
for (int i = 0; i < ANTAL_BOKSTAVER; i++) sum += arr[i];
if (sum >0) for (int i = 0; i < ANTAL_BOKSTAVER; i++) {
ree[i] = (arr[i] * 100) / sum;
std::cout << (char)(i + 'a') << '\t' << ree[i] << '\n';
}
for (int x = 0; x < ANTAL_BOKSTAVER; x++) {
}
}
void plotta_histogram_rel(int(&ree)[ANTAL_BOKSTAVER]) {
std::cout << "Frekvensen av bokstäver i texten är: " << std::endl;
for (int i = 0; i < ANTAL_BOKSTAVER; i++) {
std::cout << char(i + 'a') << " : " << std::string(ree[i]*2,'*') << std::endl;
}
}
int main() {
std::string test{"The quick brown fox jumps over the lazy dog"};
int frequencyArray[ANTAL_BOKSTAVER] = {};
int frequencyInPercent[ANTAL_BOKSTAVER] = {};
berakna_histogram_abs(test, frequencyArray);
abs_till_rel(frequencyArray, frequencyInPercent);
plotta_histogram_rel(frequencyInPercent);
}
But in C++, we would use the standard approach and write the followin:
#include <iostream>
#include <map>
#include <string>
#include <cctype>
// Our test string. This is a standard test string that contains all letters
std::string test{ "The quick brown fox jumps over the lazy dog" };
int main() {
// Count all letters
std::map<char, size_t> counter{};
for (const auto& c : test) if (std::isalpha(c)) counter[std::tolower(c)]++;
// Show histogram
for (const auto& [letter, count] : counter)
std::cout << letter << '\t' << std::string((count * 200) / test.size(), '*') << '\n';
return 0;
}
void abs_till_rel(int arr[ANTAL_BOKSTAVER], int langd, double frekArr[ANTAL_BOKSTAVER]){
//Function to calculate the relative frequency of letters in a string.
for (int i = 0; i < ANTAL_BOKSTAVER; i++){
frekArr[i] = arr[i]; //Writes over the input from the user to a new array.
frekArr[i] = frekArr[i] * 200 / langd; //Calculates the relative frequency
//*200 since 1% should be represented by two (2) *.
}
}
void plotta_histogram_rel(double frekArr[ANTAL_BOKSTAVER], int langd){
int j = 0;
for (int i = 0; i < ANTAL_BOKSTAVER; i++){
cout << char(i + 'A') << " : ";
//Creates a histograg, horizontal, with A-Z.
if(frekArr[i] > 0){
for ( j = 0; j < frekArr[i]; j++){
cout << "*";
}
cout << endl;
}
//If the index in frekArr is NOT empty, loop through the index [i] times and
//write double the amount of *.
else {
cout << " " << endl;
//Else, leave it empty.
}
}
}
I've solved the issue. See the working code above.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
string compression(const string & str){
int i = str.size();
string letters;
letters[0] = str[0];
for (int j = 0; j < i; ++j){
int count = 1;
while (str[j] == str[j+1]){
count++;
j++;
}
letters.push_back('0' + count);
letters.push_back(str[j]);
}
return letters;
}
int main(){
string input;
char c;
try {
cout << "Enter the data to be compressesed: "<< endl;
cin >> input;
for (int z = 0; z < input.length(); ++z){
c = input.at(z);
}
if (!(c >= 'a' && c <= 'z')){
throw runtime_error("error: invalid input");
}
}
catch (runtime_error& excpt){
cout << excpt.what() <<endl;
return 0;
}
cout << "The compressed data is " << compression(input) << endl;
return 0;
}
The expected output is , repeated for each run of characters. Here is the amount of times is repeated in sequence.
Some examples:
aaeeeeae = 2a4e1a1e
rr44errre = invalid input
eeeeeeeeeeeeeeeeeeeee = 21e
the code works properly only if the character is repeated consecutively 9 times or less. for values of 10 and more the input is other symbols.
For example it stays blank for 10, so if input is 'aaaaaaaaaabb',output just would be 'a2b' instead of '10a2b'. For 11 its outputs ';',
so if input is 'aaaaaaaaaaabb', output is ';a2b' for some reason.
So my question is, how do i make the pushback work for all numbers and not just from 0-9?
Thank you for your time if u've gotten to here. ^^
If you can use c++11 or newer your function compression could look like:
string compression(const string & str){
int i = str.size();
string letters;
for (int j = 0; j < i; ++j){
int count = 1;
while (str[j] == str[j+1]){
count++;
j++;
}
letters += std::to_string(count);
letters.push_back(str[j]);
}
return letters;
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Trying to implement a fairly simple program in C++. I'm kinda new to this language. But it doesn't seem to be working.
#include <iostream>
#include <string>
using namespace std;
bool isUnique(string);
int main(){
bool uniq;
string a;
cout << "Please input a string, not a very long one...."<< endl;
getline(cin, a);
uniq = isUnique(a);
if (uniq == true)
{
cout << "The string has no repeatations." <<endl;
}else{
cout << "The characters in the string are not unique." <<endl;
}
return EXIT_SUCCESS;
}
bool isUnique(string str){
int len = strlen(str);
bool uniq = true;
for (int i = 0; i <= len; ++i)
{
for (int j = i+1; j <= len; ++j)
{
if (str[j] == str[i])
{
uniq = false;
}
}
}
return uniq;
}
The program compiles but has some logical errors I suppose. Any help appreciated.
An simple criterion for uniqueness is that there are no repeated characters in the sorted range of characters. There are algorithms in the standard library for this:
#include <algorithm> // for std::sort, std::unique
#include <iostream> // for std::cin, std::cout
#include <string> // for std:getline, std::string
int main()
{
std::string input;
std::cout << "Please input a string, not a very long one: ";
std::getline(input, std::cin);
std::sort(input.begin(), input.end());
bool u = std::unique(input.begin(), input.end()) == input.end();
if (u) { std::cout << "Every character is unique.\n"; }
else { std::cout << "The string contains repeated characters.\n"; }
}
As an optimization, you can exit early if the string has more characters than there are unique characters, though you'd need some way to determine what that number is.
You can check uniqueness much easier without a nested loop: make an array of bool[256], cast char to unsigned char, and use as an index into the array. If a bool has been set, the characters are not unique; otherwise, they are unique.
bool seen[256];
for (int i = 0 ; i != str.length() ; i++) {
unsigned char index = (unsigned char)str[i];
if (seen[index]) return false;
seen[index] = true;
}
return true;
The idea is simple: you mark characters that you've seen as you go, returning false if you see a "marked" character. If you reach the end without returning, all characters are unique.
This algorithm is O(n); your algorithm is O(n2). This does not make much difference, though, because it is impossible to construct a string of unique characters that is longer than 256 characters.
You are using a string, so it is not necessary to convert it to a char array. Use the string to check. You can check it like this:
bool isUnique(string str){
for (std::string::size_type i = 0; i < str.size(); ++i)
{
if(i < str.size()-1){
for (std::string::size_type j = i+1; j < str.size(); ++j)
{
if (str[j] == str[i])
{
uniq = false;
}
}
}
}
return uniq;
}
you can try this:
int main () {
bool uniqe=false;
string a;
char arr[1024];
int count[256]={0};
cout << "Please input a string, not a very long one...."<< endl;
getline(cin, a);
strcpy(arr, a.c_str());
for(int i=0;i<strlen(arr);i++)
count[(int)(arr[i])]++; // counting the occurence of character
for(int i=0;i<256;i++){
if(count[i]>1){ // if count > 1 means character are repeated.
uniqe=false;
break;
}else{
uniqe=true;
}
}
if(uniqe)
cout << "The string has no repeatations." <<endl;
else
cout << "The characters in the string are not unique." <<endl;
return 0;
}
There are too many errors in your code. For example instead of
int len = sizeof(arr)/sizeof(*arr);
there shall be
size_t len = std::strlen( arr );
Or instead of
for (int i = 0; i <= len; ++i)
there shall be at least
for (int i = 0; i < len; ++i)
and so on.
And there is no any need to define a character array. Class std::string has all that is required to do the task.
Try the following function
bool isUnique( const std::string &s )
{
bool unique = true;
for ( std::string::size_type i = 0; i < s.size() && unique; i++ )
{
std::string::size_type j = 0;
while ( j < i && s[j] != s[i] ) ++j;
unique = j == i;
}
return unique;
}
Here is a demonstrative program
#include <iostream>
#include <iomanip>
#include <string>
bool isUnique( const std::string &s )
{
bool unique = true;
for ( std::string::size_type i = 0; i < s.size() && unique; i++ )
{
std::string::size_type j = 0;
while ( j < i && s[j] != s[i] ) ++j;
unique = j == i;
}
return unique;
}
int main()
{
std::string s( "abcdef" );
std::cout << std::boolalpha << isUnique( s ) << std::endl;
s = "abcdefa";
std::cout << std::boolalpha << isUnique( s ) << std::endl;
return 0;
}
The output is
true
false
Here is your code with the errors fixed:
#include <iostream>
using namespace std;
bool isUnique(string,int); //extra parameter
int main(){
bool uniq;
string a;
cout << "Please input a string, not a very long one...."<< endl;
getline(cin, a);
uniq = isUnique(a,a.length()); //pass length of a
if (uniq == true)
{
cout << "The string has no repeatations." <<endl;
}else{
cout << "The characters in the string are not unique." <<endl;
}
return EXIT_SUCCESS;
}
bool isUnique(string str,int len){
bool uniq = true;
for (int i = 0; i < len-1; ++i) //len-1 else j would access unitialized memory location in the last iteration
{
for (int j = i+1; j < len; ++j) //j<len because array index starts from 0
{
if (str[j] == str[i])
{
uniq = false;
}
}
}
return uniq;
}
This question already has answers here:
How can I print a list of elements separated by commas?
(34 answers)
Closed 7 years ago.
LANGUAGE: C++
Hello, in the following function (code block) i have written a line to print an space between characters but i don't want print spaces after last characters. How can i solve this problem?
bool perfecto(int n)
{
int suma, i;
suma = 0;
for (i = 1; i < n; i++)
{
if (n % i == 0)
{
suma += i;
cout << i << " ";
}
}
if (suma == n)
return true;
else
return false;
}
Best regards.
Ángel Manuel.
The simplest way would be to turn the problem around: if you only print spaces before printing the number (and not after) then it becomes how not to print the first time, which is much easier.
I'll let you figure it out :)
bool perfecto(int n)
{
int suma, i;
suma = 0;
bool first = true;
for (i = 1; i < n; i++)
{
if (n % i == 0)
{
suma += i;
if ( !first )
{
cout << " ";
}
cout << i;
first = false;
}
}
if (suma == n)
return true;
else
return false;
}
You can either check if i is equal to n - 1 and not print it in that case, or something like
std::cout << "1";
for (int i = 2; i < n; ++i)
{
std::cout << " " << i;
}
In the second case, you have to watch for for a case where n is 1 or less
There are a variety of options. In this case, probably the easiest is to print spaces BEFORE elements except the first and use a flag to track the first element:
bool perfecto(int n)
{
int suma, i;
suma = 0;
bool first = true;
for (i = 1; i < n; i++)
{
if (n % i == 0)
{
suma += i;
if(!first)
{
std::cout << " ";
}
else first = false;
cout << i;
}
}
if (suma == n)
return true;
else
return false;
}
EDIT: Other popular alternatives are printing the first item and no delimiter outside the loop completely and then inside the loop you can always pre-print the item with no if-check at all. This approach wouldn't work as well with your loop though since you don't always know when the first item will print. You can also create wrapper ostream like classes that keep track of their internal printing state and know when to put the spaces.
Replace this line: cout << i << " ";
with:
cout << i;
if (i == n-1)
cout << endl;
else
cout << " ";