Character array adds random characters at outputting - c++

cin.get(a, 256);
for(int i = 0; i < strlen(a); i++){
if(strchr("aeiou", a[i])){
s = 0;
strcpy(substr, empty);
isubstr = 0;
}
else{
s++;
substr[isubstr++] = a[i];
if(s > maax || s == maax){
maax = s;
memset(show, 0, 256);
strcpy(show, substr);
}
}
}
cout << show;
This is the code. It intends to find the longest substring with only consonants and if there are 2+ with the same lenght it outputs the farthest one (closer to the right)
Consider the following sequence:
jfoapwjfppawefjdsjkflwea
Splitted by vowels it wold look something like this:
jf |oa| pwjfpp |a| w |e| fjdsjkflw |ea|
Notice how "fjdsjkflw" is the largest substring without a vowel. This code outputs just that including some random numbers at the end:
fjdsjkflwê²a
Why does this happen? Why does it put NULL 3 characters beyond of what it's intended to?

For starters you should write a function that finds such a longest sequence of consonants.
You provided an incomplete code so it is difficult to analyze it. For example it is not seen where and how variables substr and empty used in this call
strcpy(substr, empty);
are defined and what are their meanings.
Also there are statements like this
memset(show, 0, 256);
that do not make a sense because for example after this statement there is the statement
strcpy(show, substr);
So the previous statement is just redundant.
Or for example it seems that one of these variables s and isubstr is also redundant.
I can suggest the following solution implemented as a function.
#include <iostream>
#include <utility>
#include <cstring>
std::pair<const char *, size_t> max_consonant_seq( const char *s )
{
const char *vowels = "aeiouAEIOU";
std::pair<const char *, size_t> p( nullptr, 0 );
do
{
size_t n = std::strcspn( s, vowels );
if ( n != 0 && !( n < p.second ) )
{
p.first = s;
p.second = n;
}
s += n;
s += std::strspn( s, vowels );
} while ( *s );
return p;
}
int main()
{
const char *s = "jfoapwjfppawefjdsjkflwea";
auto p = max_consonant_seq( s );
if ( p.second ) std::cout.write( p.first, p.second ) << '\n';
return 0;
}
The program output is
fjdsjkflw
The function returns a pair of objects. The first one specifies the starting pointer of the maximum sequence of consonants in the passed string and the second object specifies the length of the sequence.
All what you need to understand how the function works is to read the description of the two C string functions strspn and strcspn.

Related

find the maximum number of words in a sentence from a paragraph with C++

