#include <iostream>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <string>
#include <iomanip>
#include <fstream>
#include <stdio.h>
using namespace std;
int main()
{
ifstream file;
string filename;
char character;
int letters[153] = {};
cout << "Enter text file name: ";
cin >> filename;
file.open(filename.c_str());
if (! file.is_open())
{
cout << "Error opening file. Check file name. Exiting program." << endl;
exit(0);
}
while (file.peek() != EOF)
{
file >> character;
if(!file.fail())
{
letters[static_cast<int>(character)]++;
}
}
for (int i = 0; i <= 153; i++)
{
if (letters[i] > 0)
{
cout << static_cast<char>(i) << " " << letters[i] << endl;
}
}
exit(0);
}
#endif
Hi everyone, my current code counts the frequency of each letter from a text file. However, it does not count the number of blank spaces. Is there a simple way to printout the number of blank spaces in a .txt file?
Also, how come when I'm trying to access a vector item, I run into a seg fault?
For example, if I use:
cout << " " + letters[i] << endl;, it displays a segfault. Any ideas?
Thank you so much.
By default, iostreams formatted input extraction operations (those using >>) skip past all whitespace characters to get to the first non-whitespace character. Perhaps surprisingly, this includes the extraction operator for char. In order to consider whitespace characters as characters to be processed as usual, you should alter use the noskipws manipulator before processing:
file << std::noskipws;
Don't forget to set it back on later:
file << std::skipws;
What if you're one of those crazy people who wants to make a function that leaves this aspect (or in even all aspects) of the stream state as it was before it exits? Naturally, C++ provides a discouragingly ugly way to achieve this:
std::ios_base::fmtflags old_fmt = file.flags();
file << std::noskipws;
... // Do your thang
file.flags(old_fmt);
I'm only posting this as an alternative way of doing what you're apparently trying. This uses the same lookup table approach you use in your code, but uses an istreambuf_iterator for slurping unformatted (and unfiltered) raw characters out of the stream buffer directly.
#include <iostream>
#include <fstream>
#include <iterator>
#include <climits>
int main(int argc, char *argv[])
{
if (argc < 2)
return EXIT_FAILURE;
std::ifstream inf(argv[1]);
std::istreambuf_iterator<char> it_inf(inf), it_eof;
unsigned int arr[1 << CHAR_BIT] = {};
std::for_each(it_inf, it_eof,
[&arr](char c){ ++arr[static_cast<unsigned int>(c)];});
for (int i=0;i<sizeof(arr)/sizeof(arr[0]);++i)
{
if (std::isprint(i) && arr[i])
std::cout << static_cast<char>(i) << ':' << arr[i] << std::endl;
}
return 0;
}
Executing this on the very source code file itself, (i.e. the code above) generates the following:
:124
#:4
&:3
':2
(:13
):13
*:1
+:4
,:4
/:1
0:3
1:2
2:1
::13
;:10
<:19
=:2
>:7
A:2
B:1
C:1
E:2
F:1
H:1
I:3
L:1
R:2
T:2
U:1
X:1
[:8
]:8
_:10
a:27
b:1
c:19
d:13
e:20
f:15
g:6
h:5
i:42
l:6
m:6
n:22
o:10
p:1
r:37
s:20
t:34
u:10
v:2
z:2
{:4
}:4
Just a different way to do it, but hopefully it is clear that usually the C++ standard library offers up elegant ways to do what you desire if you dig deep enough to find whats in there. Wishing you good luck.
Related
I work with russian a lot and I've been trying to get data from a file with an input stream. Here's the code, it's supposed to output only the words that contain no more than 5 characters.
#include <iostream>
#include <fstream>
#include <string>
#include <Windows.h>
using namespace std;
int main()
{
setlocale(LC_ALL, "ru_ru.utf8");
ifstream input{ "in_text.txt" };
if (!input) {
cerr << "Ошибка при открытии файла" << endl;
return 1;
}
cout << "Вывод содержимого файла: " << "\n\n";
string line{};
while (input >> line) {
if (line.size() <= 5)
cout << line << endl;
}
cout << endl;
input.close();
return 0;
}
Here's the problem:
I noticed the output didn't pick up all of the words that were actually containing less than 5 characters. So I did a simple test with the word "Test" in english and the translation "тест" in russian, the same number of characters. So my text file would look like this:
Test тест
I used to debugger to see how the program would run and it printed out the english word and left the russian. I can't understand why this is happening.
P.S. When I changed the code to if (line.size() <= 8) it printed out both of them. Very odd
I think I messed up my system locale somehow I don't know. I did one time try to use std::locale
without really understanding it, maybe that did something to my PC I'm not really sure. Please help
I'm very unsure about this but using codecvt_utf8 and wstring_convert seems to work:
#include <codecvt> // codecvt_utf8
#include <string>
#include <iostream>
#include <locale> // std::wstring_convert
int main() {
// ...
while (input >> line) {
// convert the utf8 encoded `line` to utf32 encoding:
std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> u8_to_u32;
std::u32string u32s = u8_to_u32.from_bytes(line);
if (u32s.size() <= 5) // check the utf32 length
std::cout << line << '\n'; // but print the utf8 encoded string
}
// ...
}
Demo
I need help, I wrote the code, did the reverse thing but I can't get it written on another file.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
ifstream par2("C:/fajllat/f1.bin", ios::in);
string line;
for (int i = 1; !par2.eof() ; i++)
{
getline(par2, line);
if (i < 5 || i >14) continue;
line = string(line.rbegin(), line.rend());
}
par2.close();
ofstream mbrapsht ("C:/fajllat/f3.bin", ios::out);
mbrapsht << line;
mbrapsht.close();
cin.get();cin.get();
return 0;
}
When I check the files the f3.bin file is empty
You have the right idea. What you're missing is that if you want to write the reversed lines, you need to either write them inside the loop or store them for after. You are doing neither of these things.
Currently what happens is you overwrite line every loop. And whatever is left in that string is what you write afterwards. Turns out that for your case, that's an empty string.
Let's make minimal changes to what you have:
// (*) Open the output file before looping
ofstream mbrapsht("C:/fajllat/f3.bin", ios::out);
for (int i = 1; !par2.eof() ; i++)
{
getline(par2, line);
if (i < 5 || i > 14) continue;
line = string(line.rbegin(), line.rend());
// (*) output the line - you also probably want an end-of-line
mbrapsht << line << std::endl;
}
Now, it's okay-ish. But it does have a problem where if getline fails, your code still runs the loop body one more time. This happens if getline hits the end of file (or some other error state), which your loop doesn't pick up until the next iteration (or possibly never, if the error is not EOF).
So, a somewhat better choice might be:
for(int lineNo = 1; std::getline(par2, line); ++lineNo)
{
if (lineNo >= 5 && lineNo <= 14)
{
std::reverse(line.begin(), line.end()); // (*) requires <algorithm>
mbrapsht << line << std::endl;
}
}
Note that I also inverted your test condition and removed the continue. In general, I avoid continue and break in loops unless not using them results in code that is hard to follow or understand at a glance. It's a style/maintainability thing. Take it or leave it.
See this snippet . For line-by-line reversal, you can use getline() instead and reverse before pushing into vector<string>.
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <algorithm>
using namespace std;
int main()
{
string str;
ifstream par2("D:\\MyFolder\\try.txt", ios::in);
if (par2.is_open())
{
stringstream strStream;
strStream << par2.rdbuf();
str = strStream.str();
cout << str << endl;
par2.close();
}
cout << "\n\nReversing ...\n\n";
std::reverse(str.begin(), str.end());
cout << str << endl;
ofstream mbrapsht("D:\\MyFolder\\try2.txt", ios::out);
mbrapsht << str;
mbrapsht.close();
return 0;
}
Output:
I'm trying to count same string/words from a text file in C++.
This is my text file
one two three two
test testing 123
1 2 3
This is my main program
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(int argc, const char** argv)
{
int counter = 0;
int ncounter = 0;
string str;
ifstream input(argv[1]);
while (getline(input, str))
{
if(str.find("two") != string::npos){counter++;}
if(str.find('\n') != string::npos){ncounter++;}
cout << str << endl; //To show the content of the file
}
cout << endl;
cout << "String Counter: " << counter << endl;
cout << "'\\n' Counter: " << ncounter << endl;
return 0;
}
I'm using the .find() function to find the string.
When I insert an non-existant word, it doesn't count.
When I insert the word "two", it counts, but only once.
How come it didn't count 2 times?
And for the carriage return (or return line; \n), it can't count any. Why is that?
Because the two twos are on the same line and you are searching the line only for one substring.
You can't find the '\n' because the getline function reads the line up to and without the '\n'.
Why not use a std::multiset to store the words? It would do the counting for you, and reading the file into it can be done in one line:
#include <iostream>
#include <fstream>
#include <string>
#include <set>
#include <iterator>
int main(int argc, const char** argv)
{
// Open the file
std::ifstream input(argv[1]);
// Read all the words into a set
std::multiset<std::string> wordsList =
std::multiset<std::string>( std::istream_iterator<std::string>(input),
std::istream_iterator<std::string>());
// Iterate over every word
for(auto word = wordsList.begin(); word != wordsList.end(); word=wordsList.upper_bound(*word))
std::cout << *word << ": " << wordsList.count(*word) << std::endl;
// Done
system("pause");
return 0;
}
Note the last for part - word=wordsList.upper_bound(*word). Technically you can switch it to simply word++ (then actually it would be better to shorten it to simply for(auto word: wordList). It ensures each value from the set will only be output once.
It will also list the words themselves without you needing to do it like now inside your current while loop.
Your best bet is going to be to read each line, then tokenize along the white space so you can examine each word individually.
I suspect we're talking about a homework assignment here, so my best answer is to direct you to the c++ reference for std::strtok: http://en.cppreference.com/w/cpp/string/byte/strtok
I need to do this:
$ ./compiledprog.x < inputValues > outputFile
so that I read from the file inputValues which for our case might just be \n separated int values or whatever. Then anything printf()'d goes into outputFile. But what's this called, technically speaking, and where can I find a demo of doing this.
As noted by others, it's input/output redirection.
Here's an example program that would copy the standard input to the standard output, in your example copy the contents from inputValues to outputFile. Implement whatever logic you want in the program.
#include <unistd.h>
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
using std::cerr;
#include <string>
using std::string;
int main(int argc, char** argv) {
string str;
// If cin is a terminal, print program usage
if (isatty(fileno(stdin))) {
cerr << "Usage: " << argv[0] << " < inputValues > outputFile" << endl;
return 1;
}
while( getline(cin, str) ) // As noted by Seth Carnegie, could also use cin >> str;
cout << str << endl;
return 0;
}
Note: this is quick and dirty code, which expects a well behaved file as input. A more detailed error checking could be added.
This is called I/O redirection.
I'm obviously not quite getting the 'end-of-file' concept with C++ as the below program just isn't getting past the "while (cin >> x)" step. Whenever I run it from the command line it just sits there mocking me.
Searching through SO and other places gives a lot of mention to hitting ctrl-z then hitting enter to put through an end-of-file character on windows, but that doesn't seem to be working for me. That makes me assume my problem is elsewhere. Maybe defining x as a string is my mistake? Any suggestions about where I'm going wrong here would be great.
Note: sorry for the lack of comments in the code - the program itself is supposed to take in a series of
words and then spit back out the count for each word.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iomanip>
using std::cin;
using std::cout; using std::endl;
using std::sort;
using std::string; using std::vector;
int main()
{
cout << "Enter a series of words separated by spaces, "
"followed by end-of-file: ";
vector<string> wordList;
string x;
while (cin >> x)
wordList.push_back(x);
typedef vector<string>::size_type vec_sz;
vec_sz size = wordList.size();
if (size == 0) {
cout << endl << "This list appears empty. "
"Please try again." << endl;
return 1;
}
sort(wordList.begin(), wordList.end());
cout << "Your word count is as follows:" << endl;
int wordCount = 1;
for (int i = 0; i != size; i++) {
if (wordList[i] == wordList[i+1]) {
wordCount++;
}
else {
cout << wordList[i] << " " << wordCount << endl;
wordCount = 1;
}
}
return 0;
}
If you're on windows ^Z has to come as the first character after a newline, if you're on a unixy shell then you want to type ^D.
The input portion of your code works. The only real problem I see is with the loop the tries to count up the words:
for (int i = 0; i != size; i++) {
if (wordList[i] == wordList[i+1]) {
The valid subscripts for wordList run from 0 through size-1. In the last iteration of your loop, i=size-1, but then you try to use wordList[i+1], indexing beyond the end of the vector and getting undefined results. If you used wordList.at(i+1) instead, it would throw an exception, quickly telling you more about the problem.
My guess is that what's happening is that you're hitting Control-Z, and it's exiting the input loop, but crashing when it tries to count the words, so when you fix that things will work better in general. If you really can't get past the input loop after fixing the other problem(s?), and you're running under Windows, you might try using F6 instead of entering control-Z -- it seems to be a bit more dependable.
I pretty much always use getline when using cin (particularly when what I want is a string):
istream& std::getline( istream& is, string& s );
So, you'd call getline(cin, x) and it would grab everything up to the newline. You have to wait for the newline for cin to give you anything anyway. So, in that case, your loop would become:
while(getline(cin, x))
wordList.push_back(x);
cin does not accept blank space or line breaks so execution of cin does not complete unless you enter something , here is a test program that gives you what you want
#include "stdafx.h"
#include<iostream>
#include <string>
#include <sstream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
string str = "";
while(std::getline(cin, str) && str!="")
{
cout<<"got "<<str<<endl;
}
cout<<"out"<<endl;
cin>>str;
return 0;
}