I am trying to convert input text/numbers (string), which will include any characters, but I want to separate the numbers from the characters and store them into an integer array, once it is converted from a string.
I believe the problem is where the string is converting to an integer by use of stoi(), but I cannot seem to spot the problem.
Currently, the code accepts any input and turns it into a string, the string is then checked character by character, and all the numbers without separation with comma or space is added together, once a comma or space, or any other character separates the number, the number as a whole is added to the array, and then continues to check the string for more numbers.
Any ideas?
Input Example1: 12, 13, 15
Input Example2: 12 13 15
Input Example3: 12ab13cd15ef
Result in integer array: 0[12] 1[13] 2[15]
These numbers will be used in the specific order, by using the numbers within the array.
#include<iostream>
#include<string>
#include <sstream>
using namespace std;
int main()
{
string datainput, str1, str3;
cin >> datainput;
int n = 0, raycount = 0, c;
int myray[10];
while (datainput[n])
{
if (datainput[n] == ('0') || datainput[n] == ('1') || datainput[n] == ('2') || datainput[n] == ('3') || datainput[n] == ('4') ||
datainput[n] == ('5') || datainput[n] == ('6') || datainput[n] == ('7') || datainput[n] == ('8') || datainput[n] == ('9'))
{
str1 = datainput[n];
str3 += str1;
}
else
{
c= stoi(str3);
c >> myray[raycount];
raycount++;
}
n++;
}
cout << myray[0] << endl;
cout << myray[1] << endl;
cout << myray[2] << endl;
cout << myray[3] << endl;
system("pause");
return 0;
}
I see quite a few issues with your code.
Prior to C++11, while (datainput[n]) has undefined behavior once n reaches the end of the string.
The way you are checking for numeric digits can be greatly simplified using std::isdigit(), or even just a simple range check using the >= and <= operators.
You are not correctly accounting for numbers that are separated by other characters, or when the last number in the string is at the very end of the string.
The statement c >> myray[raycount]; needs to be changed to myray[raycount] = c; instead. And you are not breaking your loop if raycount reaches the max capacity of myray[].
You are not resetting str3 back to an blank string after converting it with std::stoi(). You just keep appending new digits to the end of previous digits with no break in between numbers.
With that said, try something more like this instead:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string datainput, str3;
cin >> datainput;
int myray[10];
int raycount = 0;
bool gettingDigits = false;
for (int n = 0; n < datainput.size(); ++n)
{
char ch = datainput[n];
//if (isdigit(ch))
if (ch >= '0' && ch <= '9')
{
if (!gettingDigits)
{
str3 = "";
gettingDigits = true;
}
str3 += ch;
}
else
{
if (gettingDigits)
{
myray[raycount] = stoi(str3);
raycount++;
str3 = "";
gettingDigits = false;
if (raycount == 10) break;
}
}
}
if (gettingDigits && (raycount < 10))
{
myray[raycount] = stoi(str3);
raycount++;
}
for (int n = 0; n < raycount; ++n)
cout << myray[n] << endl;
system("pause");
return 0;
}
Live Demo
Alternatively:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string datainput, str3;
cin >> datainput;
int myray[10];
int raycount = 0;
string::size_type start = datainput.find_first_of("0123456789");
string::size_type end;
while (start != string::npos)
{
end = datainput.find_first_not_of("0123456789", start+1);
if (end == string::npos)
{
str3 = datainput.substr(start);
myray[raycount] = stoi(str3);
raycount++;
break;
}
str3 = datainput.substr(start, end-start);
myray[raycount] = stoi(str3);
raycount++;
if (raycount == 10) break;
start = datainput.find_first_of("0123456789", end+1);
}
for (int n = 0; n < raycount; ++n)
cout << myray[n] << endl;
system("pause");
return 0;
}
Live Demo
So, you want to segregate numbers and characters into different arrays.
In if block, you are checking for characters, so, I suspect stoi() wouldn't work.
Better typecast it to an integer.
int temp[10];
if (datainput[n] == ('0') || ...) {
temp[n] = int(datainput[n]);
}
This way your temp array would contain the numbers.
The program below I came up with for checking whether two strings are anagrams. Its working fine for small string but for larger strings ( i tried : listened , enlisted ) Its giving me a 'no !'
Help !
#include<iostream.h>
#include<string.h>
#include<stdio.h>
int main()
{
char str1[100], str2[100];
gets(str1);
gets(str2);
int i,j;
int n1=strlen(str1);
int n2=strlen(str2);
int c=0;
if(n1!=n2)
{
cout<<"\nThey are not anagrams ! ";
return 0;
}
else
{
for(i=0;i<n1;i++)
for(j=0;j<n2;j++)
if(str1[i]==str2[j])
++c;
}
if(c==n1)
cout<<"yes ! anagram !! ";
else
cout<<"no ! ";
system("pause");
return 0;
}
I am lazy, so I would use standard library functionality to sort both strings and then compare them:
#include <string>
#include <algorithm>
bool is_anagram(std::string s1, std::string s2)
{
std::sort(s1.begin(), s1.end());
std::sort(s2.begin(), s2.end());
return s1 == s2;
}
A small optimization could be to check that the sizes of the strings are the same before sorting.
But if this algorithm proved to be a bottle-neck, I would temporarily shed some of my laziness and compare it against a simple counting solution:
Compare string lengths
Instantiate a count map, std::unordered_map<char, unsigned int> m
Loop over s1, incrementing the count for each char.
Loop over s2, decrementing the count for each char, then check that the count is 0
The algorithm also fails when asked to find if aa and aa are anagrams. Try tracing the steps of the algorithm mentally or in a debugger to find why; you'll learn more that way.
By the way.. The usual method for finding anagrams is counting how many times each letter appears in the strings. The counts should be equal for each letter. This approach has O(n) time complexity as opposed to O(n²).
bool areAnagram(char *str1, char *str2)
{
// Create two count arrays and initialize all values as 0
int count1[NO_OF_CHARS] = {0};
int count2[NO_OF_CHARS] = {0};
int i;
// For each character in input strings, increment count in
// the corresponding count array
for (i = 0; str1[i] && str2[i]; i++)
{
count1[str1[i]]++;
count2[str2[i]]++;
}
// If both strings are of different length. Removing this condition
// will make the program fail for strings like "aaca" and "aca"
if (str1[i] || str2[i])
return false;
// Compare count arrays
for (i = 0; i < NO_OF_CHARS; i++)
if (count1[i] != count2[i])
return false;
return true;
}
I see 2 main approaches below:
Sort then compare
Count the occurrences of each letter
It's interesting to see that Suraj's nice solution got one point (by me, at the time of writing) but a sort one got 22. The explanation is that performance wasn't in people's mind - and that's fine for short strings.
The sort implementation is only 3 lines long, but the counting one beats it square for long strings. It is much faster (O(N) versus O(NlogN)).
Got the following results with 500 MBytes long strings.
Sort - 162.8 secs
Count - 2.864 secs
Multi threaded Count - 3.321 secs
The multi threaded attempt was a naive one that tried to double the speed by counting in separate threads, one for each string. Memory access is the bottleneck and this is an example where multi threading makes things a bit worse.
I would be happy to see some idea that would speed up the count solution (think by someone good with memory latency issues, caches).
#include<stdio.h>
#include<string.h>
int is_anagram(char* str1, char* str2){
if(strlen(str1)==strspn(str1,str2) && strlen(str1)==strspn(str2,str1) &&
strlen(str1)==strlen(str2))
return 1;
return 0;
}
int main(){
char* str1 = "stream";
char* str2 = "master";
if(is_anagram(str1,str2))
printf("%s and %s are anagram to each other",str1,str2);
else
printf("%s and %s are not anagram to each other",str1,str2);
return 0;
}
#include<iostream>
#include<unordered_map>
using namespace std;
int checkAnagram (string &str1, string &str2)
{
unordered_map<char,int> count1, count2;
unordered_map<char,int>::iterator it1, it2;
int isAnagram = 0;
if (str1.size() != str2.size()) {
return -1;
}
for (unsigned int i = 0; i < str1.size(); i++) {
if (count1.find(str1[i]) != count1.end()){
count1[str1[i]]++;
} else {
count1.insert(pair<char,int>(str1[i], 1));
}
}
for (unsigned int i = 0; i < str2.size(); i++) {
if (count2.find(str2[i]) != count2.end()) {
count2[str2[i]]++;
} else {
count2.insert(pair<char,int>(str2[i], 1));
}
}
for (unordered_map<char, int>::iterator itUm1 = count1.begin(); itUm1 != count1.end(); itUm1++) {
unordered_map<char, int>::iterator itUm2 = count2.find(itUm1->first);
if (itUm2 != count2.end()) {
if (itUm1->second != itUm2->second){
isAnagram = -1;
break;
}
}
}
return isAnagram;
}
int main(void)
{
string str1("WillIamShakespeare");
string str2("IamaWeakishSpeller");
cout << "checkAnagram() for " << str1 << "," << str2 << " : " << checkAnagram(str1, str2) << endl;
return 0;
}
It's funny how sometimes the best questions are the simplest.
The problem here is how to deduce whether two words are anagrams - a word being essentially an unsorted multiset of chars.
We know we have to sort, but ideally we'd want to avoid the time-complexity of sort.
It turns out that in many cases we can eliminate many words that are dissimilar in linear time by running through them both and XOR-ing the character values into an accumulator. The total XOR of all characters in both strings must be zero if both strings are anagrams, regardless of ordering. This is because anything xored with itself becomes zero.
Of course the inverse is not true. Just because the accumulator is zero does not mean we have an anagram match.
Using this information, we can eliminate many non-anagrams without a sort, short-circuiting at least the non-anagram case.
#include <iostream>
#include <string>
#include <algorithm>
//
// return a sorted copy of a string
//
std::string sorted(std::string in)
{
std::sort(in.begin(), in.end());
return in;
}
//
// check whether xor-ing the values in two ranges results in zero.
// #pre first2 addresses a range that is at least as big as (last1-first1)
//
bool xor_is_zero(std::string::const_iterator first1,
std::string::const_iterator last1,
std::string::const_iterator first2)
{
char x = 0;
while (first1 != last1) {
x ^= *first1++;
x ^= *first2++;
}
return x == 0;
}
//
// deduce whether two strings are the same length
//
bool same_size(const std::string& l, const std::string& r)
{
return l.size() == r.size();
}
//
// deduce whether two words are anagrams of each other
// I have passed by const ref because we may not need a copy
//
bool is_anagram(const std::string& l, const std::string& r)
{
return same_size(l, r)
&& xor_is_zero(l.begin(), l.end(), r.begin())
&& sorted(l) == sorted(r);
}
// test
int main() {
using namespace std;
auto s1 = "apple"s;
auto s2 = "eppla"s;
cout << is_anagram(s1, s2) << '\n';
s2 = "pppla"s;
cout << is_anagram(s1, s2) << '\n';
return 0;
}
expected:
1
0
Try this:
// Anagram. Two words are said to be anagrams of each other if the letters from one word can be rearranged to form the other word.
// From the above definition it is clear that two strings are anagrams if all characters in both strings occur same number of times.
// For example "xyz" and "zxy" are anagram strings, here every character 'x', 'y' and 'z' occur only one time in both strings.
#include <map>
#include <string>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
bool IsAnagram_1( string w1, string w2 )
{
// Compare string lengths
if ( w1.length() != w2.length() )
return false;
sort( w1.begin(), w1.end() );
sort( w2.begin(), w2.end() );
return w1 == w2;
}
map<char, size_t> key_word( const string & w )
{
// Declare a map which is an associative container that will store a key value and a mapped value pairs
// The key value is a letter in a word and the maped value is the number of times this letter appears in the word
map<char, size_t> m;
// Step over the characters of string w and use each character as a key value in the map
for ( auto & c : w )
{
// Access the mapped value directly by its corresponding key using the bracket operator
++m[toupper( c )];
}
return ( m );
}
bool IsAnagram_2( const string & w1, const string & w2 )
{
// Compare string lengths
if ( w1.length() != w2.length() )
return false;
return ( key_word( w1 ) == key_word( w2 ) );
}
bool IsAnagram_3( const string & w1, const string & w2 )
{
// Compare string lengths
if ( w1.length() != w2.length() )
return false;
// Instantiate a count map, std::unordered_map<char, unsigned int> m
unordered_map<char, size_t> m;
// Loop over the characters of string w1 incrementing the count for each character
for ( auto & c : w1 )
{
// Access the mapped value directly by its corresponding key using the bracket operator
++m[toupper(c)];
}
// Loop over the characters of string w2 decrementing the count for each character
for ( auto & c : w2 )
{
// Access the mapped value directly by its corresponding key using the bracket operator
--m[toupper(c)];
}
// Check to see if the mapped values are all zeros
for ( auto & c : w2 )
{
if ( m[toupper(c)] != 0 )
return false;
}
return true;
}
int main( )
{
string word1, word2;
cout << "Enter first word: ";
cin >> word1;
cout << "Enter second word: ";
cin >> word2;
if ( IsAnagram_1( word1, word2 ) )
cout << "\nAnagram" << endl;
else
cout << "\nNot Anagram" << endl;
if ( IsAnagram_2( word1, word2 ) )
cout << "\nAnagram" << endl;
else
cout << "\nNot Anagram" << endl;
if ( IsAnagram_3( word1, word2 ) )
cout << "\nAnagram" << endl;
else
cout << "\nNot Anagram" << endl;
system("pause");
return 0;
}
In this approach I took care of empty strings and repeated characters as well. Enjoy it and comment any limitation.
#include <iostream>
#include <map>
#include <string>
using namespace std;
bool is_anagram( const string a, const string b ){
std::map<char, int> m;
int count = 0;
for (int i = 0; i < a.length(); i++) {
map<char, int>::iterator it = m.find(a[i]);
if (it == m.end()) {
m.insert(m.begin(), pair<char, int>(a[i], 1));
} else {
m[a[i]]++;
}
}
for (int i = 0; i < b.length(); i++) {
map<char, int>::iterator it = m.find(b[i]);
if (it == m.end()) {
m.insert(m.begin(), pair<char, int>(b[i], 1));
} else {
m[b[i]]--;
}
}
if (a.length() <= b.length()) {
for (int i = 0; i < a.length(); i++) {
if (m[a[i]] >= 0) {
count++;
} else
return false;
}
if (count == a.length() && a.length() > 0)
return true;
else
return false;
} else {
for (int i = 0; i < b.length(); i++) {
if (m[b[i]] >= 0) {
count++;
} else {
return false;
}
}
if (count == b.length() && b.length() > 0)
return true;
else
return false;
}
return true;
}
Check if the two strings have identical counts for each unique char.
bool is_Anagram_String(char* str1,char* str2){
int first_len=(int)strlen(str1);
int sec_len=(int)strlen(str2);
if (first_len!=sec_len)
return false;
int letters[256] = {0};
int num_unique_chars = 0;
int num_completed_t = 0;
for(int i=0;i<first_len;++i){
int char_letter=(int)str1[i];
if(letters[char_letter]==0)
++num_unique_chars;
++letters[char_letter];
}
for (int i = 0; i < sec_len; ++i) {
int c = (int) str2[i];
if (letters[c] == 0) { // Found more of char c in t than in s.
return false;
}
--letters[c];
if (letters[c] == 0) {
++num_completed_t;
if (num_completed_t == num_unique_chars) {
// it’s a match if t has been processed completely
return i == sec_len - 1;
}
}
}
return false;}
#include <iostream>
#include <string.h>
using namespace std;
const int MAX = 100;
char cadA[MAX];
char cadB[MAX];
bool chrLocate;
int i,m,n,j, contaChr;
void buscaChr(char [], char []);
int main() {
cout << "Ingresa CadA: ";
cin.getline(cadA, sizeof(cadA));
cout << "Ingresa CadB: ";
cin.getline(cadB, sizeof(cadA));
if ( strlen(cadA) == strlen(cadB) ) {
buscaChr(cadA,cadB);
} else {
cout << "No son Anagramas..." << endl;
}
return 0;
}
void buscaChr(char a[], char b[]) {
j = 0;
contaChr = 0;
for ( i = 0; ( (i < strlen(a)) && contaChr < 2 ); i++ ) {
for ( m = 0; m < strlen(b); m++ ) {
if ( a[i] == b[m]) {
j++;
contaChr++;
a[i] = '-';
b[m] = '+';
} else { contaChr = 0; }
}
}
if ( j == strlen(a)) {
cout << "SI son Anagramas..." << endl;
} else {
cout << "No son Anagramas..." << endl;
}
}
Your algorithm is incorrect. You're checking each character in the first word to see how many times that character appears in the second word. If the two words were 'aaaa', and 'aaaa', then that would give you a count of 16. A small alteration to your code would allow it to work, but give a complexity of N^2 as you have a double loop.
for(i=0;i<n1;i++)
for(j=0;j<n2;j++)
if(str1[i]==str2[j])
++c, str2[j] = 0; // 'cross off' letters as they are found.
I done some tests with anagram comparisons. Comparing two strings of 72 characters each (the strings are always true anagrams to get maximum number of comparisons), performing 256 same-tests with a few different STL containers...
template<typename STORAGE>
bool isAnagram(const string& s1, const string& s2, STORAGE& asciiCount)
{
for(auto& v : s1)
{
asciiCount[v]++;
}
for(auto& v : s2)
{
if(--asciiCount[static_cast<unsigned char>(v)] == -1)
{
return false;
}
}
return true;
}
Where STORAGE asciiCount =
map<char, int> storage; // 738us
unordered_map<char, int> storage; // 260us
vector<int> storage(256); // 43us
// g++ -std=c++17 -O3 -Wall -pedantic
This is the fastest I can get.
These are crude tests using coliru online compiler + and std::chrono::steady_clock::time_point for measurements, however they give a general idea of performance gains.
vector has the same performance, uses only 256 bytes, although strings are limited to 255 characters in length (also change to: --asciiCount[static_cast(v)] == 255 for unsigned char counting).
Assuming vector is the fastest. An improvement would be to just allocate a C style array unsigned char asciiCount[256]; on the stack (since STL containers allocate their memory dynamically on the heap)
You could probably reduce this storage to 128 bytes, 64 or even 32 bytes (ascii chars are typically in range 0..127, while A-Z+a-z 64.127, and just upper or lower case 64..95 or 96...127) although not sure what gains would be found from fitting this inside a cache line or half.
Any better ways to do this? For Speed, Memory, Code Elegance?
1. Simple and fast way with deleting matched characters
bool checkAnagram(string s1, string s2) {
for (char i : s1) {
unsigned int pos = s2.find(i,0);
if (pos != string::npos) {
s2.erase(pos,1);
} else {
return false;
}
}
return s2.empty();
}
2. Conversion to prime numbers. Beautiful but very expensive, requires special Big Integer type for long strings.
// https://en.wikipedia.org/wiki/List_of_prime_numbers
int primes[255] = {2, 3, 5, 7, 11, 13, 17, 19, ... , 1613};
bool checkAnagramPrimes(string s1, string s2) {
long c1 = 1;
for (char i : s1) {
c1 = c1 * primes[i];
}
long c2 = 1;
for (char i : s2) {
c2 = c2 * primes[i];
if (c2 > c1) {
return false;
}
}
return c1 == c2;
}
string key="listen";
string key1="silent";
string temp=key1;
int len=0;
//assuming both strings are of equal length
for (int i=0;i<key.length();i++){
for (int j=0;j<key.length();j++){
if(key[i]==temp[j]){
len++;
temp[j] = ' ';//to deal with the duplicates
break;
}
}
}
cout << (len==key.length()); //if true: means the words are anagrams
Instead of using dot h header which is deprecated in modern c++.
Try this solution.
#include <iostream>
#include <string>
#include <map>
int main(){
std::string word_1 {};
std::cout << "Enter first word: ";
std::cin >> word_1;
std::string word_2 {};
std::cout << "Enter second word: ";
std::cin >> word_2;
if(word_1.length() == word_2.length()){
std::map<char, int> word_1_map{};
std::map<char, int> word_2_map{};
for(auto& c: word_1)
word_1_map[std::tolower(c)]++;
for(auto& c: word_2)
word_2_map[std::tolower(c)]++;
if(word_1_map == word_2_map){
std::cout << "Anagrams" << std::endl;
}
else{
std::cout << "Not Anagrams" << std::endl;
}
}else{
std::cout << "Length Mismatch" << std::endl;
}
}
#include <bits/stdc++.h>
using namespace std;
#define NO_OF_CHARS 256
int main()
{ bool ans = true;
string word1 = "rest";
string word2 = "tesr";
unordered_map<char,int>maps;
for(int i = 0 ; i <5 ; i++)
{
maps[word1[i]] +=1;
}
for(int i = 0 ; i <5 ; i++)
{
maps[word2[i]]-=1 ;
}
for(auto i : maps)
{
if(i.second!=0)
{
ans = false;
}
}
cout<<ans;
}
Well if you don't want to sort than this code will give you perfect output.
#include <iostream>
using namespace std;
int main(){
string a="gf da";
string b="da gf";
int al,bl;
int counter =0;
al =a.length();
bl =b.length();
for(int i=0 ;i<al;i++){
for(int j=0;j<bl;j++){
if(a[i]==b[j]){
if(j!=bl){
b[j]=b[b.length()-counter-1];
bl--;
counter++;
break;
}else{
bl--;
counter++;
}
}
}
}
if(counter==al){
cout<<"true";
}
else{
cout<<"false";
}
return 0;
}
Here is the simplest and fastest way to check for anagrams
bool anagram(string a, string b) {
int a_sum = 0, b_sum = 0, i = 0;
while (a[i] != '\0') {
a_sum += (int)a[i]; // (int) cast not necessary
b_sum += (int)b[i];
i++;
}
return a_sum == b_sum;
}
Simply adds the ASCII values and checks if the sums are equal.
For example:
string a = "nap" and string b = "pan"
a_sum = 110 + 97 + 112 = 319
b_sum = 112 + 97 + 110 = 319
I'm trying to format numbers to a specific number of significant digits using C/C++ and preferably STL. I've seen examples of doing this in Javascript (toPrecision()) and .Net, but I can't find anything on doing this in C/C++. I want to create a function something like this:
std::string toPrecision(double value, int significantDigits) {
std::string formattedString;
// magic happens here
return formattedString;
}
So that it produces results like this:
toPrecision(123.4567, 2) --> "120"
toPrecision(123.4567, 4) --> "123.4"
toPrecision(123.4567, 5) --> "123.45"
Does anyone know a good way to do this? I'm considering dumping the whole number into a string and then just scanning through it to find the non-zero digits and count them off in some intelligent way, but that seems cumbersome.
I could also download the source code to one of the browsers and just see what their toPrecision function looks like, but I think it would take me all day to work through the unfamiliar code. Hope someone can help!
Stolen from another question:
#include <string>
#include <sstream>
#include <cmath>
#include <iostream>
std::string toPrecision(double num, int n) {
https://stackoverflow.com/questions/202302/rounding-to-an-arbitrary-number-of-significant-digits
if(num == 0) {
return "0";
}
double d = std::ceil(std::log10(num < 0 ? -num : num));
int power = n - (int)d;
double magnitude = std::pow(10., power);
long shifted = ::round(num*magnitude);
std::ostringstream oss;
oss << shifted/magnitude;
return oss.str();
}
int main() {
std::cout << toPrecision(123.4567, 2) << "\n";
std::cout << toPrecision(123.4567, 4) << "\n";
std::cout << toPrecision(123.4567, 5) << "\n";
}
Check out setprecision() in iomanip. That should do what you are looking for on the double, then just convert to string
Print it to an ostringstream, setting the floating-point formatting parameters as appropriate.
The method above with a ceil(log10(x)) is perfectly legit to determine the number of digit of the integer part of a number. But I feel it's a bit heavy on CPU to call for maths functions just to set a number of digit.
Isn't that simpler to convert the floating value into a string with too many digits, then to work on the string itself?
Here is what I'd try (with Qt instead of the STL):
QString toPrecision(double num, int n) {
QString baseString = QString::number(num, 'f', n);
int pointPosition=baseString.indexOf(QStringLiteral("."));
// If there is a decimal point that will appear in the final result
if (pointPosition != -1 && pointPosition < n)
++n ; // then the string ends up being n+1 in length
if (baseString.count() > n) {
if (pointPosition < n) {
baseString.truncate(n);
} else {
baseString.truncate(pointPosition);
for (int i = n ; i < baseString.count() ; ++i)
baseString[i]='0';
}
} else if (baseString.count() < n) {
if (pointPosition != -1) {
for (int i = n ; i < baseString.count() ; ++i)
baseString.append('0');
} else {
baseString.append(' ');
}
}
return baseString ;
}
But the question was about the STL.. So, let's rewrite it that way:
std::string toPrecision(double num, size_t n) {
std::ostringstream ss;
ss << num ;
std::string baseString(ss.str());
size_t pointPosition=baseString.find('.');
if (pointPosition != std::string::npos && pointPosition < n)
++n ;
if (baseString.length() > n) {
if (pointPosition < n) {
baseString.resize(n);
} else {
baseString.resize(pointPosition);
for (size_t i = n ; i < baseString.length() ; ++i)
baseString[i]='0';
}
} else if (baseString.length() < n) {
if (pointPosition != std::string::npos) {
baseString.append(n-baseString.length(),'0');
} else {
baseString.append(n-baseString.length(),' ');
}
}
return baseString ;
}
I'm not trying to ask you guys to help me to do homework because i've do much research and also try to program it myself but still i encounter problem and i think so far i've know where the problem is but still no solution can be figure out by me :
The Code
#include <iostream>
#include <string>
#include <cmath>
int main(void)
{
using namespace std;
int num;
int max;
string answer = "";
cin >> num;
for(int i = 2 ; i < num ; i++)
{
max = sqrt(i);
if(max < 2) // This must be done beacuse sqrt(2) and sqrt(3)
{ // is 1 which will make it become nonprime.
answer += i;
answer += ' ';
continue;
}
for(int j = 2 ; j <= max ; j++) // Trial division ,divide each by integer
{ // more than 1 and less than sqrt(oftheinteger)
if(i % j == 0)
break;
else if(j == max)
{
answer += i + " ";
answer += ' ';
}
}
}
cout <<"The answer is " << answer ;
return 0;
}
The Question
1.)This program will prompt for a number from user and return all the prime number before it(e.g if user input 9 : then the answer is 2 , 3 , 5 , 7).
2.)I think the wrong part is the string and integer concatenation , till now i still puzzle how to concat string and integer in C++(Previous Javascript programmer so i'm accustomed to using + as string-int concat operator)
3.)Beside the problem i mention above , so far i've go through the code and find none of other problem exist.If any expert manage to find any , mind to point it out to enlighten me??
4.)If there's any mistake in terms of coding or algorithm or anything done by me , please don't hesitate to point it out , i'm willing to learn.
Thanks for spending time reading my question
The usual way to perform formatting in C++ is to use streams.
In this situation, you can use a std::stringstream to accumulate the results, and then convert it into a string when you do the final printing.
Include sstream to get the required type and function declarations:
#include <sstream>
Declare answer to be a std::stringstream instead of a std::string:
stringstream answer;
and then wherever you have:
answer += bla;
, replace it with:
answer << bla;
To get a std::string out of answer, use answer.str():
cout << "The answer is " << answer.str();
If you have to store your complete output before printing it out (I would probably print it as I go, but up to you), a simple way is to use stringstreams.
In this case, rather than answer being an std::string, we can change it to an std::stringstream (and include the <sstream> header).
Now rather than having:
answer += i;
We can just make a simple change and have:
answer << i;
Just as you would if you were printing to cout (which is an ostream).
So basically, += in your code would become <<.
Similar to printing to cout, you can also chain together such as:
answer << a << b
Now to print your stringstream to cout, all you'd need to do is:
cout << my_stringstream.str()
See how you go. I don't want to provide you with the complete since it's homework.
You can go around the string concatenation problem if you just print what you have so far:
int main()
{
int num;
int max;
string answer = "";
cin >> num;
cout << "The answer is ";
for(int i = 2 ; i < num ; i++)
{
max = sqrt((double)i);
if(max < 2) // This must be done beacuse sqrt(2) and sqrt(3)
{ // is 1 which will make it become nonprime.
cout << i << ' ';
continue;
}
for(int j = 2 ; j <= max ; j++) // Trial division ,divide each by integer
{ // more than 1 and less than sqrt(oftheinteger)
if(i % j == 0)
break;
else if(j == max)
{
cout << i << ' ';
}
}
}
return 0;
}
As other mentioned one way to do concatenation is std::stringstream.
it's not very beautiful, but it works. I use a general library "genlib.h", I'm not sure what you use, so you might need to replace that or I can send it to you.
#include "genlib.h"
#include <iostream>
#include <string>
#include <cmath>
using namespace std;
bool IsPrime(int num);
int main()
{
int num;
int i = 2;
cout << "Enter an integer to print previous primes up to: ";
cin >> num;
cout << endl << "The primes numbers are: " << endl;
while(i < num){
if (IsPrime(i) == true){
cout << i << ", ";
}
i++;
}
return 0;
}
bool IsPrime(int num){
if((num == 2) || (num == 3)) {
return true;
}else if ((num % 2) == 0){
return false;
}else{
for (int i = 3; i < sqrt(double(num))+1; i++){
if ((num % i) == 0){
return false;
}
return true;
}
}
}
you need tn convert the integer to string (char*, exactly) using :
answer += itoa(i);
or using standard function :
char str[10];
sprintf(str,"%d",i);
answer += str;
and if you want to avoid using sqrt function, you can replace :
for(int i = 2 ; i < num ; i++)
{
max = sqrt(i);
with :
for(int i = 2 ; i*i < num ; i++)
{
The problem is that the + operator of std::string accepts strings as parameter, pointers to an array of chars, or single chars.
When a single char is used in the + operator, then a single char is added to the end of the string.
Your C++ compiler converts the integer to char before passing it to the operator + (both char and int are signed integer values, with different bit number), and therefore your string should contain a strange char instead of the numbers.
You should explicitly convert the integer to string before adding it to the string, as suggested in other answers, or just output everything to std::cout (its operator << accepts also int as parameter and convert them correctly to string).
As a side note, you should receive a warning from the C++ compiler that your integer i has been converted to char when you add it to the string (the integer has been converted to a lower resolution or something like that). This is why is always good to set the warning level to high and try to produce applications that don't generate any warning during the compilation.
You could perform a faster lookup by storing your known prime numbers in a set. These two sample functions should do the trick:
#include <iostream>
#include <set>
#include <sstream>
#include <string>
typedef std::set< unsigned int > PrimeNumbers;
bool isComposite(unsigned int n, const PrimeNumbers& knownPrimeNumbers)
{
PrimeNumbers::const_iterator itEnd = knownPrimeNumbers.end();
for (PrimeNumbers::const_iterator it = knownPrimeNumbers.begin();
it != itEnd; ++it)
{
if (n % *it == 0)
return true;
}
return false;
}
void findPrimeNumbers(unsigned int n, PrimeNumbers& primeNumbers)
{
for (unsigned int i = 2; i <= n; ++i)
{
if (!isComposite(i, primeNumbers))
primeNumbers.insert(i);
}
}
You could then invoke findPrimeNumbers like so:
unsigned int n;
std::cout << "n? ";
std::cin >> n;
PrimeNumbers primeNumbers;
findPrimeNumbers(n, primeNumbers);
And if you really need to dump the result in a string:
std::stringstream stringStream;
int i = 0;
PrimeNumbers::const_iterator itEnd = primeNumbers.end();
for (PrimeNumbers::const_iterator it = primeNumbers.begin();
it != itEnd; ++it, ++i)
{
stringStream << *it;
if (i < primeNumbers.size() - 1)
stringStream << ", ";
}
std::cout << stringStream.str() << std::endl;
Since you're willing to learn, you can perform both join and split algorithm on string/sequence by using Boost String Algorithms Library.
This solution is not perfect, but it's basic C++ usage (simple containers, no structure, only one typedef, ...).
Feel free to compare your results with The First 1000 Primes.
Good luck