I am trying to find out the maximum number of words in a sentence (Separated by a dot) from a paragraph. and I am completely stuck into how to sort and output to stdout.
Eg:
Given a string S: {"Program to split strings. By using custom split function. In C++"};
The expected output should be : 5
#define max 8 // define the max string
string strings[max]; // define max string
string words[max];
int count = 0;
void split (string str, char seperator) // custom split() function
{
int currIndex = 0, i = 0;
int startIndex = 0, endIndex = 0;
while (i <= str.size())
{
if (str[i] == seperator || i == str.size())
{
endIndex = i;
string subStr = "";
subStr.append(str, startIndex, endIndex - startIndex);
strings[currIndex] = subStr;
currIndex += 1;
startIndex = endIndex + 1;
}
i++;
}
}
void countWords(string str) // Count The words
{
int count = 0, i;
for (i = 0; str[i] != '\0';i++)
{
if (str[i] == ' ')
count++;
}
cout << "\n- Number of words in the string are: " << count +1 <<" -";
}
//Sort the array in descending order by the number of words
void sortByWordNumber(int num[30])
{
/* CODE str::sort? std::*/
}
int main()
{
string str = "Program to split strings. By using custom split function. In C++";
char seperator = '.'; // dot
int numberOfWords;
split(str, seperator);
cout <<" The split string is: ";
for (int i = 0; i < max; i++)
{
cout << "\n initial array index: " << i << " " << strings[i];
countWords(strings[i]);
}
return 0;
}
Count + 1 in countWords() is giving the numbers correctly only on the first result then it adds the " " whitespace to the word count.
Please take into consideration answering with the easiest solution to understand first. (std::sort, making a new function, lambda)
Your code does not make a sense. For example the meaning of this declaration
string strings[max];
is unclear.
And to find the maximum number of words in sentences of a paragraph there is no need to sort the sentences themselves by the number of words.
If I have understood correctly what you need is something like the following.
#include <iostream>
#include <sstream>
#include <iterator>
int main()
{
std::string s;
std::cout << "Enter a paragraph of sentences: ";
std::getline( std::cin, s );
size_t max_words = 0;
std::istringstream is( s );
std::string sentence;
while ( std::getline( is, sentence, '.' ) )
{
std::istringstream iss( sentence );
auto n = std::distance( std::istream_iterator<std::string>( iss ),
std::istream_iterator<std::string>() );
if ( max_words < n ) max_words = n;
}
std::cout << "The maximum number of words in sentences is "
<< max_words << '\n';
return 0;
}
If to enter the paragraph
Here is a paragraph. It contains several sentences. For example, how to use string streams.
then the output will be
The maximum number of words in sentences is 7
If you are not yet familiar with string streams then you could use member functions find, find_first_of, find_first_not_of with objects of the type std::string to split a string into sentences and to count words in a sentence.
Your use case sounds like a reduction. Essentially you can have a state machine (parser) that goes through the string and updates some state (e.g. counters) when it encounters the word and sentence delimiters. Special care should be given for corner cases, e.g. when having continuous multiple white-spaces or >1 continous full stops (.). A reduction handling these cases is shown below:
int max_words_in(std::string const& str)
{
// p is the current and max word count.
auto parser = [in_space = false] (std::pair<int, int> p, char c) mutable {
switch (c) {
case '.': // Sentence ends.
if (!in_space && p.second <= p.first) p.second = p.first + 1;
p.first = 0;
in_space = true;
break;
case ' ': // Word ends.
if (!in_space) ++p.first;
in_space = true;
break;
default: // Other character encountered.
in_space = false;
}
return p; // Return the updated accumulation value.
};
return std::accumulate(
str.begin(), str.end(), std::make_pair(0, 0), parser).second;
}
Demo
The tricky part is deciding how to handle degenerate cases, e.g. what should the output be for "This is a , ,tricky .. .. string to count" where different types of delimiters alternate in arbitrary ways. Having a state machine implementation of the parsing logic allows you to easily adjust your solution (e.g. you can pass an "ignore list" to the parser and update the default case to not reset the in_space variable when c belongs to that list).
vector<string> split(string str, char seperator) // custom split() function
{
size_t i = 0;
size_t seperator_pos = 0;
vector<string> sentences;
int word_count = 0;
for (; i < str.size(); i++)
{
if (str[i] == seperator)
{
i++;
sentences.push_back(str.substr(seperator_pos, i - seperator_pos));
seperator_pos = i;
}
}
if (str[str.size() - 1] != seperator)
{
sentences.push_back(str.substr(seperator_pos + 1, str.size() - seperator_pos));
}
return sentences;
}

to lexicographically compare kth word from two strings

