#include <iostream>
#include <cstring>
using namespace std;
const int BUFFER_SIZE = 80;
void getstr(char* &str);
int main()
{
char* str;
while(true)
{
getstr(str);
if (!strlen(str))
break;
}
delete [] str;
return 0;
}
void getstr(char* &str)
{
char temp[BUFFER_SIZE];
cout<<"Enter a string(empty line to quit): ";
cin.get(temp, BUFFER_SIZE);
while(cin.get()!='\n')
continue;
str = new char [strlen(temp)+1];
strcpy(str, temp);
}
I have a string reading loop above and entering an empty line to terminate the loop doesn't work(after entering an empty line program stops responding to any input). But when I replace a loop in getstr with single cin.get() all works fine. What's wrong?
istream::get() sets failbit when empty string is read.
This makes cin.get() return EOF and this because you couldn't break the loop while(cin.get()!='\n').
You can use ios::clear() to clear failbit.
cin.get(temp, BUFFER_SIZE);
cin.clear(); // add this
while(cin.get()!='\n')
continue;
cin.get(char* s, size_t n) Extracts characters from the stream and stores them in s as a c-string, until either (n-1) characters have been extracted or the delimiting character is encountered: the delimiting character being either the newline character ('\n') or delim (if this argument is specified).
The delimiting character is not extracted from the input sequence if found and remains there as the next character to be extracted from the stream (see getline for an alternative that does discard the delimiting character).
A null character ('\0') is automatically appended to the written sequence if n is greater than zero, even if an empty string is extracted.
So here is the problem. cin.get() need to read at least 1 character. You can close stdin by pressing Ctrl+D and Enter, after that, your program will be finished.
And BTW, you are using new N times, but you have only 1 delete. You need to delete the previous buffer
If you are going to use C++, you should really use cin/cout in an objectively consistent manner. For example:
string name;
cout << "What is your name: ";
getline (cin, name);
cout << "Your name is: " << name;
What you are doing is kind of a C/C++ hybrid (char arrays in leu of string objects, but using std namespace).
Now, I know this isn't your question, but what you are doing right now is slightly unorthodox which makes answering your question a bit difficult without putting the code in to and editor and debugging it.
Given the c++11 tag, I assume that you really want C++ code. The great thing is that C++ simplifies this a lot.
#include <iostream>
#include <string>
int main()
{
std::string str;
while(std::getline(std::cin, str) && !str.empty())
{
// do stuff
}
return 0;
}
Related
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
I have been trying to implement a simple code which takes a sentence as an input from the user, stores it in a string and displays it back.
Here are the issues:
1. When T = 1, the program exits immediately.
2. When T>1, the loop runs for only T-1 times.
I think the usage of cin to store the value of T is an issue here. Is the value of T entered being stored as a string due to some buffer capacity of cin?
#include <iostream>
#include <string>
int main()
{
int T;
std::cin >> T;
while (T--)
{
std::string song;
getline(std::cin, song);
std::cout << song << std::endl;
}
return 0;
}
How do you terminate the input that becomes T? With a newline. What happens with that newline after you read into T? It's still left in the input buffer. What will happen when you next call std::getline, what is the first character it will read? The newline, and what happens next? The loop iterates and then T is zero (for the first case where T was originally 1) and the loop and then the program exits.
The solution to this problem is to ignore characters up to and including the newline.
Add a getchar after cin as the \n after the input of T stays in buffer.
std::cin >> T;
getchar();
This is a strange way to do it. So you ask the user to tell the program, before any other input, how many lines will follow? Why not simply:
std::string s;
while (getline(std::cin, s)) {
std::cout << s << std::endl;
}
(This will simply echo every line (press enter to end the line) until end-of-file (Ctrl-d).
Either way, the problem with your code is the while (T--): so why don't you try to see what your T is, and what your getline gives you on each iteration? (I will let you figure it out on your own). Why not use the idiomatic:
for (int i = 0; i < T; ++i)
?
P.S. If you want to read sentences, and not lines, you might want to consider reading up to a delimiter (for example .). getline will do that for you, too:
getline(std::cin, s, '.');
My question is based on this simple code:
#include <string>
using namespace std;
int main() {
string buf;
while (cin >> buf && !buf.empty()) {
cout << "input is " << buf << "\n";
}
return 0;
}
The operator>> of cin (which is an object of type basic_istream) reads and discards any leading whitespace (e.g. spaces, newlines, tabs). Then operator>> reads characters until the next whitespace character is encountered. The operators returns finally the stream itself, cin.
It shouldn't be possible to enter an empty string without also setting at least one of the iostates eof, fail or bad? And therefore the streams converts with the operator bool to false. I think !buf.empty() is here superfluous, but a good habit. Is there a way to leave the iostate of cin in good and leaving the string empty?
Example usage:
1. type in a word of your choice
2. press enter
3. press Ctrl+d (EOF on UNIX) or Ctrl+d (EOF on Windows)
Thank you
No, it is not possible. If no characters could be extracted std::ios::failbit is set. [string.io]/3:
If the function extracts no characters, it calls
is.setstate(ios::failbit), which may throw ios_base::failure.
And if characters could be extracted they are subsequently appended to the string and thereby make its size non-zero.
Somehow when I run this code and it comes to inputting strings, the first string where i=0 is being skipped and it starts entering strings from A[1]. So I end up with A[0] filled with random stuff from memory. Can someone please point at the problem?
cin>>s;
char** A;
A = new char *[s];
cout<<"now please fill the strings"<<endl;
for (int i=0;i<s;i++)
{
A[i] = new char[100];
cout<<"string "<<i<<": ";
gets(A[i]);
}
That code is horrible. Here's how it should look like in real C++:
#include <string>
#include <iostream>
#include <vector>
int main()
{
std::cout << "Please start entering lines. A blank line or "
<< "EOF (Ctrl-D) will terminate the input.\n";
std::vector<std::string> lines;
for (std::string line; std::getline(std::cin, line) && !line.empty(); )
{
lines.push_back(line);
}
std::cout << "Thank you, goodbye.\n";
}
Note the absence of any pointers or new expressions.
If you like you can add a little prompt print by adding std::cout << "> " && at the beginning of the conditional check in the for loop.
Probably because you're using gets()... never use gets()
Use fgets() instead.
gets vs fgets
The problem is that cin>>s; just picks up the number you want and leaves a \n (newline from the enter press) on stdin that gets() picks up in the first iteration. This is not the nicest way to fix it, but to prove it write this line after that line:
int a = fgetc(stdin);
Check out a afterwards to confirm it has a newline.
Well, you probably get an empty string: when reading s you use formatted input which stops as soon as a non-digit is encountered, e.g., the newline used to indicate its input is finished. gets(), thus, immediately finds a newline, terminating the first string read.
That said, you shall never use gets(): It is a primary security problem and the root cause of many potential attack! You should, instead, use fgets() or, better, yet, std::getline() together with std::strings and a std::vector<std::string> >. Aslo, you should always verify that the attempt to input was successful:
if ((std::cin >> s).ignore(std::numeric_limits<std::streamsize>::max(), `\n`)) {
std::string line;
for (int i(0); i != s && std::getline(std::cin, line); ) {
A.push_back(line);
}
}
I'm having an unpleasant problem with my c++ example. Everything works fine until I enter something with a whitespace.
#include <iostream>
using namespace std;
int main (int argc, char * const argv[])
{
int iteration = 0;
while (true) {
char * input = new char[256];
scanf("%s", input);
cout << ++iteration << ": " << input << endl;
cin.get();
}
return 0;
}
So with this code, I can enter anything, but everything after whitespace is somehow like stored in buffer and used in the second iteration.
foo
1: foo
bar
2: bar
foobar
3: foobar
foo bar
4: foo
5: bar
Every single input reading function acts like this and it's driving me crazy. cin >> input, freads(), cin.get() etc. all do this.
It this frequent problem with user input, or am I doing something wrong here?
First of all, never use scanf. It's difficult to use that function and avoid buffer overflows. Replace input with a std::string, and read from std::cin.
Both scanf("%s", input) and cin >> input will read one word, delimited by whitespace. If you want to read a whole line, then use getline(cin, input).
About scanf %s format specifier:
This will read subsequent characters until a whitespace is found (whitespace characters are considered to be blank, newline and tab).
About istream::operator>> with str parameter:
Extraction ends when the next character is either a valid whitespace or a null character, or if the End-Of-File is reached.
So yes, this is standard behaviour for these functions.
Maybe try using std::getline instead?
http://www.cplusplus.com/reference/string/getline/