creating input stream manipulator - c++

As an exercise, I'm trying to create a input stream manipulator that will suck up characters and put them in a string until it encounters a specific character or until it reaches eof. The idea came from Bruce Eckel's 'Thinking in c++' page 249.
Here's the code I have so far:
#include <string>
#include <iostream>
#include <istream>
#include <sstream>
#include <fstream>
#include <iomanip>
using namespace std;
class siu
{
char T;
string *S;
public:
siu (string *s, char t)
{
T = t;
S = s;
*S = "";
}
friend istream& operator>>(istream& is, siu& SIU)
{
char N;
bool done=false;
while (!done)
{
is >> N;
if ((N == SIU.T) || is.eof())
done = true;
else
SIU.S->append(&N);
}
return is;
}
};
and to test it....
{
istringstream iss("1 2 now is the time for all/");
int a,b;
string stuff, zork;
iss >> a >> b >> siu(&stuff,'/');
zork = stuff;
}
the idea being that siu(&stuff,'/') will suck up characters from iss until it encounters the /. I can watch it with the debugger as it gets the characters 'n' 'o' 'w' through '/'
and terminates the loop. It all seems to be going swimingly until I look at Stuff. Stuff has the characters now etc BUT there are 6 extra characters between each of them. Here's a sample:
&stuff 0x0012fba4 {0x008c1861 "nÌÌÌýoÌÌÌýwÌÌÌýiÌÌÌýsÌÌÌýtÌÌÌýhÌÌÌýeÌÌÌýtÌÌÌýiÌÌÌýmÌÌÌýeÌÌÌýfÌÌÌýoÌÌÌýrÌÌÌýaÌÌÌýlÌÌÌýlÌÌÌý"}
What's going on?

This line:
SIU.S->append(&N);
appends the character as a char *. The append function is expecting a null terminated string, so it keeps reading from &N, (&N)+1... until it sees a zero byte.
You can either make up a small null terminated char array and pass that in, or you can use the an alternate append function that takes a count and a character to append:
SIU.S->append(1, N);

Related

C++ I want fscanf to ignore newline characters but not other whitespace characters

In my program I want to read data from a file character by character and store them somewhere but I want to ignore newline characters. Ive been trying to find a solution to this all day. When I leave a space before the %c it ignore all whitespaces when I use stuff like fscanf(fp, "%*[\n]", ch); I cant get it to continue reading from the next line. Or it only reads last line for some reason. Can someone please help me?
Since this is supposed to be a C++ question how about iostream/boost::...::filter_istream solution ? It gives you the full input capacity of iostreams (number pasring etc.)
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/concepts.hpp>
#include <iostream>
#include <fstream>
static const int NL = 0xa;
class nl_input_filter : public boost::iostreams::input_filter {
public:
template<typename Source>
int get(Source& src) {
int c;
while ((c = boost::iostreams::get(src)) != EOF && c != boost::iostreams::WOULD_BLOCK) {
if(c != NL)
break;
}
return c;
}
};
int main()
{
std::ifstream fi("/tmp/bla");
boost::iostreams::filtering_istream in;
std::string s;
in.push(nl_input_filter());
in.push(fi);
while ( in >> s )
{
std::cerr << s << std::endl;
}
}

C++ Cin input to array

