I want to write a program in which the names of n different chemical elements are read in the same line in the input (where 1 ≤ n ≤ 17 and n is also read in the input) (the names are made apart by a space). The names of the chemical elements should be stored in different strings for further uses.
As n is unknown, I don't know how to make something like an "array of strings". Of course I should not make 17 different strings st1,st2,st3,... :D.
Can you please help me? Any help will be high appreciated and they will help me a lot.
Thank you in advance.
It sounds like you want to read in a line and split it with spaces. Try something such as this:
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
int main()
{
std::string input;
std::getline(std::cin, input); // takes one line, stops when enter is pressed
std::stringstream ss(input); // makes a stream using the string
std::vector<std::string> strings;
while (ss >> input) { // while there's data left in the stream, store it in a new string and add it to the vector of strings
strings.push_back(input);
}
for (std::string s : strings) {
std::cout << "string: " << s << std::endl;
}
}
You give input such as H He Li, terminated by hitting enter, and the strings are stored in strings (printed in last loop for demonstration).
Edit:
I now see that you want to read the number n in the input, too. In this case, you don't need the stringstream solution. You can do this instead:
int main()
{
int amount;
std::cin >> amount; // read in the amount
std::vector<std::string> strings;
for (int i = 0; i < amount; i++) {
std::string s;
std::cin >> s; // read in the nth string
strings.push_back(s); // add it to the vector
}
for (std::string s : strings) {
std::cout << "string: " << s << std::endl;
}
}
And pass input such as 3 H He Li.
Related
I want to read string and extract all numbers.
Input: 5a3 1f a0aaaa f1fg3
Output: 53 1 0 13
I tried this code:
string s;
getline(cin, s);
stringstream str_strm(s);
int found;
string temp;
while (!str_strm.eof()) {
str_strm >> temp;
if (stringstream(temp) >> found)
{
cout << found << endl;
}
}
but when found 5 (from example)after that automatically start to check the other string. How can I extract all numbers?
Here's a possible solution - while loop is used to separate strings with whitespaces, after that digits are extracted from the sub-strings.
int main()
{
stringstream ss("5a3 1f a0aaaa f1fg3");
string str;
while (getline(ss, str, ' ') ){
str.erase(std::remove_if(str.begin(), str.end(), [](unsigned char c) { return !std::isdigit(c); }), str.end());
cout << str << " ";
}
}
You could read each space separated word, and then remove the non-digits, like this
std::string word;
while (std::cin >> word)
{
word.erase(std::remove_if(word.begin(), word.end(),
[](unsigned char c) { return not std::isdigit(c); }),
word.end());
std::cout << word << " ";
}
For the input of 5a3 1f a0aaaa f1fg3, it prints 53 1 0 13.
The admittedly odd way of removing elements of a range, is a common idiom.
You could even avoid the loop entirely, if you have the input on a single line
std::string word;
std::getline(std::cin, word);
word.erase(std::remove_if(word.begin(), word.end(),
[](unsigned char c) { return not std::isdigit(c)
and not std::isspace(c); }),
word.end());
std::cout << word;
Please see here the ultra simple example. (There is an even simpler solution at the bottom of this post)
It is using modern C++ elements and algorithms. And has only a few lines of code.
#include <iostream>
#include <string>
#include <regex>
#include <iterator>
#include <algorithm>
#include <sstream>
int main() {
// Read a string from the console
if (std::string line{}; std::getline(std::cin, line)) {
// Put the complete line into a std::istringstream
std::istringstream iss{line};
// Print result
std::transform(std::istream_iterator<std::string>(iss), {}, std::ostream_iterator<std::string>(std::cout, " "),
[](const std::string& s) { return std::regex_replace(s, std::regex{ R"([^\d])" }, ""); });
}
return 0;
}
So, what's going on here. Let us look at it statement by statement. So, first:
if (std::string line{}; std::getline(std::cin, line)) {
This is a if-statement with initializer. If you look up if in the C++ reference, here, then you can see, that we can now have an additional initialization statement as the first part in the if. And why are we using that? Because it is an additional measure for scoping. The variable "line" is only used within the scope of the if statement. It is not needed outside the if. From the functionality point of view, it is the same as writing:
std::string line{};
if (std::getline(std::cin, line)) {
But then, "line" would be also visible outside of the if statement. And, because we want to prevent the pollution of outer namespace, we select this method.
Next is std::getline. This will read a complete line from the input stream, so, from the console (std::cin)and put it into the string. The std::getline returns a reference to the stream. The stream has an overloaded bool operator, that returns, if there was a failure (or end of file) or not. So, the if statement checks, if the input operation works. By the way. All IO-opereations should be checked, if they work or fail.
Good, now we have the complete line of the user input in our variable "line".
With
std::istringstream iss{line};
we put the string into an std::istringstream. We do this, because we want to make use of the C++ "iostream" library. The std::istringstream behaves as any other stream, for example std::cin and you can extract values from it that are separated by a white space. Like in std::cin >> v1 >> v2. The disadvantage for such an approach is, that you need to know the number of values in advance or use a dynamic growing container and a loop.
And this brings ud to our next construct that I want to explain. You may have heard about "iterators". Iterators are like pointers and can point to a range of elements. If you have a std::vector or any other container, then you can iterate with the begin() and end() iterator over all elements in the std::vector without knowing, how many elements are in the std::vector, without knowing how many elements it contains.
And for input streams, we have something similar: The std::istream_iterator. This iterator will iterate over the elements in the std::sitringstream and returns the type of variable given in its template parameter, by repeatedly calling the extractor operator >>. Here, in our case, a std::string. You may know ask: Until when? Where is the end. If you look in the description of the constructor number 1 of the std::istream_operator then you will see, that the default constructor Constructs the end-of-stream iterator. and the default construct can be generated by using the empty braced {} initializer. So {} is the end iterator.
If we want to read all std::strings from the std::istringstream, then we read between
std::istream_iterator<std::string>(iss) and {}. So every string that is in the std::istringstream.
Good, next, there is a similar thing for output, the std::ostream_iterator. This will call the inserter operator "<<" for all elements in a given range. And, we can can specify, to which stream it should send the data, here std::cout and additionally a separator-string, which will be appended to the outputted value.
OK, next: std::transform. As it names says, it will transform the elements in a range of elements, between a begin() and end() iterator, to a other range. So, it will transform the elements as shown above from the std::istringstream and send them to the std::ostream iterator. So, we read the source value, transform it, then write it.
But, how to transform. For the transformation, we give a simple lambda function, which calls the std::regex_replace function. This is a standard function, to replace parts of a string with other string data. And, the what that will be replaced is specified by a std::regex. This is a special pattern that is defined in some kind of meta language and matches specified parts of a string. in our case we use [^\d] which means, not a digit. You can test regexes here. You can also lean about them here.
And now, all together, explains the above solution.
All this can be further optimized to 2 statements:
#include <iostream>
#include <string>
#include <regex>
int main() {
// Read a string from the console
if (std::string line{}; std::getline(std::cin, line)) {
// Remove unnecessary characters
std::cout << std::regex_replace(line, std::regex{ R"([^\d ])" }, "") << "\n";
}
return 0;
}
I cannot think of a more simpler solution.
In case of questions, please ask.
You can use get from istream to get each character, including whitespace, and then isdigit to check for a digit character...
#include <iostream>
#include <cctype>
int main()
{
char ch;
std::cin.get(ch);
while (!std::cin.eof())
{
if (isdigit(ch) || ch == ' ' || ch == '\n')
{
std::cout << ch;
}
std::cin.get(ch);
}
return 0;
}
However, you can avoid using std::cin.eof() for your expression for your While loop as follows...
#include <iostream>
#include <cctype>
int main()
{
char ch;
while (std::cin.get(ch))
{
if (isdigit(ch) || ch == ' ' || ch == '\n')
{
std::cout << ch;
}
}
return 0;
}
Regular expression pattern matching can be used to find all the digits in the input string.
Here is an example program to find the digits:
// C++ program to find all digits in a string
#include <bits/stdc++.h>
using namespace std;
int main() {
string inputString;
cout << "Enter the input string: ";
getline(cin, inputString);
cout << "Digits found: ";
// Define the regular expression matcher and pattern
smatch matcher;
regex pattern("[[:digit:]]");
while (regex_search(inputString, matcher, pattern)) {
// Show the match
cout << matcher.str(0);
// Continue searching the rest of the string
inputString = matcher.suffix().str();
}
return 0;
}
Output:
Enter the input string: sdfh354 eutyt;ljkn756897490uiotureu 587689jkgf 90
Digits found: 35475689749058768990
Here is another approach of finding the numbers in the string, without using the regular expression pattern matching:
#include <iostream>
#include <cctype>
#include <bits/stdc++.h>
using namespace std;
int main() {
string rawInput;
cout <<"Enter input string: ";
getline(cin, rawInput);
// Get all words from the input string
stringstream allWords(rawInput);
// Find and print digits in each word
string word;
while(allWords >> word) {
for(int i = 0; word[i]; i++) {
// Print only the numbers in the word
if(isdigit(word[i])) {
cout<<word[i];
}
}
cout<<" ";
}
cout<<"\n";
return 0;
}
Output:
Enter input string: ghjg45 jsdfj 897897 343yut45 90
45 897897 34345 90
How can I extract all numbers?
When you KNOW that the input numbers are all hex values ... (and how many)
stringstream ss ("5a3 1f a0aaaa f1fg3");
for (int i=0; i<4; ++i)
{
int k;
ss >> hex >> k;
cout << k << endl;
}
with output
1443
31
10529450
3871
I tried to accept N spaced integers, store them in a vector and print them. This is my code:
#include <string>
#include <vector>
using namespace std;
int main() {
string rawInput;
vector<string> numbers;
while( getline( cin, rawInput, ' ' ) )
{
numbers.push_back(rawInput);
}
for (int j = 0; j < sizeof(numbers)/sizeof(numbers[0]); ++j) {
cout << numbers[j] << " ";
}
}
It doesn't work. I get no output after running this code.
Please give an example with floating point numbers and integers. Please tell me how to print them as well. Thank you.
For space separated integers, don't use getline. The newline counts as space when constructing integers.
Try something like this:
std::vector<int> database;
int number;
while (cin >> number)
{
database.push_back(number);
}
You may want ask yourself if there really is a need to read a line of integers (or if any kind of record is delineated by a newline).
Edit 1: Reading space separated integers by text line
If you must read by line, one method is to use std::istringstream:
std::vector<int> database;
std::string text_line;
while (getline(cin, text_line))
{
int number;
std::istringstream line_stream(text_line);
while (line_stream >> number)
{
database.push_back(number);
}
}
IMHO, reading by line adds an unnecessary level of complexity.
I am trying to create an vector <int> whose size is not pre-defined. It should take in numbers as long as there are numbers in the input terminal and should stop reading when I hit Enter. I tried many solutions including the ones given here and here. In the second case, I can enter a non-integer to terminate the input to the vector. If I use the first solution (code added below), it listens to the input indefinitely.
Code:
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <iterator>
using std::cout;
using std::cin;
using std::vector;
using std::string;
using std::istringstream;
int main()
{
//cout << "Enter the elements of the array: \n";
//vector <int> arr ( std::istream_iterator<int>( std::cin ), std::istream_iterator<int>() );
vector <int> arr;
string buf;
cout << "Enter the elements of the array: \n";
while(getline(cin, buf))
{
istringstream ssin(buf);
int input;
while(ssin >> input)
{
arr.push_back(input);
}
}
cout << "The array: \n";
for(size_t i = 0; i < arr.size(); i++)
{
cout << arr[i] << " ";
}
return 0;
}
1) I don't feel that typing in a character or a very large number to end listening to input is very elegant. However, the solution with istringstream seems to be the way to go. I am not sure why it doesn't work.
2) Is there any way to detect the Enter from keyboard to terminate listening to input? I tried using cin.get(), but it changed the numbers in the vector.
3) Any other methods or suggestions?
Let's take things one step at a time.
We want to read up until enter is pressed. That means you probably want to use std:getline to read a line.
Then you want to parse it, so you want to put the line into an istringstream.
Then you want to read numbers. While you're reading them, you apparently want to ignore anything other than digits, and you want to keep reading even if you get to a group of digits that can't be converted to a number.
That leaves a few things that aren't entirely clear, such as what to do with that input that's too large to convert? Do you want to just skip to the next? Do you want to read some digits as a number, then read remaining digits as another number?
Likewise, what do you want to do if you get something like "123a456"? Should it be skipped completely, read as "123" (and the "a456" ignored)? Should it be read as "123" and "456", and just the "a" ignored?
For the moment let's assume that we're going to read space-separated groups of characters, and convert all those to numbers that we can. If something is too big to convert to a number, we'll ignore it (in its entirety). If we have a group like "123a456", we'll read the "123" as a number, and ignore the "a456".
To achieve this, we can do something like this:
std::string line;
std::getline(infile, line);
std::istringstream input(line);
std::string word;
std::vector<int> output;
while (input >> word) {
try {
int i = std::stoi(word);
output.push_back(i);
}
catch (...) {}
}
For example, given input like: "123a456 321 1111233423432434342343223344 9", this will read in [123, 321, 9].
Of course, I'm just taking a guess about your requirements, and I haven't worked at making this particularly clean or elegant--just a straightforward implementation of one possible set of requirements.
Please see the comments from #LearningC and #M.M.
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <iterator>
using std::cout;
using std::cin;
using std::vector;
using std::string;
using std::istringstream;
int main()
{
vector <int> arr;
string buf;
int input;
cout << "Enter the elements of the array: \n";
getline(cin, buf);
istringstream ssin(buf);
while(ssin >> input)
{
arr.push_back(input);
}
cout << "The array: \n";
for(size_t i = 0; i < arr.size(); i++)
{
cout << arr[i] << " ";
}
return 0;
}
So, I have a file that contains a pattern of a string then an int alternating line by line.
Something like this:
John McClane
30
James Bond
150
Indiana Jones
50
In this example, I would set John McClane to a string variable and then 30 to an integer variable. My issue is dealing with two types. I want to use getline(), but that only works with strings.
Is there an efficient or "right" way of doing this?
There are a number of approaches you could try.
Get string input, and convert to an integer if valid
Convert every second string to an integer
Try to read an integer when you expect one (just using cin >> in;). If you want a robust program, you can check validity with cin.good()
I don't know if there is a "right" way of doing this per say, but it's not a very taxing operation, so whatever you choose should be fine.
You could make a variable like this
string ibuf;
Then convert it to an integer doing this
getline(cin, ibuf);
(Whatever your int variable is) = strtol(ibuf.c_str(), NULL, 10);
One thing about C++ is that there are a large number of ways to accomplish any one task. One way to get integers from strings is to use a stringstream. There is a tutorial on stringstreams here
As for your problem with reading the alternating file, consider the following pseudocode:
boolean isInt = false;
while(fileIsNotOver) {
//getline
if(isInt) {
//use stringstream to get int here
} else {
//do whatever with the name here
}
isInt = !isInt;
}
I don't know if this fully works as i didn't tested it however it just compiles fine and answer should be something like this i think.
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;
int main()
{
int counter = 0;
int number;
string test_string;
ifstream myfile ("example.txt");
if (myfile.is_open())
{
while ( getline (myfile,test_string) )
{
cout << test_string << '\n';
++counter;
if(counter % 2 == 0 ){
number = atoi(test_string.c_str());
cout << number << '\n';
}else{
cout << test_string << '\n';
}
}
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
You can try like this to read a string then an int alternating line by line.
#include<iostream>
#include<string>
#include<cstdio>
using namespace std;
int main()
{
string name;
int number;
freopen("input.txt", "r", stdin);
while (getline(cin, name))
{
cin >> number;
/*
process the input here
...
...
*/
getline(cin, name); // just to read the new line and/or spaces after the integer
//getchar(); //you can use getchar() instead of getline(cin, name) if there is no spaces after the integer
}
return 0;
}
Thanks !!!
I'm trying to write a program that keeps taking input from the user until the user enters "quit." Each time the user enters input, I want the program to print out the number of words the user has entered. So the following input on the user's part:
hello how are you
would yield the following output:
You entered 4 words.
However, I am having trouble writing the program so that it counts the number of words on just one line; it doesn't clear the number before going onto the next line. So, if it took input from the user three times, it would add up the total number of words on those three lines. For example, the following input:
how are you
i am good thank you
quit
would yield the following output:
You entered 9 words.
when I want it to output the number of words following each line the user enters (except quit), i.e.
>>how are you
<<You entered 3 words.
>>i am good thank you
<<You entered 5 words.
>>quit
Here's the relevant bit of my code:
char *input;
int inum;
int inputLoop()
{
char quit[] = "quit";
inum = 0; //counts number of words
while (strcmp(input, quit) != 0)
{
cin >> input;
inum++;
}
cout <<"You entered " <<inum <<" words." <<endl;
I'd rather not use something like a vector; whatever I use will need to be converted to a *char eventually because my global variable is a *char. (And my global variable is a *char because, depending on certain conditions, *input may be set to *argv[] from main.)
I've tried all sorts of things, but I just can't seem to get past the fact that strcmp(input, quit) compares one word of the input at a time to quit rather than comparing the entire input line to quit. HELP.
None of your requirements precludes the use of std::string and std::vector. I recommend you use them.
#include <string>
#include <sstream>
#include <iostream>
#include <vector>
std::vector<std::string> words;
int inputLoop()
{
char quit[] = "quit";
total_words = 0;
std::string line;
// grab a line at a time
while(std::getline(std::cin, line) && line != quit) {
// clear the vector of words
words.clear();
// make a string stream to read words from that line
std::stringstream ss(line);
// grab all the words into a vector
std::string word;
while(ss >> word) {
words.push_back(word);
}
std::cout <<"You entered " <<words.size() <<" words." <<endl;
}
}
int main(int argc, char** argv) {
// get the data from argv
words = std::vector<std::string>(argv, argv + argc);
}
You should use getline() to get an entire line of input into some buffer. Then, process that buffer of input to count the number of words in it. Assuming you define each word to be a block of characters separated by a space. Myself, I am a fan of strtok() for breaking up a buffer.
An alternative approach, just for fun:
#include <iostream>
#include <algorithm>
#include <iterator>
int main()
{
unsigned num = 0;
std::for_each(
std::istream_iterator<std::string>(std::cin),
std::istream_iterator<std::string>(),
[&num](const std::string& s)
{
if (s == "quit")
std::cin.setstate(std::ios::eofbit);
++num;
if (std::cin.peek() == '\n') {
std::cout << "You entered "
<< num
<< " word"
<< ((num == 1) ? "." : "s.")
<< '\n';
num = 0;
}
});
}
Doesn't waste resources by tokenizing a line into a vector :)
I would call distance
#include <string>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <sstream>
int main()
{
std::string line;
while(std::getline(std::cin, line) && line != "quit")
{
std::stringstream linestream(line);
std::cout << "You entered "
<< std::distance(std::istream_iterator<std::string>(linestream),
std::istream_iterator<std::string>())
<< " words\n";
}
}