-1

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;
}
user438383
  • 5,716
  • 8
  • 28
  • 43
  • 5
    Just a note: your opinion of the code doesn't matter if the compiler is complaining. – sweenish Oct 20 '21 at 13:30
  • `amounts_of_words` is an array of exactly 1 element. You try to write more than 1 element to that, which (I guess) results in a segmentation fault. – Yksisarvinen Oct 20 '21 at 13:31
  • The error I get is about `Windows.h`; check your capitalization on that. – sweenish Oct 20 '21 at 13:32
  • 1
    First of all please try to create a [mre] to show us, with emphasis on the *minimal* part. It shoulr preferably only be a few lines which replicates the error you're asking about, and nothing more. Then when posting questions about build errors, add comment in the code on the lines where you get the errors, and copy-paste the full and complete build output (as text!) into the question itself. And also tell us how you build the program and what options and flags and configurations you use when building. – Some programmer dude Oct 20 '21 at 13:33
  • 1
    At a glance, I don't see why `Windows.h` is in there in the first place... – DevSolar Oct 20 '21 at 13:34
  • Please choose a title which is useful for others with the same issue. – user438383 Oct 20 '21 at 13:34
  • Commenting out the windows header, I get the code to compile and I get output, but I can't tell you if it's what you want or not. What's the expected output? – sweenish Oct 20 '21 at 13:35
  • 1
    If the problem is *not* a build error, but an error when you attempt to run the program, then the compiler isn't involved. If the problem is a crash then you should use a debugger to locate when and where in your code the crash happens. If the problem is invalid or wrong output then you need to tell us the input together with the expected and actual output. And also use a debugger to step through the code statement by statement while monitoring variables and their values, to see when and where things go wrong. – Some programmer dude Oct 20 '21 at 13:36
  • Your question is tagged C++, but the code you presented is the classic "C with `std::cout`". A *good* answer would include a complete rewrite of your code in idiomatic C++, with strings, vectors, streams, and quite likely end up being a five-liner with some `` in it... and definitely neither pointers nor C arrays. What I am trying to say is: Get a better book / tutorial / tutor. Also, *comments*... – DevSolar Oct 20 '21 at 13:36
  • `#include` is a C++ red flag. At the least it should be `#include`. – sweenish Oct 20 '21 at 13:37
  • If you have run-time problem, it's probably because you forget that array or memory allocations aren't dynamic. Once you have created an array or allocated memory with a specific size, then that's the size they will have. And flow of control goes from top to bottom, once you have passed e.g. `int* array_of_K = new int[sz];` then modifying `sz` will not change the memory already allocated. Either move the allocations to after you set the actual size, or use `std::vector`. – Some programmer dude Oct 20 '21 at 13:38
  • All in all it seems that whatever resource you're using to learn C++ is not doing a very good job. I recommend you invest in [some good C++ books](https://stackoverflow.com/a/388282/440558) to read and learn from. – Some programmer dude Oct 20 '21 at 13:39
  • @Someprogrammerdude Thanks a lot for the advice, i really lost the fact, that once you have created an array or allocated memory with a specific size, then that's the size they will have. std::vector helped; – Gleb Shapovalov Oct 20 '21 at 14:46
  • Thank everybody. It's my first question. Next time, i will take all your notes into consideration. – Gleb Shapovalov Oct 20 '21 at 14:47

2 Answers2

0

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
Jason
  • 36,170
  • 5
  • 26
  • 60
0

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;
}
Pepijn Kramer
  • 9,356
  • 2
  • 8
  • 19