I am a beginner in c++ and I want to enter a string as character by character into an array , so that I can implement a reverse function .. However unlike C when the enter is hit a '\n' is not insterted in the stream.. how can I stop data from being entered ?
my code is :
#include<iostream>
#include<array>
#define SIZE 100
using namespace std;
char *reverse(char *s)
{
array<char, SIZE>b;
int c=0;
for(int i =(SIZE-1);i>=0;i--){
b[i] = s[c];
c++;
}
return s;
}
int main()
{
cout<<"Please insert a string"<<endl;
char a[SIZE];
int i=0;
do{
cin>>a[i];
i++;
}while(a[i-1]!= '\0');
reverse(a);
return 0;
}
When you read character by character, it really reads characters, and newline is considered a white-space character.
Also the array will never be terminated as a C-style string, that's not how reading characters work. That means your loop condition is wrong.
To begin with I suggest you start using std::string for your strings. You can still read character by character. To continue you need to actually check what characters you read, and end reading once you read a newline.
Lastly, your reverse function does not work. First of all the loop itself is wrong, secondly you return the pointer to the original string, not the "reversed" array.
To help you with the reading it could be done something like
std::string str;
while (true)
{
char ch;
std::cin >> ch;
if (ch == '\n')
{
break; // End loop
}
str += ch; // Append character to string
}
Do note that not much of this is really needed as shown in the answer by Stack Danny. Even my code above could be simplified while still reading one character at a time.
Since you tagged your question as C++ (and not C) why not actually solve it with the modern C++ headers (that do exactly what you want, are tested, save and work really fast (rather than own functions))?
#include <string>
#include <algorithm>
#include <iostream>
int main(){
std::string str;
std::cout << "Enter a string: ";
std::getline(std::cin, str);
std::reverse(str.begin(), str.end());
std::cout << str << std::endl;
return 0;
}
output:
Enter a string: Hello Test 4321
1234 tseT olleH

Parsing and turning a string into a number

I have an input file which I'm reading in with the basic myFile >> variable since I know the format and the format will always be correct. The file I'm reading in is formatted as instruction <num> <num> and to make >> work, I'm reading everything in as a string. If I have 3 variables, one to take in each piece of the line, how can I then turn string <1> (for example) into int 1? I know the string's first and last characters are brackets which need to be removed, then I could cast to an int, but I'm new to C++ and would like some insight on the best method of doing this (finding and removing the <>, then casting to int)
use stringstream
#include <string>
#include <sstream>
#include <iostream>
int main() {
std::string str = "<1>";
int value;
std::stringstream ss(str);
char c;
ss >> c >> value >> c;
std::cout << value;
}
First to get the middle character out you can just do char myChar = inputString.at(1);. Then you can do int myInt = (int)myChar;
Even if you remove the <> characters, your still importing the file content into a string using >> so you still need to cast it to an int. If you have only 1 value, you can follow what Nicholas Callahan wrote in the previous answer, but if you have multiple characters you want to read as int, you dont have a choice but to cast.
You can also resort to sscanf.
#include <cstdio>
#include <iostream>
#include <string>
int main()
{
std::string str = "<1234>";
int value;
sscanf(str.c_str(), "<%d>", &value);
std::cout << value << std::endl;
}

How to read the whole lines from a file (with spaces)?

I am using STL. I need to read lines from a text file. How to read lines till the first \n but not till the first ' ' (space)?
For example, my text file contains:
Hello world
Hey there
If I write like this:
ifstream file("FileWithGreetings.txt");
string str("");
file >> str;
then str will contain only "Hello" but I need "Hello world" (till the first \n).
I thought I could use the method getline() but it demands to specify the number of symbols to be read. In my case, I do not know how many symbols I should read.
You can use getline:
#include <string>
#include <iostream>
int main() {
std::string line;
if (getline(std::cin,line)) {
// line is the whole line
}
}
using getline function is one option.
or
getc to read each char with a do-while loop
if the file consists of numbers, this would be a better way to read.
do {
int item=0, pos=0;
c = getc(in);
while((c >= '0') && (c <= '9')) {
item *=10;
item += int(c)-int('0');
c = getc(in);
pos++;
}
if(pos) list.push_back(item);
}while(c != '\n' && !feof(in));
try by modifying this method if your file consists of strings..
Thanks to all of the people who answered me. I made new code for my program, which works:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(int argc, char** argv)
{
ifstream ifile(argv[1]);
// ...
while (!ifile.eof())
{
string line("");
if (getline(ifile, line))
{
// the line is a whole line
}
// ...
}
ifile.close();
return 0;
}
I suggest:
#include<fstream>
ifstream reader([filename], [ifstream::in or std::ios_base::in);
if(ifstream){ // confirm stream is in a good state
while(!reader.eof()){
reader.read(std::string, size_t how_long?);
// Then process the std::string as described below
}
}
For the std::string, any variable name will do, and for how long, whatever you feel appropriate or use std::getline as above.
To process the line, just use an iterator on the std::string:
std::string::iterator begin() & std::string::iterator end()
and process the iterator pointer character by character until you have the \n and ' ' you are looking for.

Reading a full line of input

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;
}