I m trying to write a c++ function to lexicographically compare kth word from two strings. here is my function :
bool kth_lexo ()
{
int k = 2 ;
str1 = "123 300 60009" ;
str2 = "1500 10002" ;
// to store the kth word of fist string in ptr1
char *ptr1 = strtok( (char*)str1.c_str() ," ");
for(int i = 1; i<k; i++)
{
ptr1 = strtok(NULL," ");
}
// to store the kth word of second string in ptr2
char *ptr2 = strtok( (char*)str2.c_str() ," ");
for(int i = 1; i<k; i++)
{
ptr2 = strtok(NULL," ");
}
string st1 = ptr1 ;
string st2 = ptr2 ;
return st1 > st2 ;
}
In this function my lexicographical comparison works fine, as this func returns 1 because 300 (2nd word of str1) is lexicographically bigger than 10002 (2nd word of str2)
My Problem :
If i slightly modify my function by replacing last line of previous function by this return ptr1>ptr2 ;
now my new function lokks something like this :
bool kth_lexo ()
{
int k = 2 ;
str1 = "123 300 60009" ;
str2 = "1500 10002" ;
// to store the kth word of fist string in ptr1
char *ptr1 = strtok( (char*)str1.c_str() ," ");
for(int i = 1; i<k; i++)
{
ptr1 = strtok(NULL," ");
}
// to store the kth word of second string in ptr2
char *ptr2 = strtok( (char*)str2.c_str() ," ");
for(int i = 1; i<k; i++)
{
ptr2 = strtok(NULL," ");
}
// modified line compared to previous function
return ptr1 > ptr2 ;
}
for this modified function each time my output consistently comes out to be 0, no matter whether kth word of str1 stored in ptr1 is lexicographically greater or smaller than kth word of str2 stored in ptr2.
also even after modifying the return statement by this line doesn't bring much help :
return (*ptr1)>(*ptr2) ;
So what's the problem with either of these two return statement lines in my modified function for comparing the kth word of both the strings:
return ptr1 > ptr2 ;
OR
return (*ptr1) > (*ptr2) ;
You are using a very C-like program. Using modern C++ makes this much simpler and easier to read, since we can use very expressive syntax:
#include <string_view>
#include <iostream>
#include <cassert>
auto find_kth_char(std::string_view to_search, char c, std::size_t k, std::size_t pos = 0) {
for (; pos < std::string_view::npos && k > 0; --k) {
pos = to_search.find(c, pos + 1);
}
return pos;
}
auto get_kth_word(std::string_view to_search, std::size_t k) {
// We count starting on 1
assert(k > 0);
auto start = find_kth_char(to_search, ' ', k - 1);
if (start == std::string_view::npos) {
return std::string_view{};
}
auto end = find_kth_char(to_search, ' ', 1, start);
return to_search.substr(start, end - start);
}
auto compare_kth(std::string_view lhs, std::string_view rhs, std::size_t k) {
auto l_word = get_kth_word(lhs, k);
auto r_word = get_kth_word(rhs, k);
// returnvalue <=> 0 == lhs <=> rhs
return l_word.compare(r_word);
}
int main() {
auto str1 = "123 300 60009";
auto str2 = "1500 10002";
for (std::size_t k = 1; k < 4; ++k) {
std::cout << k << ":\t" << compare_kth(str1, str2, k) << '\n';
}
}
I am using C++17's string_view since we do not change anything in the strings and taking substrings etc. is very cheap with them. We use the find and compare member functions for doing the real work.
The return value from our function is an int that tells us whether the left hand side is smaller (negative result), equal (0) or greater (positve result) than the right hand side.
If you would stop using C and consequently use C++, then this problem would not occur.
You are here mixing up C++ std::string and char* or const char*. Basically, for strings, std::string is that superior to the old style C-char-arrays or char* that you from now on and in the future should never use something else than std::string
A char pointer is an adress into some area in the memory, where your char data is stored. Dereferencing the pointer with *, will give you the element stored at this address. So only one element. Not a string or whatever. Only exactly one character.
comparing ptr1 > ptr2 , will not compare strings. It will compare some values, where the strings are stored in memory. "ptr1" could be 0x578962574 and "ptr2" could be 0x95324782, or whatever. We do not know the address. This will be defined by the linker.
And if you compare (*ptr1)>(*ptr2), then you compare only 2 singgle characters, and that may give you also the wrong result.
On the other hand, Comparing 2 std::strings, will always work as expected.
So, simple answer: Use std::string for all strings.

Why can't I change the pointer's content when in a loop?

