Generating substrings in c++ - c++

I'm trying to generate all the substrings of the word fun.
But it prints "un" two times, I don't know why.
int c, i;
string s = "fun";
for (c = 0; c < s.length(); c++)
{
for (i = c+1; i <= s.length(); i++)
{
string d = s.substr(c, i);
cout << d << endl;
}
}

The second parameter to substr is length, not the ending index of the sub-string.
You can use the following logic to get all sub-strings:
Start from index 0, select the substring of length 1, then of length 2, then 3 and so on
Then move on to index 1 and perform the same to it and so on. (When at index 1, the remaining length of the string would be 2, in case of fun, so we'd have to run the loop till length 2)
string s = "fun";
for (int c = 0; c < s.length(); c++)
{
for (int i = 1; i <= s.length() - c; i++)
{
string d = s.substr(c, i);
cout << d << endl;
}
}

But it prints "un" two times, I don't know why.
you can find why if you print c and i
...
for (i = c+1; i <= s.length(); i++)
{
cout << "c,i: " << c << i << endl; // add this line to debug !
string d = s.substr(c, i);
...
the output:
c,i: 01
f
c,i: 02
fu
c,i: 03
fun
c,i: 12
un
c,i: 13
un
c,i: 23
n
Note that, substr will just add as many char as possible after c, if i is longer than the remaining characters in your string, as per http://www.cplusplus.com/reference/string/string/substr/
Number of characters to include in the substring (if the string is shorter, as many characters as possible are used).

Related

Occurrences of same alternative characters in a CString

I'm new to C++ programming and this is the task that i've to do, but i can't get the desired output even after trying and trying. Can anyone please look into code and let me know what should do, i know my code is incomplete but i don't know how to proceed from here.
Task: Write a program, using functions only, with the following features.
Program reads paragraph(s) from console and stores in a string.
Program then counts the occurrences of double letter appearing in any word of the paragraph(s) and outputs the characters along with its number of occurrences.
If a double letter is appearing more than one time the program should show this only one time along with its total frequency in paragraph.
Output letters must be in sequence.
Sample input (file):
Double bubble deep in the sea of tooth with teeth and meet with riddle.
Sample output:
bb 1
dd 1
ee 3
oo 1
This is my code:
#include <iostream>
#include <conio.h>
#include <cstring>
#include <ctime>
using namespace std;
int counter = 0;
char alphabets[26] = { 0 };
void alternatives();
int main() {
alternatives();
_getch();
return 0;
}
void alternatives() {
char str[] = "Double bubble deep in the sea of tooth with teeth and meet with riddle.";
int count = 0;
for (int j = 0; j < strlen(str); j++)
str[j] = tolower(str[j]);
for (int i = 0; i < strlen(str); i++) {
if (str[i] == str[i + 1]) {
counter++;
cout << str[i] << str[i + 1] << "\t" << counter << endl;
}
counter = 0;
}
}
Output:
bb 1
ee 1
oo 1
ee 1
ee 1
dd 1
You have 26 letters (I assume) so you need 26 counts. A simple array would do
int counters[26] = { 0 }; // initialise all counts to zero
Now when you find a repeated letter you need to increment the appropriate count, something like
for (int i = 0; i < strlen(str); i++)
{
char letter = str[i];
if (letter >= 'a' && letter <= 'z' && // is it a letter and
letter == str[i + 1]) // is it repeated?
{
counters[letter - 'a']++; // increment count
}
}
Note the use of letter - 'a' to get the offset into the array of counts
Finally you need to output the results
for (char letter = 'a'; letter <= 'z'; ++letter)
{
int count = counters[letter - 'a'];
if (count > 0)
cout << letter << letter << ' ' << count << ' ';
}
cout << '\n';
Not perfect, but hopefully something to get you started. This is untested code.
You can use an int array of length 26 to keep track of repeated instances of letters. You can then iterate over the C string and check for repeats. If you find one, make sure to jump your iterator forward.
#include <iostream>
#include <cstring>
int main() {
int repeats[26] = {0};
char str[] = "Double bubble deep in the sea of tooth with teeth and meet with riddle.";
for (char *ch = str; *ch; ch++)
*ch = tolower(*ch);
for (char *ch = str; *ch; ch++) {
if (std::isalpha(*ch) && *ch == ch[1]) {
repeats[*ch - 'a']++;
ch++;
}
}
for (size_t i = 0; i < 26; i++) {
std::cout << static_cast<char>('a' + i) << ": " << repeats[i] << std::endl;
}
return 0;
}
Result:
a: 0
b: 1
c: 0
d: 1
e: 3
f: 0
g: 0
h: 0
i: 0
j: 0
k: 0
l: 0
m: 0
n: 0
o: 1
p: 0
q: 0
r: 0
s: 0
t: 0
u: 0
v: 0
w: 0
x: 0
y: 0
z: 0

Can't make a way to print strings by words/or as 12 characters

To start with, we have array of strings, I have to print this array that way, that one word before space or first 12 characters = one string.
For example, lets say we have string "hello world qwerty------asd" , this must be printed as :
hello
world
qwerty------ (12 characters without space)
asd
So, it will be easy to do without this 12 characters condition in the task ( just strtok function I guess ), but in this case, I dont know what to do, I have idea, but it works with only 50% of inputs, here it is, it is quite a big and very stupid, I know its about strings functions, but cant make algoritm , thank you:
int counter = 0;// words counter
int k1 = 0;// since I also need to print addresses of letters of third word, I have to know where 3rd word is
int jbegin=0,// beginning and end of 3rd word
jend=0;
for (int k = 0; k < i; k++) {
int lastspace = 0;//last index of new string( space or 12 characters)
for (int j = 0; j < strlen(*(arr + k)); j++) {
if (*(*(arr + k) + j) == ' ' ) { //if space
printf("\n");
lastspace = j;
counter++;
if ( counter == 3 ) { // its only for addreses, doesnt change anything
k1 = k;
jbegin = j + 1;
jend = jbegin;
}
}
if (j % 12 == 0 && (j-lastspace>11 || lastspace==0) ) { // if 12 characters without space - make a new string
printf(" \n");
counter++;
lastspace = j;
}
if (counter==3 ) {
jend++;
}
printf("%c", *(*(arr+k) + j)); // printing by char
}
printf("\n ");
}
if ( jend!=0 && jbegin!=0 ) {
printf("\n Addreses of third word are :\n");
for (int j = jbegin; j < jend; j++) {
printf("%p \n", arr + k1 + j);
printf("%c \n", *(*(arr + k1) + j));
}
}
I tried to understand your code, but to be honest, I have no idea what you are doing there. If you print character by character you only need to add a line break when you encounter a space and you need to keep track of how many characters you already printed on the same line.
#include <iostream>
int main() {
char x[] = "hello world qwerty------asd";
int chars_on_same_line = 0;
const int max_chars_on_same_line = 12;
for (auto& c : x) {
std::cout << c;
++chars_on_same_line;
if (c == ' ' || chars_on_same_line == max_chars_on_same_line){
std::cout << "\n";
chars_on_same_line = 0;
}
}
}
If for some reason you cannot use auto and rage based for loops then you need to get the length of the string and use an index, as in
size_t len = std::strlen(x);
for (size_t i = 0; i < len; ++i) {
c = x[i];
...
}
printf( "%.12s\n", wordStart);
can limit printed chars to 12.
Otherwise there are 2 independent data word starts and line limits.
word starts - each transition from white space to word char needs to be tracked.
whenever a word is completed = wordchar to whitespace
less than or equal to 12 chars since word start. Print whole word + new line.
greater than 12 chars. Print 12 chars and dump rest.
whitespace followed by whitespace - ignore

Shifting Objects Up in an Array

I'm creating a program that creates an array of objects in random positions in an array size 8. Once created, I need them to sort so that all the objects in the array are shifted up to the top, so no gaps exist between them. I'm almost there, but I cannot seem to get them to swap to index 0 in the array, and they instead swap to index 1. Any suggestions? (Must be done the way I'm doing it, not with other sorting algorithms or whatnot)
#include <iostream>
#include <string>
#include <ctime>
using namespace std;
struct WordCount {
string name = "";
int count = 0;
};
int main() {
cout << "Original random array: " << endl;
srand(static_cast<int>(time(0)));
int i = 0;
WordCount wordArr[8];
while (i < 4) {
int randomNum = 0 + (rand() % static_cast<int>(7 + 1));
if(wordArr[randomNum].name == "") {
wordArr[randomNum].name = "word" + static_cast<char>(i);
wordArr[randomNum].count = i;
i++;
}
}
int j = 0;
while (j < 8) {
cout << wordArr[j].name << " " << wordArr[j].count << endl;
j++;
}
cout << "\n\nSorted array: " << endl;
for (int i = 7; i >= 0; i--) {
for (int j = 0; j <= 7; j++) {
if (wordArr[i].name != "") {
if (wordArr[j].name == "") {
WordCount temp = wordArr[i];
wordArr[i] = wordArr[j];
wordArr[j] = temp;
}
}
}
}
int k = 0;
while (k < 8) {
cout << wordArr[k].name << " " << wordArr[k].count << endl;
k++;
}
return 0;
}
If I understand your requirement correctly, you want to move all the non-blank entries to the start of the array. To do this, you need an algorithm like this for example:
for i = 0 to 7
if wordArr[i].name is blank
for j = i + 1 to 7
if wordArr[j].name is not blank
swap [i] and [j]
break
So, starting from the beginning, if we encounter a blank entry, we look forward for the next non-blank entry. If we find such an entry, we swap the blank and non-blank entry, then break to loop again looking for the next blank entry.
Note, this isn't the most efficient of solutions, but it will get you started.
Note also I'd replace the 4 and 8 with definitions like:
#define MAX_ENTRIES (8)
#define TO_GENERATE_ENTRIES (4)
Finally:
wordArr[randomNum].name = "word" + static_cast<char>(i);
That will not do what you want it to do; try:
wordArr[randomNum].name = "word" + static_cast<char>('0' + i);
To append the digits, not the byte codes, to the end of the number. Or perhaps, if you have C++11:
wordArr[randomNum].name = "word" + std::to_string(i);
I see couple of problems.
The expression "word" + static_cast<char>(i); doesn't do what you are hoping to do.
It is equivalent to:
char const* w = "word";
char const* p = w + i;
When i is 2, p will be "rd". You need to use std::string("word") + std::to_string(i).
The logic for moving objects with the non-empty names to objects with empty names did not make sense to me. It obviously does not work for you. The following updated version works for me:
for (int i = 0; i <= 7; ++i) {
// If the name of the object at wordArr[i] is not empty, move on to the
// next item in the array. If it is empty, copy the next object that
// has a non-empty name.
if ( wordArr[i].name == "") {
// Start comparing from the object at wordArr[i+1]. There
// is no need to start at wordArr[i]. We know that it is empty.
for (int j = i+1; j <= 7; ++j) {
if (wordArr[j].name != "") {
WordCount temp = wordArr[i];
wordArr[i] = wordArr[j];
wordArr[j] = temp;
}
}
}
}
There was two problems as :
wordArr[randomNum].name = "word" + static_cast<char>(i); this is not what your are looking for, if you want that your names generate correctly you need something like this :
wordArr[randomNum].name = "word " + std::to_string(i);
Your sorting loop does not do what you want, it's just check for the "gaps" as you said, you need something like this :
for (int i = 0; i < 8; ++i) {
for (int j = i+1; j < 8; ++j) {
if (wordArr[i].name == "" || (wordArr[i].count < wordArr[j].count)) {
WordCount temp = wordArr[i];
wordArr[i] = wordArr[j];
wordArr[j] = temp;
}
}
}
Your algorithm sorts the array, but then looses the sorting again.
You want to swap elements only when i > j, in order to push elements to the top only. As a result, you need to change this:
if (wordArr[j].name == "")
to this:
if (wordArr[j].name == "" && i > j)
Consider this array example:
0
ord 1
0
0
rd 2
word 0
d 3
0
Your code will sort it to:
d 3
ord 1
word 0
rd 2
0
0
0
0
but when i = 3, it will try to populate the 5th cell, and it will swap it with rd 2, which is not what we want.
This will push rd 2 down, but we don't want that, we want gaps (zeroes) to go to the end of the array, thus we need to swap eleemnts only when they are going to go higher, not lower, which is equivalent to say when i > j.
PS: If you are a beginner skip that part.
You can optimize the inner loop by using one if statement and a break keyword, like this:
for (int j = 0; j <= 7; j++) {
if (wordArr[i].name != "" && wordArr[j].name == "" && i > j) {
WordCount temp = wordArr[i];
wordArr[i] = wordArr[j];
wordArr[j] = temp;
break;
}
}

Project Euler 8 in c++

I'm trying to solve problem 8 from project euler but I'm getting way too big numbers as results and I don't know why.
The problem is "Find the thirteen adjacent digits in the 1000-digit number that have the greatest product. What is the value of this product?"
My code :
#include <iostream>
#include <string>
int main()
{
std::string str = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";
long long a = 1;
long long fin = 0;
for (int c = 0; c < 988; c++)
{
for (int d = 0; d < 13; d++)
{
a = a * str.at(c + d);
}
if (a > fin)
{
fin = a;
std::cout << fin << " at " << c << std::endl;
}
a = 1;
}
system("pause");
}
The output :
7948587103611909356 at 0
8818137127266647872 at 15
8977826317031653376 at 71
9191378290313403392 at 214
9205903071867879424 at 573
Press any key to continue...
The problem is that the characters '0' through '9' are not the same as the integers 0 through 9; rather, '0' has the value 48, '1' has the value 49, and so on. (These are the ASCII values of those characters.)
So to convert from a digit character to the desired number — for example, to extract e.g. 3 from '3' — you need to subtract '0'. In other words, you need to change this:
a = a * str.at(c + d);
to this:
a = a * (str.at(c + d) - '0');

How to list all strings of length 12 in C++?

I'm a novice programmer studying my own. I tried to make a program that lists all strings of length 12 such as its characters are from a-z. However, there seems to be a bug I could find. It outputs for example The word is ). Could anyone tell me what I'm doing wrong, and is there some easier way to do the program?
#include <iostream>
#include <string>
int main(int argc, char *argv[])
{
using namespace std;
string l ("qwertyuiopasdfghjklzxcvbnm");
string test ("");
for(int i1 = 0;i1 < 26;++i1)
for(int i2 = 0;i2 < 26;++i2)
for(int i3 = 0;i3 < 26;++i3)
for(int i4 = 0;i4 < 26;++i4)
for(int i5 = 0;i5 < 26;++i5)
for(int i6 = 0;i6 < 26;++i6)
for(int i7 = 0;i7 < 26;++i7)
for(int i8 = 0;i8 < 26;++i8)
for(int i9 = 0;i9 < 26;++i9)
for(int i10 = 0;i10 < 26;++i10)
for(int i11 = 0;i11 < 26;++i11)
for(int i12 = 0;i12 < 26;++i12) {
test = l[i1]+l[i2]+l[i3]+l[i4]+l[i5]+l[i6]+l[i7]+l[i8]+l[i9]+l[i10]+l[i11]+l[i12];
cout << "The word is " << test << "." << endl;
test = "";
}
return 0;
}
l[i1]+l[i2] won't do what you expect. You're adding two expressions of type char so you'll get a result of type int.
An easy fix is:
test = std::string() + l[i1]+l[i2]+l[i3]+l[i4]+l[i5]+l[i6]+l[i7]+l[i8]+l[i9]+l[i10]+l[i11]+l[i12];
As I mentioned in my comment, when you see a permutations problem like this you should think of how to write a recursive algorithm.
In this case, ask yourself what each step (level) looks like. Well, you're given the string up to that point, you need to iterate through the letters, and you need to call the next level down each time so it can continue the process.
Working that out into code, "given the string up to this point" means your recursive function is passed in the prefix string, and a number indicating where it is in the chain:
void print_all_strings(const std::string& prefix, unsigned remain) {
Iterating through the letters is something you've already got (use a for loop), but the way you're doing it is not great. Instead of typing all the characters into a string and iterating through those characters, you're better off realizing that you can iterate through characters in a for loop like you can iterate through numbers, since characters are numbers in C++ (and C). In other words, 'a' + 1 == 'b' and so forth. So your loop becomes:
for(char c = 'a'; c <= 'z'; c++)
Finally, you need to handle the next level down. That means using the prefix and remain parameters to figure out what to do next. Well, there's one thing we know: if there are 0 letters left, then don't add a letter, but instead print the string and return!
if(remain == 0) {
cout << "The word is " << prefix << "." << endl;
return;
}
In other cases, we need to add a letter. That's where std::string + char => std::string comes in. (Note that char + char => char!)
print_all_strings(prefix + c, remain - 1);
Putting it all together:
void print_all_strings(const std::string& prefix, unsigned remain) {
if(remain == 0) {
cout << "The word is " << prefix << "." << endl;
return;
}
for(char c = 'a'; c <= 'z'; c++)
print_all_strings(prefix + c, remain - 1);
}
int main(int argc, char *argv[])
{
print_all_strings("", 12);
return 0;
}
But then, as CiaPan explained, your computer will die before this program finishes.