I just started learning C++. I was just playing around with it and came across a problem which involved taking input of a string word by word, each word separated by a whitespace. What I mean is, suppose I have
name place animal
as the input. I want to read the first word, do some operations on it. Then read the second word, do some operations on that, and then read the next word, so on.
I tried storing the entire string at first with getline like this
#include<iostream>
using namespace std;
int main()
{
string t;
getline(cin,t);
cout << t; //just to confirm the input is read correctly
}
But then how do I perform operation on each word and move on to the next word?
Also, while googling around about C++ I saw at many places, instead of using "using namespace std" people prefer to write "std::"
with everything. Why's that? I think they do the same thing. Then why take the trouble of writing it again and again?
Put the line in a stringstream and extract word by word back:
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
string t;
getline(cin,t);
istringstream iss(t);
string word;
while(iss >> word) {
/* do stuff with word */
}
}
Of course, you can just skip the getline part and read word by word from cin directly.
And here you can read why is using namespace std considered bad practice.
(This is for the benefit of others who may refer)
You can simply use cin and a char array. The cin input is delimited by the first whitespace it encounters.
#include<iostream>
using namespace std;
main()
{
char word[50];
cin>>word;
while(word){
//Do stuff with word[]
cin>>word;
}
}
getline is storing the entire line at once, which is not what you want. A simple fix is to have three variables and use cin to get them all. C++ will parse automatically at the spaces.
#include <iostream>
using namespace std;
int main() {
string a, b, c;
cin >> a >> b >> c;
//now you have your three words
return 0;
}
I don't know what particular "operation" you're talking about, so I can't help you there, but if it's changing characters, read up on string and indices. The C++ documentation is great. As for using namespace std; versus std:: and other libraries, there's already been a lot said. Try these questions on StackOverflow to start.
Related
#include<iostream>
using namespace std;
int main() {
string str;
gets_s(str);
cout << str << endl;
return 0;
}
When I tried to run the above code it threw an error that no instance of gets_s() matched the argument list.
How can I pass an std::string instead of a char[] to gets_s() function if is possible?
The C function get_s takes a char* and a length argument, not a std::string.
Your best options are:
Formatted input:
std::cin >> str;
Read a line:
std::getline(std::cin, str);
Don't do that. Use the stream in a normal way:
#include<iostream>
using namespace std;
int main()
{
string str;
cin >> str;
cout << str << endl;
return 0;
}
gets_s has a significant limitation in that you must provide an upper limit on the number of characters you want to read.
Since you are using string the superior alternative is to use getline
#include <iostream>
#include <string>
using namespace std;
string str;
getline(cin, str);
This will expand the string to hold as many characters as are entered by the user.
gets_s() takes two arguments: pointer to char array and maximal size (your call is missing it). You cannot pass std::string - only C style strings.
Instead of C functions, why not use C++ way std::cin >> str or getline(std::cin, str)?
In C also don't use gets_s() (it's optional in C11) or gets() - use fgets() instead.
Well, there are a lot of answers about std::getline, but in case if you really need to use get_s, you may write such code:
size_t length = 10; // Just for example
std::string my_string(length, 0);
get_s(&my_string[0], length); // C++14 and older
get_s(my_string.data(), length); // C++17 and newer
note: I just learned about Getline and Streams.
Instead of a space separating first name, last name, and age, how could I separate them with ^ or --?
Is there a function for this? Is this a stupid question, and if so, why?
-The reason for this question is because I was going to make a function for solving polynomial derivatives and failed miserably.
int main() {
istringstream inSS; // Input string stream
string lineString; // Holds line of text
string firstName;
string lastName;
int userAge;
getline(cin, lineString);
inSS.str(lineString);
inSS >> firstName;
inSS >> lastName;
inSS >> userAge;
return 0;
}
The free function getline also offers to have a custom delimiter like user4581301 said. However, it will only extract strings and you also have int.
A similar solution can be found in this answer and I have modified the code to fit your needs: changing the delimiter for cin (c++)
You can use imbue to have some custom delimiter. A simple example is below:
#include <locale>
#include <iostream>
template<char Delim>
struct alternativeDelimiter : std::ctype<char> {
alternativeDelimiter() : std::ctype<char>(get_table()) {}
static mask const* get_table()
{
static mask rc[table_size];
rc[Delim] = std::ctype_base::space;
return &rc[0];
}
};
int main() {
using std::string;
using std::cin;
using std::locale;
cin.imbue(locale(cin.getloc(), new alternativeDelimiter<'^'>));
string word;
while(cin >> word) {
std::cout << word << "\n";
}
}
imbue does take ownership of the ctype, so no worries about calling delete yourself.
If you input some^text, the output will be
some
text
You can also use it with your example, of course.
If you extend the table by writing lines similar to line 11 (rc[Delim] = std::ctype_base::space) only changing Delim, you can have multiple characters that will be interpreted as space.
I am not sure in how far this solves your original problem of writing a math parser, though. The general terminology involves the concepts "parser" and "lexer" and you might research these concepts to build a reliable math solver. Hope it helps, too.
How this program should work:
Enter 4 words:
this is bad
Bad input.
and
Enter 4 words:
hello you love it
Good input.
How I tried it:
#include <iostream>
#include <string>
using namespace std;
int main(void) {
cout << "Enter 4 words:" << endl;
string a, b, c, d;
cin >> a >> b >> c >> d;
}
It reads input after end of the line and I can't figure out how to limit it only to one line. Can you please point me what function I should use? I'll be very grateful for every answer.
Thank you all!
std::getline() should be used when the program's expected input comes from an interactive terminal.
That's what std::getline() does: it reads text until the newline character. operator>> doesn't do that, that's what std::getline() does, and that's what should be used to process a line of typed-in text. Use the right tool, for the right job.
Sadly, many C++ books and tutorials introduce >> too early, before introducing std::getline(), and use it in their examples, simply because it's easier and more convenient to have >> handle the required data type conversion. Unfortunately, this results in a wrong mindset settling in, where >> is thought to be the automatic choice for processing interactive input. It is not.
The correct approach is to use std::getline(). Then, if necessary, construct a std::istringstream, and use that to handle any type conversions from the entered input. Not only does that solve the immediate problem, it also solves the problem of unparsable input putting std::cin into a failed state, with all subsequent attempted input conversions failing as well -- that's another common pitfall.
So, use std::getline(), first:
#include <string>
#include <iostream>
#include <sstream>
#include <vector>
int main(void) {
std::cout << "Enter 4 words:" << endl;
std::string line;
std::getline(std::cin, line);
And now, once the line of text is entered, it can be converted to a std::istringstream:
std::istringstream i(line);
Followed by a loop to repeatedly invoke >> in order to count the words in this line. This part you can finish yourself.
P.S. Another common pitfall is using namespace std;. You should not do that, as well. The earlier good programming practices are acquired, the easier the subsequent road on the path towards C++ guru-ism will be.
You should use following command:
std::getline()
This ignore the eventual space as a quote terminating string and you can store the value inside a variable, then see how much words are inside that.
Example:
std::getline (std::cin,name);
#include <iostream>
#include <string.h>
#include<stdio.h>
using namespace std;
int main()
{
char d,a[9],e[9];
cin.getline(a,9);
cin.getline(e,9);
cin>>d;
puts(a);
puts(e);
cout<<d<<endl;
return 0}
when i enter "hey every one" on the output screen, puts(e) prints a blank line and d prints a random character.second getline function and cinfunction is not working because of first getline. Thanks in advance.
You should read some documentation for the stuff you use:
After constructing and checking the sentry object, extracts characters from *this and stores them in successive locations of the array whose first element is pointed to by s, until any of the following occurs (tested in the order shown):
- [...]
- count-1 characters have been extracted (in which case setstate(failbit) is executed).
(Emphasize mine)
So the first getline fails if the input is too long and thus leaves std::cin in a bad (i.e. unreadable) state. This makes all successive input operations fail immediately.
Remark: To avoid tons of ugly trouble, you should avoid using C-style strings and the "kind of C-style" member-getline and just use std::string and the non-member std::getline instead.
When you use
cin.getline();
and when you press Enter after entering the string, that enter goes into the next string.
In order to prevent it, use
cin.ignore();
It ignores the Enter and prevents it from entering into another string.
Here is your modified code:
#include<iostream>
#include <cstring>
using namespace std;
int main()
{
char d,a[9],e[9];
cout<<"String:"<<endl;
cin.getline(a,9);
cin.ignore();
cout<<"String:"<<endl;
cin.getline(e,9);
cin>>d;
cout<<a;
cout<<e;
cout<<d<<endl;
return 0;
}
I would like to << stream to save all inputs from console into a file
Here is how I tried
ofstream of("file.txt");
while(1)
{
string str;
cin>>str;
of<<str;
}
I don't see the non-English characters in the file (Edit: I mean they are Japanese, Chinese or Korean etc)
You could stream char by char. Then it would be a true binary copy.
ofstream of("file.txt");
while(1)
{
char c;
cin>>c;
of<<c;
}
Streaming using the formatted extraction operator is a poor choice. Specifically, it will consume all of the white space.
If it were me, I would copy using std::getline or istream::rdbuf:
std::getline:
// Copy standard input to named file, one line at a time.
#include <iostream>
#include <fstream>
int main (int argc, char **argv) {
std::string s;
std::ofstream of(argv[1]);
while(std::getline(std::cin, s)) {
of << s << "\n";
}
}
istream::rdbuf:
// Copy entire standard input stream to named file in one go
#include <iostream>
#include <fstream>
int main (int argc, char **argv) {
std::ofstream(argv[1]) << std::cin.rdbuf();
}
Just a couple of points as a starter:
ofstream of("file.txt");
If you want to see Japanese, Chinese or Korean character you should not be using an ofstream here. You want a stream that writes wide characters: a std::wofstream. You will also haveendow that stream with a locale. See Why does wide file-stream in C++ narrow written data by default? for details.
Another point: You apparently are have a using namespace std;. You can find many questions here at Stack Overflow that indicate that this is a bad idea. Typing those extra five characters isn't very hard, it avoids problems with names from the standard library polluting your namespace, and it makes the code clearer.
while(1)
Your loop doesn't have any break statements to escape the loop, so this plus the while (1) means your program will never stop. It is just going to keep on going and going and going and going. You want it to stop (or should want it to stop) on encountering an error or end of file in the input stream.
A better approach is to use a construct such as
while (std::getline (std::cin, s))
to control the loop (except you need to use something special to get wide characters).