I would like my program to read from stdin until EOF, print all input, and repeat. I tried clearing the EOF state of stdin as follows:
#include <string>
#include <iostream>
#include <iterator>
using namespace std;
int main() {
cin >> noskipws;
while (1) {
printf("Begin");
istream_iterator<char> iterator(cin);
istream_iterator<char> end;
string input(iterator, end);
cout << input << endl;
cin.clear();
}
}
After the first input is received and printed, however, the program just infinitely prints "Begin" without waiting for further input.
The approach you're taking there won't work - when 'cin' gives you end-of-file in the context you're using, then cin is closed.
For your stated purpose of "reading text until eof, then doing it again", sorry for missing the nuance of this previously, but if you clone the stdin file descriptor and then use the clone, you can continue reading from these additional file descriptors.
Cloning iostreams isn't easy. See How to construct a c++ fstream from a POSIX file descriptor?
It's a little c-like, but this code will drain one copy of stdin until that stdin closes, then it'll make a new copy and drain that, and on.
#include <iostream>
#include <string>
void getInput(std::string& input)
{
char buffer[4096];
int newIn = dup(STDIN_FILENO);
int result = EAGAIN;
input = "";
do {
buffer[0] = 0;
result = read(newIn, buffer, sizeof(buffer));
if (result > 0)
input += buffer;
} while (result >= sizeof(buffer));
close(newIn);
return input;
}
int main(int argc, const char* argv[])
{
std::string input;
for (;;) {
getInput(input);
if (input.empty())
break;
std::cout << "8x --- start --- x8\n" << input.c_str() << "\n8x --- end --- x8\n\n";
}
}
That is because you have printf("begin"); inside your loop so you are going to get it printed again each time round the loop.
The loop will not wait for input so each time it reads data from stdin - if there is nothing there it immediately gets EOF and so continues looping until some data is present.
Let me know if this doesn't make sense - or if I got it totally wrong.
eg:
#include <string>
#include <iostream>
#include <iterator>
using namespace std;
int main() {
cin >> noskipws;
printf("Begin");
while (1) {
istream_iterator<char> iterator(cin);
istream_iterator<char> end;
string input(iterator, end);
cout << input << endl;
cin.clear();
}
}
Related
I am learning how to read and write from file . There is a problem that when I try to write (--something in the file letter for example--) after reading or read after writing in the file
using fstream
something wrong is happening. I tried to just write or read and it worked. what is the problem?
the file content is :
abcdefgh
ijklmnopqr
stuvw
xyz
and the code is :
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
fstream ioFile;
char ch;
ioFile.open("search.txt", ios::in | ios::out);
if (!ioFile)
{
cout << "problem opening the file";
goto k270;
}
while (ioFile>>ch)
{
if (ch == 'z')
{
ioFile.seekp(((int)ioFile.tellg()));
ioFile << "x";
}
}
//cout<<ioFile.rdbuf();
ioFile.close();
k270:
system("pause");
return 0;
}
Look at this answer: https://stackoverflow.com/a/17567454/11829247 it explains the error you are experiencing.
Short version: Input and output is buffered and interleaving reads and writes only work if you force buffer updates in between.
This works for me:
#include <iostream>
#include <fstream>
#include <string>
int main()
{
std::fstream ioFile;
char ch;
ioFile.open("search.txt", std::ios::in | std::ios::out);
if (!ioFile)
{
std::cout << "problem opening the file";
return 1;
}
while (ioFile >> ch)
{
if (ch == 'z')
{
ioFile.seekp(-1, std::ios_base::cur);
ioFile << "x";
ioFile.flush();
}
}
ioFile.close();
return 0;
}
The difference is that I use ioFile.seekp(-1, std::ios_base::cur); to move one step back from the current position. You could also use ioFile.seekp((int)ioFile.tellg() -1); - note the -1.
Then after stepping back and overwriting the z, use ioFile.flush(); to force the write to be pushed to file. This also means that the read buffer is updated, without this the read operation just steps back in its buffer and keeps reading the same buffered z.
I am trying to bind input stream with a file stream , I hope that input something from input stream and then automatic flush to the file stream
It does not work...I enter something from keyboard , outfile is still empty
#include <iostream>
#include <fstream>
#include <stdexcept>
using namespace std;
int main(int argc, char const *argv[])
{
ofstream outfile("outfile" , ofstream::app | ofstream::out);
if(!outfile)
throw runtime_error("Open the file error");
ostream * old_tie = cin.tie();//get old tie
cin.tie(0);//unbind from old tie
cin.tie(&outfile);//bind new ostream
string temp;
while(cin >> temp)
{
if(temp == ".")//stop input
break;
}
cin.tie(0);
cin.tie(old_tie);// recovery old tie
return 0;
}
Your program is too complicated and is misusing tie(). Try the following:
#include <iostream>
#include <fstream>
int main() {
using namespace std;
ofstream outfile("outfile" , ofstream::app | ofstream::out);
if(!outfile) {
cerr << "Open the file error";
return 1;
}
char data(0);
while(data != '.') {
cin.get(data);
cin.clear(); // Prevents EOF errors;
outfile << data;
}
return 0;
}
It reads char by char until it finds a .
Errors:
why make throw exception if you don't catch it...
close file please
do you put data from file to temp and go through it to find "." and
end program?
Why do you use pointer for old_tie use it for the first ofstream file
like this ofstream * file.
fix if statement and break
include string library -- //This might solve your problem
what is filename??
is tie(0) function to unbind?
//EDIT
Explanation:
once you find first period with find_first_of function you create a substr and copy it into outfile. The Solution is so efficent and works every time. The logic is as simple as it can get. Don't use unnecessary functions and initialize unnecessary variables because it is more complex and more prone to errors when you have too many variables.
Solution: - No need for cin.tie()
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(int argc, char const *argv[])
{
ofstream outfile("outfile" , ofstream::app | ofstream::out);
string s;
getline(cin, s);
int i = s.find_first_of(".");
if(i!=std::string::npos)
{
s = s.substr(0, i);
outfile << s;
}
else
{
cout << "No periods found" << endl;
}
}
Compiled code - http://ideone.com/ooj1ej
If this needs explanation please ask questions in comments below.
#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.
I am working on a small program that takes a input file and processors the data in the file. With my current code (see below) when you enter a valid file name it just freezes the command line (drops down a line and just shows a flashing _ ) and I have to kill the program to get out. If you enter a invalid file name the if(!file) gets called and runs fine.
Whats really odd is that if I put a debugging cout above that if statement it will not get called if the file name is correct. Hope you can help and if you need more info let me know!
This is my current code:
using namespace std;
#include <iostream>
#include <stdexcept>
#include <string>
#include <fstream>
#include <vector>
#include <cctype>
#include "Student.h"
int main(){
string filename, name;
char *inputfile;
ifstream file;
vector<Student> students;
const int SIZE = 200;
char buffer [SIZE];
int regno, i;
cout << "Enter file name: ";
cin >> filename;
inputfile = const_cast<char*> (filename.c_str());
file.open(inputfile);
if (!file){
cout << "Failed to open " << filename << endl;
exit(1);
}
while (!file.eof()){
file.getline(buffer, SIZE);
i = 0;
regno = 0;
while (isdigit(buffer[i])){
regno = (regno*10)+buffer[i];
}
cout << regno;
}
file.close();
}
Your problems is that you never increase i in the cycle.
Here:
i = 0;
regno = 0;
while (isdigit(buffer[i])){
regno = (regno*10)+buffer[i];
}
You go into infinite cycle as i always stays 0.
Also why do you do the const_cast? You can open using a const char * too. So you can write this:
cin >> filename;
file.open(filename.c_str());
And code will still work.
There's another problem in your code concerning the use of getline() and eof(). The idiomatic way to read a file line-by-line is this:
std::string line;
while(getline(in, line)) {
// handle line here
}
in refers to some input stream like a std::ifstream or std::cin. The point is that reading a line can fail (e.g. due to EOF), which you check in above loop. Your version only checks if EOF was encountered before but not that the subsequent getline() call actually yielded any data.
I'm trying to store the input that user enters through console. so I need to include the "enter" and any white space.
But cin stops giving me input after the first space.
Is there a way to read whole lines until CTRL+Z is pressed, or something?
is there a way like readLines till CTRL+Z is pressed or something ??
Yes, precisely like this, using the free std::getline function (not the istream method of the same name!):
string line;
while (getline(cin, line)) {
// do something with the line
}
This will read lines (including whitespace, but without ending newline) from the input until either the end of input is reached or cin signals an error.
#include <iostream>
#include <string>
using namespace std;
int main()
string s;
while( getline( cin, s ) ) {
// do something with s
}
}
For my program, I wrote the following bit of code that reads every single character of input until ctrl+x is pressed. Here's the code:
char a;
string b;
while (a != 24)
{
cin.get(a);
b=b+a;
}
cout << b;
For Ctrl+z, enter this:
char a;
string b;
while (a != 26)
{
cin.get(a);
b=b+a;
}
cout << b;
I can't confirm that the ctr+z solution works, as I'm on a UNIX machine, and ctrl+z kills the program. It may or may not work for windows, however; You'd have to see for yourself.
#include <string>
#include <iostream>
int main()
{
std::cout << "enter your name: ";
std::string name;
std::getline(std::cin, name);
return 0;
}
You can use the getline function in c++
#include<iostream>
using namespace std;
int main()
{
char msg[100];
cin.getline(msg,100);
return 0;
}