I need to cout random word which starts with 'k; I have decided to count the amount of words and amount of words(beginning with 'k'); After that i made it into an array, so i could have an array full of the number of words which start with 'k'; But here is the problem, compiler doesn't let the code to go on and i can't understand what's the problem; I'm a beginner, so go easy on me; Here is the code:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <stdlib.h>
#include <ctime>
#include <cmath>
#include <cstring>
#include <clocale>
#include <Windows.h>
using namespace std;
int main()
{
srand(time(NULL));
char str1[150] = "knight kevin once said that maybe that kind of process is necessary to him pushing him on and on and it is very painful he knows.";
cout << str1 << endl;
int sz = 1;
int s = 1;
int sz_count = 1;
int s_count = 0;
int x = 1;
int* amounts_of_words = new int[s];
int* array_of_K = new int[sz];
if (str1[0] == 'k' || str1[0] == 'K') {
array_of_K[0] = 1;
sz ;
}
for (int i = 0; str1[i] != '\0'; i ) {
if (str1[i] == ' ' || str1[i] == '.' || str1[i] == '?' || str1[i] == '!') {
amounts_of_words[s_count] = x;
s ;
x ;
if (str1[i 1] == 'k') {
array_of_K[sz_count] = amounts_of_words[s_count] 1;
sz ;
sz_count ;
}
s_count ;
}
if (str1[i 1] == '\0') {
sz--;
s--;
}
}
for (int f = 0; f < sz; f ) {
cout << array_of_K[f] << " ";
}
char* token;
int randomN = rand() % 4;
cout << randomN;
cout << array_of_K[randomN];
for (int i = 1; i <= s; i ) {
if (i == 1 && i == array_of_K[randomN]) {
token = strtok(str1, " ");
cout << token;
break;
}
else if (i == 0) {
token = strtok(str1, " ");
}
else {
token = strtok(NULL, " ");
if (i == array_of_K[randomN]) {
cout << token;
break;
}
}
}
delete[] array_of_K;
delete[] amounts_of_words;
}
CodePudding user response:
First you can make your program a lot smaller(in size) and better(general) using std::map
Below is the complete working example that shows how can achieve this:
#include <iostream>
#include <map>
#include <sstream>
int main() {
std::string inputString = "knight kevin once said that maybe that kind of process is necessary to him pushing him on and on and it is very painful he knows.";
std::istringstream s(inputString);
//this map maps the char to their respective count
std::map<char, int> charCount;
std::string word;
int count = 0;//this count the total number of words
while(s >> word)
{
charCount[word[0]] ;
count ;
}
std::cout<<"Total number of words are:"<<count<<" out of which"<<std::endl;
for(std::pair<char, int> pairElement: charCount)
{
std::cout<<pairElement.second<<" starts with: "<<pairElement.first<<std::endl;
}
return 0;
}
Check out the program here.
The output of the above program is as follows:
Total number of words are:26 out of which
2 starts with: a
3 starts with: h
3 starts with: i
4 starts with: k
1 starts with: m
1 starts with: n
4 starts with: o
3 starts with: p
1 starts with: s
3 starts with: t
1 starts with: v
CodePudding user response:
When people say "idiomatic C " they mean something like this:
#include <iostream>
#include <string>
#include <random>
#include <set>
// dont use : using namespace std;
// make functions!
// don't use arrays they need manual memory management with new[]/delete[]
// this is no longer the recommended way in C
// for dynamically allocatable arrays just use std::vector!
// this is just one way of splitting a string into words.
std::vector<std::string> get_words_starting_with_letter(const std::string& string, const char letter)
{
static const std::set<char> delimiters{ ' ', '.' }; // all those chars that are not part of a word.
std::vector<std::string> words;
char upper_case_letter = static_cast<char>(::toupper(letter));
auto word_begin = string.begin();
// use an iterator to move over the string.
for (auto it = string.begin(); it != string.end(); it)
{
// if a non-word character is found then push back
// a new string beginning at word_begin adn ending at it
if (delimiters.find(*it) != delimiters.end())
{
if ((*word_begin == letter) || (*word_begin == upper_case_letter))
{
words.emplace_back(word_begin, it);
}
// skip delimiter
if (it 1 != string.end())
{
it;
word_begin = it;
}
}
}
return words;
}
int main()
{
// srand is from "C", C has this:
std::random_device rd; // better seed then stime
std::default_random_engine random{ rd() };
// if something is a string then use a std::string, make it const because
// it is not supposed to be changed
const std::string str1{ "knight kevin once said that maybe that kind of process is necessary to him pushing him on and on and it is very painful he knows." };
// really do make functions to make your code readable
auto words_with_k = get_words_starting_with_letter(str1, 'k');
// indices in containers use std::size_t
std::uniform_int_distribution<std::size_t> distribution(0, words_with_k.size()-1); // distributions are inclusive, so take care to substract 1 from size
// now just output some random words
for (std::size_t n = 0; n < 10; n)
{
auto index = distribution(random);
std::cout << "random word beginning with a 'k' #" << n 1 << " is : " << words_with_k.at(index) << "\n";
}
return 0;
}