I'm given a string and i need to display all strings that can be formed removing one letter at a time.
For example,for "abbc" i should display "bbc"
"abc"
"abc"
and "abb"
Here is my code:
int main()
{
char s[41]="abbc",*p;
int n=strlen(s);
p=s;
int i=0;
while(i<n)
{
strcpy(p+i,p+i+1);
cout<<p<<" ";
i++;
strcpy(p,s);
}
return 0;
}
It keeps showing bbc bc bc bc as if strcpy(p,s); wasn't wrote. Why can't I give a value to the pointer p in a loop?
To output substrings of a string according to your description there is no need to change the original string.
This call
strcpy(p+i,p+i+1);
has 1) undefined behavior (because the ranges are overlapped) 2) and changes the original string.
This call
strcpy(p,s);
does not make sense because the string is copied into itself due to this assignment
p=s;
The task can be done using ordinary for-loops. For example (a C++ program)
#include <iostream>
int main()
{
const char *s = "abbc";
for ( size_t i = 0; s[i] != '\0'; i++ )
{
for ( size_t j = 0; s[j] != '\0'; j++ )
{
if ( j != i ) std::cout << s[j];
}
std::cout << '\n';
}
return 0;
}
The program output is
bbc
abc
abc
abb
Or (a C program)
#include <stdio.h>
int main(void)
{
const char *s = "abbc";
for ( size_t i = 0; s[i] != '\0'; i++ )
{
for ( size_t j = 0; s[j] != '\0'; j++ )
{
if ( j != i ) putchar( s[j] );
}
putchar( '\n' );
}
return 0;
}
Here is a pure C version. It removes the last character from the string and stores it. After that it replaces each character with the one that came after it, until all have been replaced. At the end the string will contain the substring starting at the second character.
#include <string.h>
#include <stdio.h>
int main()
{
char s[41] = "abbc";
int n;
char c, tmp;
n = strlen(s);
c = 0;
while( n > 0 )
{
n--;
tmp = c;
c = s[n];
s[n] = tmp;
printf( "%s\n", s );
}
return 0;
}
p and s is pointing to the same memory. The memory is modified at each loop, so after the first loop n is no longer valid as the length of the string.
loop 1: p & s = "abbc", i=0, n=4
p+0 points to "abbc", p+1 points to "bbc"
value of s after strcpy(p+0, P+1) is "bbc"
loop 2: p & s = "bbc", i=1, n=4
p+1 points to "bc", p+1+1 points to "c"
value of s after strcpy(p+1, P+2) is "bc"
loop 3: p & s = "bc", i=2, n=4
p+2 points to null or "", p+3 points to something after string
value of s after strcpy(p+2, p+3) is undifined but likely remaining "bc"
loop 4: nothing treally change from above as you now are outside string

Finding possible prefix palindromes

We are given a string S of length N. We have to calculate number of prefixes which can be rearranged into palindromes. E.g: Consider string "abba"- "a", "abb" and "abba" are the prefixes which can be rearranged into palindromes.
My approach:
I tried to use XOR for solving this problem. For example a string containing even number of characters can be made palindrome if the xor of all characters in the string is 0.In case of strings having odd characters, the xor of all characters should be between 97 and 122, i.e a single character.
Here's a part of my code-
string s;
cin>>s;
int a,n;
int ans=1;
n= s.length();
a=s[0];
for (int i=1;i<n;i++)
{
a=a^(s[i]);
if (i%2)
{
if (a==0)
{
ans++;
}
}
else
{
if ((a>=97)&&(a<=122))
{
ans++;
}
}
}
cout<< ans<< "\n";
I tried to run and it runs successfully for some test cases but fails for others. Any idea of what's wrong in this approach?
Better solution, based on the comments from OP:
#include <string>
#include <iostream>
#include <cctype>
int main() {
std::string input;
std::cin >> input;
unsigned char_xor = input[ 0 ];
unsigned pal = 1; // number of palindromes (initialized to 1,
// since a singular letter is always a
// palindrome)
for ( std::string::size_type i = 0; input.size() >= i; ++i ) {
char_xor ^= input[ i + 1 ];
// check whether length of current prefix is:
// - odd: check whether it is a lowercase character
// - even: check whether it is equal to 0
if ( ( i % 2 && std::islower( char_xor ) ) ||
( !( i % 2 ) && !char_xor ) ) {
++pal;
}
}
std::cout << "Amount of possible palindromes: " << pal << std::endl;
return 0;
}
The following assumption is incorrect (see comments below).
As having understood from
a string containing even number of characters can be made palindrome if the xor of all characters in the string is 0.In case of strings having odd characters, the xor of all characters should be between 97 and 122
you're making a mistake in checking whether the computed XOR is equal to 0/between 97 and 122 on each iteration (after XORing each character), whereas you should be checking it after iterating over the whole std::string. The following works with your given example of "abba" and, for instance, "aaaadcasdasdaffaaa" (having produced 12):
#include <string>
#include <iostream>
#include <cctype>
bool can_be_palindrome( const std::string& str ) {
unsigned char_xor = str[ 0 ];
// compute the xor of all characters
for ( std::string::size_type i = 1; str.size() != i; ++i ) {
char_xor ^= str[ i ];
}
// determine whether the input string has an even number of characters;
// if so, return whether char_xor is equal to 0;
// if not, return whether char_xor is a lowercase letter.
return !( str.size() % 2 ) ? !char_xor : std::islower( char_xor );
}
int main() {
std::string input;
std::cin >> input;
unsigned pal = 1; // number of palindromes (initialized to 1, since a
// singular letter is always a palindrome)
for ( std::string::size_type i = 2; input.size() >= i; ++i ) {
// extract a prefix from the range [0; i) and determine whether it
// can become a palindrome
if ( can_be_palindrome( input.substr( 0, i ) ) ) {
++pal;
}
}
std::cout << "Amount of possible palindromes: " << pal << std::endl;
return 0;
}

