Word & Character Counter — C++ source
Live word, character, sentence, and paragraph counts plus reading-time estimate as you type.
This is the C++ implementation — the same logic the interactive tool runs, in a shareable, citable form.
// word-counter — C++ port: word / character / sentence / paragraph counts + 200-wpm reading-time estimate.
// Display snippet: ports the counters from the TypeScript lib (src/lib/wordCount.ts); string_view
// counts bytes, so multi-byte UTF-8 diverges from the TS reference's UTF-16 code units.
#include <cctype>
#include <cstdio>
#include <string_view>
namespace word_counter {
// Words: runs of non-whitespace (ASCII subset of the JS /\s/). Blank input -> 0.
inline long count_words(std::string_view t) {
long n = 0;
bool in_word = false;
for (char c : t) {
if (std::isspace(static_cast<unsigned char>(c))) in_word = false;
else if (!in_word) { in_word = true; ++n; }
}
return n;
}
// Total character count, whitespace included.
inline long count_chars(std::string_view t) { return static_cast<long>(t.size()); }
// Character count with every whitespace byte removed.
inline long count_chars_no_spaces(std::string_view t) {
long n = 0;
for (char c : t) if (!std::isspace(static_cast<unsigned char>(c))) ++n;
return n;
}
// Sentences: maximal runs of non-terminators each closed by one or more of
// . ! ? — the TS regex /[^.!?]+[.!?]+/g as a single scan.
inline long count_sentences(std::string_view t) {
long n = 0;
bool body = false;
for (char c : t) {
if (c == '.' || c == '!' || c == '?') {
if (body) { ++n; body = false; }
} else {
body = true;
}
}
return n;
}
// Paragraphs: segments split by runs of 2+ newlines; blank segments don't
// count (the TS split(/\n{2,}/).filter(s => s.trim())).
inline long count_paragraphs(std::string_view t) {
long n = 0, run = 0;
bool blank = true;
for (char c : t) {
if (c == '\n') {
if (++run == 2) { // blank line closes the paragraph
if (!blank) ++n;
blank = true;
}
continue;
}
run = 0;
if (!std::isspace(static_cast<unsigned char>(c))) blank = false;
}
return blank ? n : n + 1;
}
// Reading time at 200 wpm: 0 for empty, else >= 1 min; (w + 100) / 200 == Math.round(w / 200).
inline long reading_time_min(long words) {
if (words <= 0) return 0;
long m = (words + 100) / 200;
return m < 1 ? 1 : m;
}
} // namespace word_counter
int main() {
using namespace word_counter;
std::string_view text = "CosmoDev counts words. Live totals update as you type!\n\n"
"Second paragraph? Two sentences - each with words. Zero logins needed.";
long w = count_words(text);
std::printf("words: %ld\n", w); // 20
std::printf("chars: %ld\n", count_chars(text)); // 126
std::printf("no spaces: %ld\n", count_chars_no_spaces(text)); // 106
std::printf("sentences: %ld\n", count_sentences(text)); // 5
std::printf("paragraphs: %ld\n", count_paragraphs(text)); // 2
std::printf("reading min: %ld\n", reading_time_min(w)); // 1
return 0;
}
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →