printing only those strings that include 2-digit number
the text inside "myFile.txt is
{the pink double jump 34
the rising frog 2
doing the code 11
nice 4 }
"
#include <iostream>
#include <sstream>
#include <string>
#include <fstream>
#include <algorithm>
int main()
{
std::string path = "myFile.txt";
std::ifstream de;
de.open(path);
if (!de.is_open()) {
std::cout << "nah";
}
else {
std::cout << "file is opened";
std::string str;
while (!de.eof()) {
std::getline(de, str);
for (int i = 0; i < str.length(); i++) {
int aa = 10;
if (str[i] > aa) {
str = "0";
}
}
std::cout << str << "\n\n";
}
}
}
what am I doing wrong? how can I check if there is any 2-digit number inside the string?
You could use stoi as follows:
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::ifstream inp("test.txt");
std::string word;
std::vector<std::string> listOfTwoDigitStrings;
while(inp>>std::ws>>word) {
if(word.length() == 2) {
int num = std::stoi(word);
if(num >= 10 && num <= 99) {
listOfTwoDigitStrings.push_back(word);
}
}
}
for(const auto& word: listOfTwoDigitStrings) {
std::cout<<word<<' ';
}
std::cout<<'\n';
return 0;
}
which has the output
34 11
when test.txt contains
{the pink double jump 34
the rising frog 2
doing the code 11
nice 4 } "
P.S.: As you're looking for strings, just read in strings rather than lines and then reading off strings from that line. Reading off strings just makes it simpler since it boils down to just narrowing down to 2-digit strings and then just verifying whether they are numbers or not. Also, as mentioned in the comments, refrain from !file.eof() code.
Related
Hello I am pretty new to C++. I have a question regarding the splitting of a string.
For example, I have a string like this
std::string str = "jump 110 5";
and between strings "jump", "110" and "5" can be as many spaces as there can be.
I want to save 110 in an int variable and if after the number 110 another number or character should appear then the loop should break.
So far I have removed all the spaces and saved 110 in a variable and printed it out and the number five get ignored.
How can I break or print an error message after 110 saying that the string is not valid?
Here's my code:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
int main() {
std::string str = "jump 110 5";
size_t i = 0;
for ( ; i < str.length(); i++ ){ if ( isdigit(str[i]) ) break; }
str = str.substr(i, str.length() - i );
int id = atoi(str.c_str());
std::cout<<id;
return 0;
}
EDIT: Second attempt..
Here is what I wrote to parse the values into a vector. if the vector has more than one set of numbers, it prints and error.
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
int main() {
std::string str = "jump 110 5";
size_t i = 0;
for (; i < str.length(); i++)
{
if (isdigit(str[i]))
break;
}
str = str.substr(i, str.length() - i);
// Parse str to id
std::stringstream sstr;
sstr << str;
std::string tempStr;
std::vector<size_t> id;
while (std::getline(sstr, tempStr, ' '))
{
std::cout << tempStr << std::endl;
id.push_back(std::stoi(tempStr));
}
// print an error if additional numbers are in id
if (id.size() > 1)
{
std::cout << "Error: " << id[1];
}
else
{
std::cout << "You're good";
}
return 0;
}
Caution: There is an error if there are more than one spaces between 110 and 5.
Original Answer:
If you want id to have the value 110 5, then id shouldn't be an int type because it can't contain spaces. If you want id to have the value 1105, then you'll need to get rid of the spaces in the string "110 5" before assigning it to id, otherwise the value will be truncated when assigned to id.
This is what I did to get rid of the spaces to make id equal to 1105.
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
int main() {
std::string str = "jump 110 5";
size_t i = 0;
for (; i < str.length(); i++)
{
if (isdigit(str[i]))
break;
}
str = str.substr(i, str.length() - i);
// get rid of spaces
std::string tempStr;
for (int i = 0; i < str.length(); i++)
{
if (str[i] != ' ')
{
tempStr.push_back(str[i]);
}
}
// Set the str object to tempStr
str = tempStr;
int id = atoi(str.c_str());
std::cout << id;
return 0;
}
If you really need to keep id as an int and make 110 and 5 separate, then I'd suggest making id into a std::vector and parse the string into the vector.
We have a string (25;16;67;13;14;.......)
We need to print out the numbers separately. The last number does not have a semicolon behind it.
Output should be something like that:
25
16
67
13
14
......
Assuming we are using str.find, str.substr and size_t variables current_pos, prev_pos, what will be the condition of the while loop we are using to browse the line, so that it prints out all the numbers, not just the first one?
You can make use of std::istringstream:
#include <sstream>
#include <iostream>
int main() {
std::string text("25;16;67;13;14");
std::istringstream ss(text);
std::string token;
while(std::getline(ss, token, ';'))
{
std::cout << token << '\n';
}
return 0;
}
Running the above code online results in the following output:
25
16
67
13
14
If you need only to print the numbers in the string (rather than represent them in data structures) the solution is quite easy. Simply read the entire string, then print it character by character. If the character is a semicolon, print a new line instead.
#include <iostream>
#include <string>
using namespace std;
int main(){
string input;
cin >> input;
for(int i = 0; i < input.length(); i++){
if(input.at(i) == ';') cout << endl;
else cout << input.at(i);
}
}
using namespace std;
int main() {
string a{ "1232,12312;21414:231;23231;22" };
for (int i = 0; i < a.size(); i++) {
if (ispunct(a[i])) {
a[i] = ' ';
}
}
stringstream line(a);
string b;
while (getline(line, b, ' ')) {
cout << b << endl;
}
}
//any punctuation ",/;:<>="
I will give you an exact answer to your question with an example and an alternative solution with an one-liner.
Please see
#include <iostream>
#include <string>
#include <iterator>
#include <algorithm>
#include <regex>
const std::regex re(";");
int main() {
std::string test("25;16;67;13;14;15");
// Solution 1: as requested
{
size_t current_pos{};
size_t prev_pos{};
// Search for the next semicolon
while ((current_pos = test.find(';', prev_pos)) != std::string::npos) {
// Print the resulting value
std::cout << test.substr(prev_pos, current_pos - prev_pos) << "\n";
// Update search positions
prev_pos = current_pos + 1;
}
// Since there is no ; at the end, we print the last number manually
std::cout << test.substr(prev_pos) << "\n\n";
}
// Solution 2. All in one statement. Just to show to you what can be done with C++
{
std::copy(std::sregex_token_iterator(test.begin(), test.end(), re, -1), {}, std::ostream_iterator<std::string>(std::cout, "\n"));
}
return 0;
}
I am trying to compare blocks of three numbers with each other to make a new output file with only the ones that meet that: first digit of the block is less than the second and less than the third, the second digit in the block has to be greater than the first but less than the third.
This is my code for the input file:
int main()
{
ofstream outfile ("test.txt");
outfile << "123 456 789 123 123 432 \n 123 243 " << endl;
I want to split this in blocks of three like"123", "456" and so on to be able to only write only the ones that meet the requirement in the new output file. I decided to conver the whole file into an integer vector to be able to compare them.
char digit;
ifstream file("test.txt");
vector<int> digits;
while(file >> digit) {
digits.push_back(digit - '0');
}
and I suppose that the method that compares them would look something like this:
bool IsValid(vector<int> digits){
for(int i=0; i<digits.size(); i++){
if(digits[0] < digits[1] & digits[0] < digits[2] & digits[1]<digits[2])
return true;
else{
return false;
}
}
}
However this would just compare the first block, would you do it differently? or should I keep doing the vector idea
You can do in this way. The "get" read a single char and when there are 3 digits the function IsValid is called.
#include <fstream>
#include <string>
#include <vector>
using namespace std;
bool IsValid(vector<int> digits)
{
if(digits[0] < digits[1] & digits[0] < digits[2] & digits[1]<digits[2])
return true;
else
return false;
}
int main()
{
ifstream in("test.txt");
ofstream out("output.txt");
char tmp;
vector<int> digits;
while(in.get(tmp))
{
if(tmp!=' ' and tmp!='\n')
{
digits.push_back(tmp-'0');
if(digits.size()==3)
{
if(IsValid(digits))
out<<digits[0]<<digits[1]<<digits[2]<<endl;
digits.clear();
}
}
}
out.close();
in.close();
}
if you task is : first digit of the block is less than the second and less than the third, the second digit in the block has to be greater than the first but less than the third - you num in string type - sorted - use it )) if data is 3 digits and space separeted )))
std::stringstream ss{line}; - for example like fstream )))
#include <iostream>
#include <vector>
#include <iterator>
#include <string>
#include <sstream>
#include <algorithm>
int main() {
std::string line{"123 456 789 123 123 432 123 243 "};
std::cout << line << std::endl;
std::string out_line;
std::stringstream ss{line};
std::string tmp_str;
while(ss >> tmp_str) {
if (std::is_sorted(std::begin(tmp_str), std::end(tmp_str))) {
out_line += tmp_str + " ";
}
}
std::cout << out_line << std::endl;
return 0;
}
I'm trying to read in a file, add each line into a vector, and then print the vector.
But right now, it will only print the first line. Because of this, I'm assuming that the first line is the only line being added to the vector, but I can't figure out why.
Here is my code:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
int main()
{
std::vector<std::string> vecOfStrs;
std::ifstream fileIn("example.txt");
std::string str;
std::string newLine;
newLine = str + "\n";
while (std::getline(fileIn, str)) {
std::string newLine;
newLine = str + "\n";
if (newLine.size() > 0) {
vecOfStrs.push_back(newLine);
}
fileIn.close();
for (int i = 0; i < vecOfStrs.size(); i++) {
std::cout << vecOfStrs.at(i) << ' ';
}
}
}
Here is the text file, and right now it should print out exactly as it appears here:
Barry Sanders
1516 1319 1108 1875 -999
Emmitt Smith
1892 1333 1739 1922 1913 1733 -999
Walter Payton
1999 1827 1725 1677 -999
There is logic inside of your reading loop that really belongs after the loop has finished instead:
You are close()'ing the file stream after the 1st line is read, thus breaking the loop after the 1st iteration.
You are printing the entire vector after adding each line to it.
Also, you don't need the newLine variables at all.
Try this instead:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
int main() {
std::vector<std::string> vecOfStrs;
std::ifstream fileIn("example.txt");
std::string str;
while (std::getline(fileIn, str)) {
if (str.size() > 0) {
vecOfStrs.push_back(str);
}
}
fileIn.close();
for (size_t i = 0; i < vecOfStrs.size(); i++) {
std::cout << vecOfStrs[i] << ' ';
}
return 0;
}
What is wrong with this code? I need to convert string into float. m2 has an error in m2.length
#include <iostream>
#include <string>
#include <cstdlib>
#include <sstream>
using namespace std;
int main()
{
float v2;
char *m2 = "1 23 45 6";
for (int i = 0; i < m2.length(); i++) //to convert every element in m2 into float
{
v2 = atof(&m2[i]);
}
printf("%.2f", v2);
system("pause");
return 0;
}
I need to convert each element in the array so that I can store them to make operations
Okay so how about you use a string stream to extract the numbers from the string into a vector?
#include <iostream>
#include <iterator>
#include <sstream>
#include <vector>
int main()
{
std::string input = "1 23 45 6";
std::stringstream ss(input);
std::istream_iterator<double> end;
std::vector<double> output(std::istream_iterator<double>(ss), end);
}
There are too may things wrong with your code to explain each and every point. That's how I would do it:
float v2;
std::istringstream iss("1 23 45 6");
while(iss >> v2) {
std::cout << v2 << std::endl;
}
Step by step analysis, for learning from the errors:
First there is no member function length() for an array of characters, so you should define string m2="..."; in order for the code to compile.
Then unfortunately your code would print only one number: the last. Why ? Because your printf() is outside the loop.
Once you've put it inside the loop, you'd have plenty of numbers, but more than you expect:
* the first iteration, it'd start with "1 23 45 6" => 1
* the second with " 23 45 6" => 23
* the third iteraton "23 45 6" => 23 again!
* the fourth iteration "3 45 6" => 3 (did you expect this ?)
So you'd have to jump from one number to the next. So instead of incrementing, you coud search for the next space, with function find_first_of():
for (int i = 0; i < m2.length(); i=m2.find_first_of(' ', i+1)) // jump to the next space
{
v2 = atof(&m2[i]);
printf("%.2f\n", v2);
}
Here the online demo.
Real c++ alternatives:
Have a look at πάντα ῥεῖ 's solution: that's the way we do it in C++
Use string instead of char*, to make things a little easier.
For converting a given string to a numerical value, either use stringstream or atof().
Quick solution to your problem:
#include <iostream>
#include <string>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int main()
{
vector<float> myFloats;
string m("1. 2.23 45 6456 72.8 46..");
// First of parse given string and separate char groups that serve as a number
// => only consider 0-9 and '.'
if(m.size() == 0)
return 1;
string charGroup;
for(int i=0; i<m.length(); i++)
{
if((isdigit(m.at(i)) || m.at(i) == '.'))
{
charGroup += m.at(i);
if(i == m.length() - 1 && !charGroup.empty())
{
// in case given group is a numerical value
myFloats.push_back((float) atof(charGroup.c_str()));
// prepare for next group
charGroup.clear();
}
}
else if(!charGroup.empty())
{
if(m.at(i) == ' ')
{
// in case given group is a numerical value
myFloats.push_back((float) atof(charGroup.c_str()));
// prepare for next group
charGroup.clear();
}
else charGroup.clear();
}
}
// Print float values here
if(!myFloats.empty())
{
cout << "Floats: ";
for(int i=0; i<myFloats.size(); i++)
cout << myFloats.at(i) << ", ";
}
getchar();
return 0;
}