How to find string in a string

I somehow need to find the longest string in other string, so if string1 will be "Alibaba" and string2 will be "ba" , the longest string will be "baba". I have the lengths of strings, but what next ?
char* fun(char* a, char& b)
{
int length1=0;
int length2=0;
int longer;
int shorter;
char end='\0';
while(a[i] != tmp)
{
i++;
length1++;
}
int i=0;
while(b[i] != tmp)
{
i++;
length++;
}
if(dlug1 > dlug2){
longer = length1;
shorter = length2;
}
else{
longer = length2;
shorter = length1;
}
//logics here
}
int main()
{
char name1[] = "Alibaba";
char name2[] = "ba";
char &oname = *name2;
cout << fun(name1, oname) << endl;
system("PAUSE");
return 0;
}
Wow lots of bad answers to this question. Here's what your code should do:
Find the first instance of "ba" using the standard string searching functions.
In a loop look past this "ba" to see how many of the next N characters are also "ba".
If this sequence is longer than the previously recorded longest sequence, save its length and position.
Find the next instance of "ba" after the last one.
Here's the code (not tested):
string FindLongestRepeatedSubstring(string longString, string shortString)
{
// The number of repetitions in our longest string.
int maxRepetitions = 0;
int n = shortString.length(); // For brevity.
// Where we are currently looking.
int pos = 0;
while ((pos = longString.find(shortString, pos)) != string::npos)
{
// Ok we found the start of a repeated substring. See how many repetitions there are.
int repetitions = 1;
// This is a little bit complicated.
// First go past the "ba" we have already found (pos += n)
// Then see if there is still enough space in the string for there to be another "ba"
// Finally see if it *is* "ba"
for (pos += n; pos+n < longString.length() && longString.substr(pos, n) == shortString; pos += n)
++repetitions;
// See if this sequence is longer than our previous best.
if (repetitions > maxRepetitions)
maxRepetitions = repetitions;
}
// Construct the string to return. You really probably want to return its position, or maybe
// just maxRepetitions.
string ret;
while (maxRepetitions--)
ret += shortString;
return ret;
}
What you want should look like this pseudo-code:
i = j = count = max = 0
while (i < length1 && c = name1[i++]) do
if (j < length2 && name2[j] == c) then
j++
else
max = (count > max) ? count : max
count = 0
j = 0
end
if (j == length2) then
count++
j = 0
end
done
max = (count > max) ? count : max
for (i = 0 to max-1 do
print name2
done
The idea is here but I feel that there could be some cases in which this algorithm won't work (cases with complicated overlap that would require going back in name1). You may want to have a look at the Boyer-Moore algorithm and mix the two to have what you want.
The Algorithms Implementation Wikibook has an implementation of what you want in C++.
http://www.cplusplus.com/reference/string/string/find/
Maybe you made it on purpose, but you should use the std::string class and forget archaic things like char* string representation.
It will make you able to use lots of optimized methods, such as string research, etc.
why dont you use strstr function provided by C.
const char * strstr ( const char * str1, const char * str2 );
char * strstr ( char * str1, const char * str2 );
Locate substring
Returns a pointer to the first occurrence of str2 in str1,
or a null pointer if str2 is not part of str1.
The matching process does not include the terminating null-characters.
use the length's now and create a loop and play with the original string anf find the longest string inside.