Related
This question already has answers here:
How do unsigned integers work
(3 answers)
Closed 2 years ago.
I am writing a program to return first occurrence of the character and the frequency of that character in the string.
For loop in the function is executing infinite times and if condition and block is not executing even once.
What is the problem?
string::size_type find_ch(string &str,char ch,int& i_r)
{
string::size_type first=0;
for(auto i=str.size()-1;i>=0;i--)
{
cout<<"\nInside a for loop."<<endl;
if(str[i]==ch)
{
cout<<"Inside if."<<endl;
first=i+1;
i_r++;
}
}
return first;
}
This loop:
for(auto i = str.size() - 1; i>=0; i--)
will only exit when i is less than 0. But this is not a valid value for an unsigned int. The value will wrap to the maximum unsigned int, and you get an infinite loop.
Note that .size() on a std::string returns a size_t, which is basically an unsigned int type.
One way to fix this would be to cast the return type of .size() to an int, like this:
for(auto i = static_cast<int>(str.size()) - 1; i>=0; i--)
Note that it's important to do the cast before subtracting 1, otherwise you'll get the wrong answer when str is empty.
In c++20, you can avoid this issue entirely by calling the std::ssize() free function, which returns a signed version of the size.
The function definition in general is wrong.
For example if the given character is nit found then why does the function return 0 that is a valid position?
Returning the value first=i+1; will only confuse users of the function. The function shall return std::string::npos if the given character is not found.
Also it is entirely unclear why the loop starts from the end of the string while you need to return the first position of the character.
As for the infinite loop then in the loop there is used variable i that has the unsigned integer type std::string::size_type a value of which never can be negative.
for(auto i=str.size()-1;i>=0;i--)
^^^^^^^^^^^^^^^^^^^
That is the condition i >= 0 is always true by the definition.
The function should be defined the following way
std::pair<std::string::size_type, std::string::size_type> find_ch( const std::string &str, char ch )
{
auto n = str.find( ch );
std::pair<std::string::size_type, std::string::size_type> p( n, 0 );
if ( n != std::string::npos )
{
++p.second;
while ( ( n = str.find( ch, n + 1 ) ) != std::string::npos ) ++p.second;
}
return p;
}
Here is a demonstrative program.
#include <iostream>
#include <string>
#include <utility>
std::pair<std::string::size_type, std::string::size_type> find_ch( const std::string &str, char ch )
{
auto n = str.find( ch );
std::pair<std::string::size_type, std::string::size_type> p( n, 0 );
if ( n != std::string::npos )
{
++p.second;
while ( ( n = str.find( ch, n + 1 ) ) != std::string::npos ) ++p.second;
}
return p;
}
int main()
{
std::string s( "C++ is not the same as C" );
auto p = find_ch( s, 'C' );
if ( p.first != std::string::npos )
{
std::cout << p.first << ": " << p.second << '\n';
}
return 0;
}
The program output is
0: 2
If you are not allowed to use methods of the class std::string then just substitute calls of the method find in the function above to while loops as it is shown below.
#include <iostream>
#include <string>
#include <utility>
std::pair<std::string::size_type, std::string::size_type> find_ch( const std::string &str, char ch )
{
std::pair<std::string::size_type, std::string::size_type> p( std::string::npos, 0 );
std::string::size_type n = 0;
while ( n < str.size() && str[n] != ch ) ++n;
if ( n != str.size() )
{
p.first = n;
++p.second;
while ( ++n != str.size() )
{
if( str[n] == ch ) ++p.second;
}
}
return p;
}
int main()
{
std::string s( "C++ is not the same as C" );
auto p = find_ch( s, 'C' );
if ( p.first != std::string::npos )
{
std::cout << p.first << ": " << p.second << '\n';
}
return 0;
}
Here is an answer similar to #Vlad From Moscow, but uses string functions, and the algorithm std::count.
#include <algorithm>
#include <string>
#include <utility>
#include <iostream>
std::pair<int,int> find_ch(const std::string &str, char ch)
{
std::pair<int, int> ret;
auto pos = str.find_first_of(ch);
if ( pos == std::string::npos )
return {-1,0}; // not found
return { pos, std::count(str.begin() + pos, str.end(), ch) };
}
int main()
{
auto pr = find_ch("abccabc", 'b');
std::cout << "character b is at position " << pr.first << ". Character count is " << pr.second << "\n";
pr = find_ch("abccabc", 'c');
std::cout << "character c is at position " << pr.first << ". Character count is " << pr.second;
}
Output:
character b is at position 1. Character count is 2
character c is at position 2. Character count is 3
Each line of the function basically describes what is being done:
find_first_of the character in the string. If found then return that position and the std::count of that character starting at the first occurrence.
Note the brevity and self-documented way the function is written. A C++ programmer could look at that code and immediately know what it does, due to the names of the functions that are being called.
Writing loops going backwards (as you originally did) with variables incremented here and there, the programmer has to sit down and go through the code to figure out what it is doing, and what the purpose of the function is.
I want to sort each string of array of strings , here is my code that i tried.
#include <iostream>
#include <algorithm>
void _sort_word(char *str)
{
int len = strlen(str);
std::sort(str,str+len); // program get stuck here.
}
int main()
{
char *str[] = {"hello", "world"};
for(int i=0;i<2;i++){
_sort_word(str[i]);
cout << str[i] << "\n";
}
}
I want to know is sort(str,str+len); a valid statement here, if not what should be done instead ?
First of all string literals in C++ have types of constant character arrays. So the correct array declaration will look like
const char *str[] = {"hello", "world"};
^^^^^
Thus the string literals pointed to by the elements of the array are immutable.
You should declare at least a two dimensional array.
Here is a demonstrative program
#include <iostream>
#include <algorithm>
#include <cstring>
void sort_word( char *s )
{
size_t l = std::strlen( s );
std::sort( s, s + l );
}
int main()
{
char str[][6] = { "hello", "world" };
for ( auto &s : str ) sort_word( s );
for ( auto &s : str ) std::cout << s << std::endl;
return 0;
}
Its output is
ehllo
dlorw
If your compiler does not support the range based for statement then you can write instead
for ( size_t i = 0; i < sizeof( str ) / sizeof( *str ); i++ ) sort_word( str[i] );
I have an array of strings,
sparnus , sapnus , lol , noon ...
As you can see they both start and end with the same character.
What can i do to compare, let's say "sparnus" with "sapnus" and find out which string has more different characters?
sparnus has s p a r n u s (6 different characters)
sapnus has s a p n u s (5 different characters)
(note: s repeats itself, so it's not a different character)
is there a function? algorithm? tips and advice are welcome.
Standard container std::set itself is in fact an algorithm.:)
For example
#include <iostream>
#include <string>
#include <set>
int main()
{
std::string s1( "sparnus" ), s2( "sapnus" );
std::cout << std::set<char>( s1.begin(), s1.end() ).size() << std::endl;
std::cout << std::set<char>( s2.begin(), s2.end() ).size() << std::endl;
return 0;
}
The output is
6
5
So you can use standard algorithm std::max_element with a predicat that compares sizes of two sets built from strings.
Here is an example
#include <iostream>
#include <string>
#include <set>
#include <algorithm>
#include <cstring>
#include <iterator>
int main()
{
const size_t N = 10;
char s[][N] = { "lol" , "noon", "sparnus", "sapnus" };
auto it = std::max_element( std::begin( s ), std::end( s ),
[]( const char *a, const char *b )
{
return std::set<char>( a, a + std::strlen( a ) ).size() <
std::set<char>( b, b + std::strlen( b ) ).size();
} );
std::cout << *it<< std::endl;
return 0;
}
The output is
sparnus
Or you can use the approach that was shown in one post here that was deleted by unknown reason. For example You can sort all words by using standard algorithm std::sort then apply standard algorithm std::unique and standard C function std::strlen will give you the number of unique characters in each string.
template <typename InputIterator>
std::size_t countDiffChars( InputIterator first,
InputIterator last )
{
bool lookup[1 << CHAR_BIT] {};
std::size_t count = 0;
while (first != last)
{
auto&& val = lookup[(unsigned char)*first++];
count += !val;
val = true;
}
return count;
}
Usage:
char const str[] = "Hello";
auto c = countDiffChars(std::begin(s), std::end(s));
Demo.
use a boolean array of 256 entries and loop on the string and set each flag of the array to true indexing by the letter of the string. At the end you may count the number of trues in the array and found how many different characters are there.
If instead of a boolean array you use an int array you may also count how many times a letter is found if that serves somehow! ( that may be done if you don't want to use sets as a previous answer points ).
#include <iostream>
#include <string>
int cnt(std::string s){
bool b[0x100]={false};int r=0;
for(int i:s) b[i]=true;for(int i:b) r+=i;
return r;
}
int main(int argc, char **argv)
{ std::cout<<cnt("sparnus")<<" "<<cnt("sapnus")<<std::endl;
return 0;
}
Write a c++ program that finds the number of vowels used in an string.
For the above problem I written a program as follows:
int main()
{
char x[10];
int n,i,s=0;
cout<<"Enter any string\n";
cin>>x;
n=strlen(x);
for(i=0;i<n;++i)
{
if(x[i]=='a'||x[i]=='e'||x[i]=='i'||x[i]=='o'||x[i]=='u')
{
s=s+1;
}
}
cout<<s;
return 0;
}
Output of the program is as:
Enter any string elephant 3
Here in 'elephant' at three places vowels are used but the total number of vowels used is 2(e and a) not 3
I am asking to improve the program so that it counts the total number of vowels and print the total number.(e.g. in case of elephant it must give 2)
Make another array(), with 5 index, like
vowels[5] = array(0,0,0,0,0);
Then make if else if, with eache vowel, and add
if(x[i] == 'a') vowels[0] =1;
elseIf(x[i] == 'e') vowels[1] =1;
etc, and then check if vowels array is set to 1 or 0, and count only, these which are 5.
int count=0;
foreach vowels as item {
if(item == 1) count++
}
return count;
The easiest solution would be to just insert each vowel you see
into an std::set, and use its size function when you're
done.
And for heaven's sake, use a table lookup to determine whether
something is a vowel (and put the logic in a separate function,
so you can correct it when you need to handle the "sometimes y"
part).
Alternatively, without using the standard algorithms:
int charCount[UCHAR_MAX + 1];
// and for each character:
++ charCount[static_cast<unsigned char>( ch )];
(Of course, if you're using C++, you'll read the characters
into an std::string, and iterate over that, rather than having
an almost guaranteed buffer overflow.)
Then, just look at each of the vowels in the table, and count
those which have non-zero counts:
int results = 0;
std::string vowels( "aeiou" ); // Handling the sometimes "y" is left as an exercise for the reader.
for ( auto current = vowels.begin(); current != vowels.end(); ++ current ) {
if ( charCount[static_cast<unsigned char>( *current )] != 0 ) {
++ results;
}
}
Of course, neither of these, implemented naïvely, will handle
upper and lower case correctly (where 'E' and 'e' are the same
vowel); using tolower( static_cast<unsigned char>( ch ) ) will
solve that.
EDIT:
Since others are proposing solutions (which are only partially
correct):
bool
isVowel( unsigned char ch )
{
static std::set<int> const vowels{ 'a', 'e', 'i', 'o', 'u' };
return vowels.find( tolower( ch ) ) != vowels.end();
}
int
main()
{
std::string text;
std::cout << "Enter any word:";
std::cin >> text;
std::set<unsigned char> vowelsPresent;
for ( unsigned char ch: text ) {
if ( isVowel( ch ) ) {
vowelsPresent.insert( tolower( ch ) );
}
}
std::cout << vowelsPresent.size() << std::endl;
}
Separating the definition of a vowel into a separate function is
practically essential in well written code, and at the very
least, you need to mask differences in case. (This code also
punts on the question of "y", which would make isVowel several
orders of magnitude more difficult. It also ignores characters
outside of the basic character set, so "naïve" will report two
different vowels.)
Sets already eliminate duplicates, so instead of counting vowels as you encounter them, add them into a set. Then, at the end, count the number of [non-duplicate] vowels by querying the set for its size.
#include <set>
#include <string>
#include <iostream>
int main()
{
std::string x;
int n = 0;
std::set<char> vowels;
std::cout << "Enter any string\n";
std::cin >> x;
n = x.size();
for (int i = 0; i < n; ++i)
if (x[i] == 'a' || x[i] == 'e' || x[i] == 'i' || x[i] == 'o' || x[i] == 'u')
vowels.insert(x[i]);
std::cout << vowels.size() <<'\n';
}
Live demo
g++-4.8 -std=c++11 -O2 -Wall -pedantic -pthread main.cpp && echo "elephant" | ./a.out
Enter any string
2
Note that I also exchanged your use of fixed-sized arrays with an std::string, so that you're not at risk of dangerous circumstances when someone happens to input more than 9 characters.
I find a really easy way to solve this problem is by using map <char, int>. This will allow you to make pairs, indexed by a char, ie. the vowels, and connect an integer counter to them.
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main()
{
map <char, int> vowels;
int n,i,s=0;
string x;
cout<<"Enter any string\n";
cin>>x;
for(i=0;i< x.length();++i)
{
if(x[i]=='a'||x[i]=='e'||x[i]=='i'||x[i]=='o'||x[i]=='u')
{
vowels[x[i]]++;
}
}
for (map<char,int>::const_iterator print = vowels.begin(); print != vowels.end(); ++print){
cout << print -> first << " " << print -> second << endl;
}
return 0;
}
For the string elephant we would get the following output:
a 1
e 2
By saying vowels[x[i]]++; we are adding the found vowel into our map, if it already has not been added, and incrementing its paired int by one. So when we find the first e it will add e to our map and increment its counter by one. Then it will continue until it finds the next e and will see that it already has that indexed, so it will simply increment the counter to 2. This way we will avoid the problem with duplicates. Of course, if you wanted to get a single digit we could just print out the size of our map:
cout << vowels.size() << endl;
Okay. My turn. To handle both upper and lower cases we convert to just lower:
std::string x("Elephant");
std::transform(x.begin(), x.end(), x.begin(), std::function<int(char)>(std::tolower));
Now remove duplicates:
std::sort(x.begin(), x.end());
std::unique(x.begin(), x.end());
Now to count the vowels. I was hoping for something specific in locale but alas... Never mind we can create our own. Bit more complex, but not overly:
struct vowel : public std::ctype<char>
{
static const mask* make_table()
{
static std::vector<mask> v(classic_table(), classic_table() + table_size);
v['a'] |= upper;
v['e'] |= upper;
// etc.
return &v[0];
}
vowel(std::size_t refs = 0) : ctype(make_table(), false, refs){}
};
While I am sure you can create your own but can't quite figure out how going by the documentation on cppreference so I say lower case vowels are uppercase. With the earlier call to std::tolower this should be safe.
With this we can use it easily like:
int i = std::count_if(x.begin(), x.end(), [](const char c)
{
return std::isupper(c, std::locale(std::locale(""), new vowel));
});
std::cout << "Number of vowels:" << i << std::endl;
However I am not particularly happy with the two std::locale next each other.
Easiest solution I can think of would be an array of bools representing each vowel and whether or not they've been counted.
bool vowelCounted[5] = { false };
Now, as you count the vowels:
if (x[i]=='a' && !vowelCounted[0]) {
vowelCounted[0] = true;
s += 1;
} else if (x[i]=='e' && !vowelCounted[1]) {
vowelCounted[1] = true;
s += 1;
}
And just repeat this structure for all 5 vowels.
The readability can be improved by using an enum rather than 0, 1, 2, 3, 4 for your indices... but you're using variables named x[] and s, so it's probably fine...
If you use one of the standard containers (vector, list) add your vowels in there, do the same check as you're doing now, if it exists then remove it. When you're finished get the number of remaining elements, your answer will be the original count for the vowels minus the the remaining elements.
try this
for( string text; getline( cin, text ) && text != "q"; )
{
set< char > vowels;
copy_if( begin(text), end(text), inserter( vowels, begin(vowels) ),
[]( char c ) { return std::char_traits< char >::find( "aeiou", 5, c ) != nullptr; } );
cout << "the string [" << text << "] contains " << vowels.size() << " vowels" << endl;
}
You need the includes string, iostream, set, algorithm and iterator.
What do You want to do with the upper ones "AEIOU" ?
You can create this:
std::vector< char> vowels;
And put into it all vowels that you meet while iterating through the string:
if(x[i]=='a'||x[i]=='e'||x[i]=='i'||x[i]=='o'||x[i]=='u')
vowels.push_back( x[i]);
Then you can sort this and eliminate duplicates:
std::sort( vowels.begin(), vowels.end());
std::vector< char> vowels_unique( vowels.size());
std::vector< char>::iterator it;
it = std::unique_copy( vowels.begin(), vowels.end(), vowels_unique.begin());
vowels_unique.resize( std::distance( vowels_unique.begin(), it));
Even better, use a set property - it holds unique data, like this:
std::set< char> unique_vowels;
if(x[i]=='a'||x[i]=='e'||x[i]=='i'||x[i]=='o'||x[i]=='u')
unique_vowels.insert( x[i]);
//...
int unique = unique_vowels.size();
C++ Code Snippet :
#include <bits/stdc++.h>
using namespace std;
int main()
{
char s[100];
int cnt;
cnt=0;
cin>>s;
for(int i=0;s[i];i++)
{
char c =s[i];
if(s[i]=='A' || s[i] =='E' || s[i]=='I' ||s[i]=='O'|| s[i]=='U') cnt++;
else if(s[i]=='a' || s[i] =='e' || s[i]=='i'||s[i]=='o' || s[i]=='u') cnt++;
}
cout<<cnt<<endl;
return 0;
}
Version utilizing std::find() and std::transform():
#include <string>
#include <iostream>
#include <algorithm>
using std::string;
using std::cout;
using std::cin;
using std::getline;
using std::transform;
int main()
{
cout << " Type sentence: ";
string sentence;
getline(cin, sentence);
transform(sentence.begin(), sentence.end(), sentence.begin(), toupper);
string vowels = "AEIOU";
size_t vowCount = 0;
for (int i = 0; i < vowels.length(); ++i)
{
if (sentence.find(vowels[i], 0) != string::npos)
{
++vowCount;
}
}
cout << "There is " << vowCount << " vowels in the sentence.\n";
return 0;
}
PROS
std::find() searches just for first occurrence of given vowel so there is no iteration over rest of the given string
using optimized algorithms from std
CONS
std::transform() transforms each lower-case letter regardless of its "vowelness"
#include<iostream> //std::cout
#include<string> //std::string
#include<cctype> //tolower()
#include<algorithm> //std::for_each
using namespace std;
int main()
{
string s;
getline(cin, s);
int count = 0;
for_each(s.begin(), s.end(), [&count](char & c) //use of lambda func
{
c = tolower(c); //you can count upper and lower vowels
switch (c)
{
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
count++;
break;
}
});
cout << count << endl;
return 0;
}
#include<iostream>
using namespace std;
int main()
{
char vowels[5] = {'a','e','i','o','u'};
char x[8] = {'e','l','e','p','h','a','n','t'};
int counts[5] = {0,0,0,0,0};
int i,j;
for(i=0;i<8;i=i+1)
{
for(j=0;j<5;j=j+1)
{
if(x[i]==vowels[j])
{
counts[j] = counts[j] + 1;
}
}
}
for(i=0;i<5;i=i+1)
{
cout<<counts[i]<<endl;
}
return 0;
}
Since I was using the example of 'elephant' so I just initialized that.
If still any modification can be made then please edit it and make it more user friendly.
I'm doing UVa Problem 10082 and I'm trying to read in some sample input to test my solution. However, when I read in the text '''CCC it outputs ;;XXX. Note that there are only 2 semi-colons, when there should be 3 since there are 3 single quotes in the input. Why is getline() ignoring the first single quote?
Here's my code:
#include <iostream>
#include <string>
using namespace std;
char mapToWertyu(char c)
{
char newC = c;
char wertyu[] = {'1','2','3','4','5','6','7','8','9','0','-','=',
'Q','W','E','R','T','Y','U','I','O','P','[',']','\\',
'A','S','D','F','G','H','J','K','L',';','\'',
'Z','X','C','V','B','N','M',',','.','/'};
char qwerty[] = {'~','1','2','3','4','5','6','7','8','9','0','-','=',
'Q','W','E','R','T','Y','U','I','O','P','[',']','\\',
'A','S','D','F','G','H','J','K','L',';','\'',
'Z','X','C','V','B','N','M',',','.','/'};
if(c=='A' || c=='Q' || c=='Z')
return c;
for(int i = 0; i < 47; ++i)
{
if(wertyu[i]==c)
{
newC = qwerty[i];
break;
}
}
return newC;
}
int main()
{
string input;
while(cin.peek()!=-1)
{
getline(cin,input);
for(int i = 0; i < input.length(); ++i)
{
if(input[i]!='\\')
cout << mapToWertyu(input[i]);
}
cin.ignore(1,'\n');
cout << endl;
}
return 0;
}
Because you tell it to. What do you thing std::cin.ignore( 1,
'\n' ) should do, if not ignore a character. std::getline
extracts the '\n' character, even if it doesn't put it into
the string.
For the rest, you're not doing the input right. For starters, std::cin.peek() will return an integer in the
range [0...UCHAR_MAX] or EOF. EOF is often defined to be
-1, but this is certainly not guaranteed. But more generally:
why not use the usual idiom:
while ( std::getline( std::cin, input ) ) {
// ...
}
You also construct the arrays in mapToWertyu each time you
call it. That is definitly not what you want to do. You could
use just one static array, indexed directly by the character,
bug this does make the program dependent on the encoding. To
use two arrays, however:
static char const wertyu[] = { ... };
static char const qwerty[] = { ... };
char const* pos = std::find( std::begin( wertyu ), std::end( wertyu ), c );
return pos == std::end( wertyu )
? c
: qwerty[ pos - std::begin( wertyu ) ];
Solves the problem in a much simpler manner. (And there's no
need to special case 'A', 'Q' and 'Z'. If you don't want
to transcode them, just don't put them in the table.)
Or...
struct Map
{
char from;
char to;
};
static Map const map[] =
{
{ '1', '~' },
{ '2', '1' },
// ...
};
Map const* pos = std::find_if( std::begin( map ), std::end( map ),
[]( char ch ) { return c == ch; } );
return pos == std::end( map )
? c
: pos->to;
This has the advantage of making the exact mapping visible.
Or if you're 100% sure you'll never have to worry about threads:
struct Map
{
char from;
char to;
};
static Map map[] =
{
{ '1', '~' },
{ '2', '1' },
// ...
{ 0, 0 }
};
Map* sentinal = std::end( map ) - 1;
sentinal->to = sentinal->from = c;
Map const* pos = std::find_if( std::begin( map ), std::end( map ),
[]( Map const& entry ) { return c == entry.from; } );
return pos->to;
By inserting the sentinal, you can be sure that the entry will
be found.
Or you could sort the map, and use std::lower_bound.
Also, why do you call the function mapToWertyu, when it maps
to querty?