How do I read the new line character? I am trying to do a character count, but the new line gets in the way. I tried doing if (text[i] == ' ' && text[i] == '\n') but that didn't work. Here is my repl.it session.
I am trying to read this from file.txt:
i like cats
dogs are also cool
so are orangutans
This is my code:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream input;
input.open("file.txt");
int numOfWords = 0;
while (true)
{
string text;
getline(input, text);
for(int i = 0; i < text.length(); i++)
{
if (text[i] == ' ')
{
numOfWords++;
}
}
if (input.fail())
{
break;
}
}
cout << "Number of words: " << numOfWords+1 << endl;
input.close();
}
Your question is asking how to count characters, but your code is counting words instead. std::getline() swallows line breaks. You don't need to worry about them if you want to count words. In fact, you can use operator>> to greatly simplify your counting in that case, eg:
int main()
{
ifstream input("file.txt");
int numOfWords = 0;
string word;
while (input >> word)
++numOfWords;
cout << "Number of words: " << numOfWords << endl;
return 0;
}
If you really want to count characters instead of words, use std::ifstream::get() to read the file 1 character at a time, eg:
int main()
{
ifstream input("file.txt");
int numOfChars = 0;
int numOfWords = 0;
bool isInSpace = true;
char ch;
while (input.get(ch))
{
++numOfChars;
if (std::isspace(ch, input.getloc())) {
isInSpace = true;
}
else if (isInSpace) {
isInSpace = false;
++numOfWords;
}
}
cout << "Number of chars: " << numOfChars << endl;
cout << "Number of words: " << numOfWords << endl;
return 0;
}
Related
I'm just learning c++. I have a problem with my program. I have to write a program which reverse string and count amount word in the string. My program doesn't return amount words and reverse only last word in string. I totally don't know how to correct it. :D
#include <iostream>
using namespace std;
void reverseString(string str)
{
for (int i=str.length()-1; i>=0; i--)
{
cout << str[i];
}
}
void countString(string strg)
{
int word = 1;
for(int j = 0; strg[j] != '\0'; j++)
{
if (strg[j] == ' ')
{
word++;
}
}
}
int main(void)
{
string inputString;
cout << "Give a string: ";
cin >> inputString;
cout << "Reverse string: ";
reverseString(inputString);
cout << "\nCounts words in a string: ";
countString(inputString);
return 0;
}
If you want to read multiple words then you must use getline as >> reads only a single word.
string inputString;
cout << "Give a string: ";
getline(cin, inputString);
To return something from a function you must 1) specify the return type and 2) use a return statement to return a value and 3) do something with that return value in the calling function
Step 1
int countString(string strg) // here we say countString returns an integer
{
...
}
Step 2
int countString(string strg)
{
...
return words; // here we say the value we want to return
}
Step 3
// here we output the value returned from the function
cout << "\nCounts words in a string: " << countString(inputString) << "\n";
Knowing how to write functions that return values is absolutely fundamental C++. You should practise this. See if you can do the same with your reverseString function, instead of printing a string make it return a string.
There are some mistake in your code.In countString() function you return nothing.So it does not print anything.If you take input as a string include a space character,please use getline(cin, inputString).Here the code for you:
#include <iostream>
using namespace std;
void reverseString(string str)
{
for (int i=str.length()-1; i>=0; i--)
{
cout << str[i];
}
}
int countString(string strg)
{
int word = 0;
for(int j = 0; strg[j] != '\0'; j++)
{
word++;
}
return word;
}
int main(void)
{
string inputString;
cout << "Give a string: ";
getline(cin, inputString);
cout << "Reverse string: ";
reverseString(inputString);
cout << "\nCounts words in a string: ";
cout<<countString(inputString)<<endl;
return 0;
}
I'm writing a wordcount function that should be able to read elements from stdin into a string. Then evaluate the string and return the number of words, number of lines, size of the string, and the number of unique words.
My issue is when it comes to adding words to the unique set. When I write it to add elements to a set, it would count the whitespace as part of the word then push entirely into my set.
Example:
Input:
this is
is
a test
test
Output
a
test
is test this
line is 4
Words = 7
size is 27
Unique is 6
It counts 7 words in total and 6 unique. I tried debugging it by printing bits of the code as i go so i can keep track of where I went wrong. I can only conclude that the issue lies within my if loops. How can I get past this, I've been stuck for some time now.
Here is my code:
#include<iostream>
#include<string>
#include<set>
using std::string;
using std::set;
using std::cin;
using std::cout;
set<string> UNIQUE;
size_t sfind(const string s) //will take string a count words, add to set
{
string a;
int linecount = 0;
int state = 0; //0 represents reading whitespace/tab, 1 = reading letter
int count = 0; //word count
for(size_t i =0; i < s.length(); i++) {
a+=s[i]; //add to new string to add to set
if(state ==0) { //start at whitespace
if(state != ' ' && state != '\t') { //we didnt read whitespace
count++;
state =1;
}
}
else if(s[i]== ' ' || s[i] == '\t' || s[i] == '\n') {
state = 0;
UNIQUE.insert(a); //add to UNIQUE words
a.clear(); // clear and reset the string
}
if (s[i] == '\n') {
linecount++;
}
}
for(set<string>::iterator i = UNIQUE.begin(); i!= UNIQUE.end(); i++) {
cout << *i;
}
cout << '\n';
cout << "line is " << linecount << '\n';
return count;
}
int main()
{
char c;
string s;
while(fread(&c,1,1,stdin)) {
s+=c; //read element add to string
}
cout << "Words = " << sfind(s) << '\n';
cout << "size is " << s.length() << '\n';
cout << "Unique is "<< UNIQUE.size() << '\n';
return 0;
}
Also I will be using
fread(&c,1,1,stdin)
because i will be using it later on with a larger wordcount function.
Rather than writing code trying to parse the string on spaces, use std::istringstream to do the parsing.
Here is an example:
#include <string>
#include <iostream>
#include <sstream>
#include <set>
int main()
{
std::set<std::string> stringSet;
std::string line;
while (std::getline(std::cin, line))
{
std::istringstream oneline(line);
std::string word;
while (oneline >> word)
{
std::cout << word << "\n";
stringSet.insert(word);
}
}
std::cout << "\n\nThere are " << stringSet.size() << " unique words";
}
Live Example
I have attempted to remove the occurrences of a user inputted letter after they've chosen a word however, the final output prints out a random string of letters and numbers instead of what I expected. For example, if the user enters the text "Coffee" then proceeds to enter the letter "f", the program should return "Coee" as the final print. However, this is not the case. Could anyone check to see where I've gone wrong? Much obliged.
#include <iostream>
#include <string>
using namespace std;
void removeAllOccurrence(char text[], char letter)
{
int off;
int i;
i = off = 0;
if (text[i] == letter)
{
off++;
}
text[i] = text[i + off];
}
int main() {
string text;
char letter;
string newText;
cout << "Type your text: " << endl;
cin >> text;
cout << "Choose the letters to remove: " << endl;
cin >> letter;
cout << "your new text is: " << removeAllOccurrence << endl;
system("pause");
return 0;
}
This should do the job
#include <algorithm>
#include <string>
#include <iostream>
void remove_char(std::string s, char r) {
s.erase( std::remove( s.begin(), s.end(), r), s.end()) ;
std::cout << s << std::endl;
}
int main()
{
std::string test = "coffee";
char r = 'f';
remove_char(test, r);
return 0;
}
If u want to do this by hand try this:
std::string removeAllOccurrence(string text, char letter)
{
int off;
int i;
i = off = 0;
string out = "";
for (i = 0; i < text.size(); i++)
{
if (text[i] != letter)
{
out += text[i];
}
}
return out;
}
int main(void)
{
string text;
char letter;
string newText;
cout << "Type your text: " << endl;
cin >> text;
cout << "Choose the letters to remove: " << endl;
cin >> letter;
cout << "your new text is: " + removeAllOccurrence(text, letter) << endl;
system("pause");
return 0;
}
As you can see your main function was kinda right. You just need to pass some arguments into the function. Additonally you missed a loop in your remove function. If you use string in your main, why don't use string in yur function? You can just use string there, too
Kind Regards
need to create a word matcher which counts how many times a specific word is mentioned in a text file. here is what i have done so far and am not sure what iv done wrong. 1 text file contains a long paragraph the other just contains a few words. I need to compare both text files e.g. the word "and" is in the short text file. need to compare this with the long paragraph and see how many time this words appears and then have a report at the end of the program which displays this.
E.g and - 6tmes, but - 0times, it - 23times.
^^ something like this. not sure how to start making this
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
ifstream infile("text1.txt");
if(!infile)
{
cout << "Error";
}
string words[250];
int counter = 0;
while (!infile.eof() )
{
infile >> words[counter];
counter++;
}
ifstream infile2("banned.txt");
if(!infile2)
{
cout << "Error";
}
string bannedwords[250];
counter = 0;
while (!infile2.eof() )
{
infile2 >> words[counter];
counter++;
}
int eatcount= 0;
int orcount = 0;
int hellocount = 0;
int number;
for(int i=0; i<200; i++)
{
for(int j = 0; j < 8; j++)
{
if ( words[i] == bannedwords[j])
{
cout << words[i] << " ";
if (words[i]=="eat")
{
eatcount++;
}
else if (words[i] == "or")
{
orcount++;
}
else if (words[i]== "hello")
{
hellocount++;
}
}
}
}
cout << endl;
cout<< "eat was found "<<eatcount<<" times";
cout << endl;
cout<< "or was found "<<orcount<<" times";
cout << endl;
cout<< "hello was found "<<hellocount<<" times";
system("pause");
}
Why not use a std::multiset?
ifstream infile("text1.txt");
if(!infile)
{
cout << "Error";
}
std::multiset<string> words;
string tmp;
while (!infile.eof() )
{
infile >> tmp;
words.insert(tmp);
}
Then also use a map for the banned words:
ifstream infile2("banned.txt");
if(!infile2)
{
cout << "Error";
}
std::map<string, int> banned;
string tmp;
while (!infile2.eof() )
{
infile2 >> tmp;
banned.insert(tmp);
}
Then you can use std::multiset::count(string) to find the words without all the extra looping. You would only need one loop to go through your banned words list. e.g:
std::map<string, int>::iterator bannedwordIter = bannedwords.begin();
for( ; bannedwordIter != bannedwords.end(); ++bannedwordIter )
{
bannedwordIter->second = words.count(bannedwordIter->first);
// you could print here as you process, or have another loop that prints it all after you finish
cout << bannedwordIter->first << " - " << bannedwordIter->second << " times." << endl;
}
A minimal way would be to use regular expressions, like so
#include <iostream>
#include <fstream>
#include <string>
#include <regex>
using namespace std;
unsigned countMatches(std::istream &is, std::string const &word)
{
string text;
unsigned count(0);
std::regex const expression(word);
while (getline(is, text)) {
count += distance(sregex_iterator(
text.begin(), text.end(), expression), sregex_iterator());
}
return count;
}
so you just pass it the input stream (in your case an input file stream) and it counts the occurences of the word specified after creating a regular expression that matches that word
int main()
{
ifstream ifs;
ifs.open("example_text_file.txt");
cout << countMatches(ifs, "word_you_want_to_search_for") << endl;
return 0;
}
I am working on a project where I will be able to read in a file that contains any text, like the sample text below. Then, character by character, it will be able to output n-character long sequences (represented below as a read-in value given by the user along the lines of 1, 2, 3, 4...) along the whole length of the text. So, for example:
As Gregor Samsa awoke one morning from uneasy dreams he found himself transformed in his bed into a gigantic insect.
If the user provided 2 as the sequence length, the program should spit out: "As" "s " " G" "Gr" "re" "eg" "go" "or" "r " and so on...
I have written this code but don't know why it won't work. Right now, it doesn't spit out every possible variation of the sequence. Any suggestions would be very helpful. Thanks.
#include "genlib.h"
#include <iostream>
#include <fstream>
#include "simpio.h"
#include "random.h"
#include "vector.h"
#include "map.h"
/* Private Instance Variables */
int seed_length;
string line;
string seed_string;
string next_string;
char ch;
/* Function Prototypes */
string promptUserForFile(ifstream & infile);
int main() {
ifstream infile;
promptUserForFile(infile);
// Ask what order of Markov model to use.
cout << "What order of Markov model should we use? ";
cin >> seed_length;
while (infile.eof() == false) {
ch = infile.get();
for (int i = 0; i < seed_length - 1; i++) {
cout << "ch up here is " << ch << endl;
if (isspace(ch) && i == 0) {
seed_string += ch;
} else {
seed_string += ch;
ch = infile.get();
}
}
next_string = ch;
if (isspace(ch)) {
next_string = " ";
} else {
char trythis = infile.get();
next_string += trythis;
}
cout << seed_string << endl;
cout << next_string << endl;
seed_string = "";
next_string = "";
}
cout << "TEST" << endl;
// Close the file when you're done storing all of the scores.
infile.close();
return 0;
}
string promptUserForFile(ifstream & infile) {
string prompt = "Please input your filename: ";
while(true) {
cout << prompt;
string filename;
getline (cin, filename);
infile.open(filename.c_str());
if(!infile.fail()) return filename;
infile.clear();
cout << "Unable to open that file. Try again." << endl;
if (prompt == "") prompt == "Input file: ";
}
return 0;
}
The code has two problems.
The special handling for isspace is broken:
if (isspace(ch) && i == 0) {
seed_string += ch;
} else {
seed_string += ch;
ch = infile.get();
}
This essentially means that if the first character in this loop is a space, it will be added twice.
Every character received from infile.get() is only added to seed_string once (with the exception of isspace characters).
A better way to code this is to recognize that:
You have to ignore consecutive isspace characters.
Every sequence can be obtained by removing the first character of the preceding sequnce and appending the next character from the file.
Here is a better implementation; it takes the order of the Markov model in the first command line parameter and takes the text from standard input. By encapsulating the skipping of duplicate spaces in a separate function, you don't have to deal with it in the main body of the algorithm.
#include <iostream>
#include <cstdlib>
char next_character() {
static bool was_space = false;
char ret = 0;
do {
ret = std::cin.get();
} while (was_space && std::isspace(ret));
if (std::isspace(ret)) {
was_space = true;
ret = ' ';
} else {
was_space = false;
}
return ret;
}
int main(int argc, char **argv) {
if (argc != 2) return 0;
int mlen = std::atoi(argv[1]);
std::string seq;
for (unsigned i = 0; i < mlen; ++i) {
seq += next_character();
}
std::cout << seq << '\n';
while (true) {
seq.erase(0, 1);
char c = next_character();
if (std::cin.eof()) break;
seq += c;
std::cout << seq << '\n';
}
return 0;
}
Example input:
This is a test
Example output:
This
his i
is is
s is
is a
is a
s a t
a te
a tes
test