Taking integers out of a string C++ [duplicate] - c++

This question already has answers here:
How to parse a string to an int in C++?
(17 answers)
c++ parse int from string [duplicate]
(5 answers)
Closed 8 years ago.
I wanted to know how I can grab numbers out of a string in C++. I'm getting the string from an input and will be getting multiple lines, but I already have the line reading working.
Note: the lines always have an even number of ints
Here's what I'd like the code to look something like:
std::getline(std::cin, line);// line looks something like "10 3 40 45 8 12"
int a, b;
while(!line.empty() /*line still has ints to extract*/) {
a = someMethod(line);//gets first int. So, 10 first loop, 40 second, 8 third
b = someMethod(line);//gets second int. So, 3 first loop, 45 second, 12 third
myMethod(a,b);//a method from elsewhere in my code. It's here so you know that I need both a and b
}
Anything similar would help. Thank you very much!

Here is a complete example.
#include <sstream>
#include <string>
#include <iostream>
int main(){
std::string line = "2 4 56 6";
std::stringstream stream(line);
int i;
while (stream >> i) {
std::cout << i << std::endl;
}
}
The following works fine also, so reading multiple lines should not be a problem.
#include <sstream>
#include <string>
#include <iostream>
int main(){
std::string line = "2 4 56 6";
std::stringstream stream(line);
int i;
while (stream >> i) {
std::cout << i << std::endl;
}
line = "32 62 44 6 22 58 34 60 71 86";
stream.clear();
stream.str(line);
int a,b;
while(stream >> a && stream >> b){
std::cout << a << " " << b << "\n";
}
}

Get tokens from string line and use them as you want.
#include <iostream>
#include <string>
#include <boost/tokenizer.hpp>
using namespace std;
typedef boost::tokenizer<boost::char_separator<char> >
tokenizer;
void myMethod(int a, int b)
{
cout<<a<<" "<<b<<endl;
}
void getNumber(string line)
{
boost::char_separator<char> sep(" ");
tokenizer tokens(line, sep);
string evenStr, oddStr;
for(tokenizer::iterator iterToken=tokens.begin();
iterToken != tokens.end(); ++iterToken)
{
evenStr = *iterToken;
++iterToken;
if(iterToken != tokens.end())
{
oddStr = *iterToken;
myMethod(atoi(evenStr.c_str()), atoi(oddStr.c_str()));
}
}
}
int main()
{
string line("10 3 40 45 8 12");
getNumber(line);
return 0;
}

You can do like this:
string line;
getline(std::cin, line);// line looks something like "10 3 40 45 8 12"
int a, b;
vector<string> tokens;
istringstream iss(line);
copy(istream_iterator<string>(iss),
istream_iterator<string>(),
back_inserter<vector<string> >(tokens));
stringstream s;
for (int i=0;i<tokens.size()/2;i++)
{
s<< tokens[i];
s>>a;
s.clear();
s<<tokens[i+2];
s>>b;
s.clear();
myMethod(a,b);
}

There are multiple ways to achieve this. I prefer to use boost.
Example:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
int main()
{
std::string line = "10 3 40 45 8 12 9"; //std::getline(std::cin, line);// line looks something like "10 3 40 45 8 12"
std::vector<std::string> intNumbers;
std::string s;
boost::split(intNumbers, line, boost::is_any_of(" "), boost::token_compress_on);
unsigned int i=0;
while(i < intNumbers.size())
{
try{
int a = boost::lexical_cast<int>(intNumbers[i++]);
if(i >= intNumbers.size())
{
std::cout << "invlaid values" << std::endl;
break;
}
int b = boost::lexical_cast<int>(intNumbers[i++]);
std::cout << "value a: " << a << std::endl;
std::cout << "value b: " << b << std::endl;
std::cout << "my method (multiply) a*b: " << (a*b) << std::endl;
}
catch(boost::bad_lexical_cast &e)
{
std::cout << "invlaid values" << std::endl;
}
}
}

Related

How to delete unnecessary new line from string while reading file?

I have created a simple file reader function which use std::map with std::tuple. The code is as follow:
#include <iostream>
#include <fstream>
#include <vector>
#include <tuple>
#include <map>
#include <algorithm>
typedef std::map<std::string, std::tuple<int, double>> Map;
Map Readfile(std::string filename)
{
std::ifstream File(filename);
if (!File.is_open())
{
std::cout << "File '" << filename << "' does not exist.";
exit(1);
}
Map data;
std::string name;
int a;
double b;
while (std::getline(File, name, '\t') >> a >> b)
{
data.insert({name, std::tuple<int, double>(a, b)});
}
return data;
}
int main()
{
std::string file = "file_read_v3.txt";
auto mt = Readfile(file);
std::for_each(mt.begin(), mt.end(), [](std::pair<std::string,std::tuple<int, double>> it) {
std::cout << it.first << "\t" << std::get<0>(it.second) << "\t" << std::get<1>(it.second) << std::endl;
});
return 0;
}
The contents of the text file I read:
Yvis 25 63.25
Wogger X Y 2 6.2
Bilbo 111 81.3
Mary 29 154.8
The data in the file is separated by tabs ('\t'). When I compile the source code, I discovered a rather strange thing on the command line: for some reason, there is a new line break after reading each line. I see this on the command line:
Bilbo 111 81.3
Mary 29 154.8
Wogger X Y 2 6.2
Yvis 25 63.25
What is the solution to this problem? And how to avoid not sorting the scanned data?

How Do I Print a Vector of Tuples?

So I'm trying to make a vector that contains tuples containing two ints, and I'm acquiring the ints from a text file source. To make sure I have the vector I want, I'm trying the print out my contents, but the output is not showing me anything. I'm not sure if it's because of my code, and where I put my text file. I'm just stuck at this point. If anything could help me with this, I'd appreciate it very much. Thanks
using namespace std;
int main()
{
ifstream file("source.txt");
typedef vector<tuple<int, int>> streets;
streets t;
int a, b;
if (file.is_open())
{
while (((file >> a).ignore() >> b).ignore())
{
t.push_back(tuple<int, int>(a, b));
for (streets::const_iterator i = t.begin();i != t.end();++i)
{
cout << get<0>(*i) << endl;
cout << get<1>(*i) << endl;
}
cout << get<0>(t[0]) << endl;
cout << get<1>(t[1]) << endl;
}
}
file.close();
system("pause");
return 0;
Here's my text file and where I placed it
enter image description here
Here's my output from debugging, if that's important
You should use a loop, that will print one tuple at a time.
Complete minimal example:
#include <iostream>
#include <tuple>
#include <vector>
#include <fstream>
using namespace std;
int main(void) {
std::ifstream infile("source.txt");
vector<tuple<int, int>> streets;
int a, b;
while (infile >> a >> b)
{
streets.push_back(tuple<int, int>(a, b));
}
infile.close();
for(auto& tuple: streets) {
cout << get<0>(tuple) << " " << get<1>(tuple) << endl;
}
return 0;
}
Output:
1 2
3 4
5 6
7 8

Reading a File's Line with no Spaces into separate Variables

First time asking a question on this site, so here goes. I've been racking my brain for quite some time, but still can't seem to find the answer to this.
Let's say I have a file that reads as follows:
123456789John Doe 0001111.11
925219042Mary Jane 0000302.54
891492829Gertrude Marisou 0123467.76
How would I separate say, 123456789 and John into their own respective strings for input into a vector containing four variables? (Std::string, Std::string, Std::string, Double)
Here is my current code if you all would like to take a peek at it and tell me where I am going wrong.
#pragma once
#if !defined(__Account7_h__)
#define __Accoun7_h__
#include <string>
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <sstream>
//Personal file for trimming the extra whitespace
#include "Trim.h"
class Account7 {
private:
std::string account_code;
std::string first_name;
std::string last_name;
double balance;
public:
//Getters, Setters, Initialization List and whatnot.
//On a separate file
#if !defined(__Vmanager7_h__)
#define __Vmanager7_h__
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <sstream>
#include "Account7.h"
#include "Trim.h"
using namespace generic;
class Vmanager7 {
public:
int a = 1;
std::ifstream infile;
std::ofstream outputFile;
std::vector<Account7> _Account;
Account7 temp;
std::string Empl;
std::string scapeg;
std::string acc_c;
std::string fname;
std::string lname;
double bal;
int Managed() {
int count;
infile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try {
infile.open("account.dat", std::ifstream::in);
}
catch (std::ios_base::failure &fail) {
std::cout << "File is not opening" << std::endl;
return 0;
}
infile.exceptions(std::ios::goodbit);
while (getline(infile, Empl)) {
count = 1;
std::istringstream ss(Empl);
while (getline(ss, scapeg)) {
if (count == 1)
acc_c = scapeg;
else if (count == 2)
fname = scapeg;
else if (count == 3)
lname = scapeg;
else
bal = atof(scapeg.c_str());
count++;
}
temp.setac(acc_c);
temp.setfn(fname);
temp.setln(lname);
temp.setba(bal);
_Account.push_back(temp);
}
infile.close();
outputFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try {
outputFile.open("Aoutput.dat");
}
catch (std::ios_base::failure &fail) {
std::cout << "File opening fail" << std::endl;
return 0;
}
outputFile.exceptions(std::ios::goodbit);
for (int i = 0; i < _Account.size(); i++) {
std::cout << _Account[i].getac() << " " << _Account[i].getfn() << " " << _Account[i].getln() << " " << _Account[i].getba();
bal = _Account[i].getba();
bal -= int(bal);
if (bal == 0)
std::cout << ".00";
std::cout << '\n';
}
outputFile.close();
}
};
};
The output I get is something along the lines of this:
123456789John Doe 0001111.11 -9.25596e+61
925219042Mary Jane 0000302.54 -9.25596e+61
191492829Gertrude Marisou 0123467.76 -9.25596e+61
I would like the output to look just like the input. Any help would be immensely appreciated.

How to read a file with multiple delimiters within a single line

I am trying to read a file which has multiple delimiters per line.
Below is the data
2,22:11
3,33:11
4,44:11
5,55:11
6,66:11
7,77:11
8,88:11
9,99:11
10,00:11
11,011:11
12,022:11
13,033:11
14,044:11
15,055:11
16,066:11
17,077:11
18,088:11
19,099:11
And the code is below
Here, I am trying to read the line first with comma as delimiter to get line and then the colon.
#include <fstream>
#include <iostream>
#include <string>
int main() {
std::string line;
std::string token;
std::ifstream infile;
infile.open("./data.txt");
while (std::getline(infile, line,',')) {
std::cout << line << std::endl;
while(getline(infile, token, ':'))
{
std::cout << " : " << token;
}
}
}
But there is an issue with the code as it is skipping the first line.
Also , if i comment the second while loop,only the first line is getting printed, and below is the output
Ian unable to figure out where exactly the code has gone wrong
Output
2
: 22 : 11
3,33 : 11
4,44 : 11
5,55 : 11
6,66 : 11
7,77 : 11
8,88 : 11
9,99 : 11
10,00 : 11
11,011 : 11
12,022 : 11
13,033 : 11
14,044 : 11
15,055 : 11
16,066 : 11
17,077 : 11
18,088 : 11
19,099 : 11
Why two while ?
Your problem is that you repeat the second while forever. The first while is executed only to get the first 2, the second while is executed to the end of the file.
You can do all with a single while; something like
#include <fstream>
#include <iostream>
using namespace std;
int main() {
std::string line;
std::string token;
std::string num;
ifstream infile;
infile.open("a.txt");
while ( getline(infile, line,',')
&& getline(infile, token, ':')
&& getline(infile, num) )
cout << line << ',' << token << ':' << num << endl;
}
The problem comes from the fact you are using std::getline twice.
At the beginning you enter the first loop. The first call to std::getline returns want you expect : the first line until the , delimiter.
Then you enter the second std::getline, in a nested loop, to get the rest of the line. But the thing is, you never leave the second loop until the end of the file. So, you read all the file splitting by : delimiter.
When the second std:getline ends up to the end of the file, it leaves the nested loop.
Because you already read all the file, nothing's left to be read and the first loop directly exits.
Here is some debug to help you understand the context :
#include <fstream>
#include <iostream>
#include <string>
int main() {
std::string line;
std::string token;
std::ifstream infile;
infile.open("./data.txt");
while (std::getline(infile, line, ',')) {
std::cout << "First loop : " << line << std::endl;
while(getline(infile, token, ':'))
{
std::cout << "Inner loop : " << token << std::endl;
}
}
}
The first lines to be printed are :
First loop : 2
Inner loop : 22
Inner loop : 11
3,33
Inner loop : 11
4,44
You can clearly see it doesn't exit the second loop until the end.
I would advise to read the entire line, with no care of delimiters, and then split the string into token using a tailor made function. It would be easy and very clean.
Solution :
#include <fstream>
#include <list>
#include <iostream>
#include <string>
struct line_content {
std::string line_number;
std::string token;
std::string value;
};
struct line_content tokenize_line(const std::string& line)
{
line_content l;
auto comma_pos = line.find(',');
l.line_number = line.substr(0, comma_pos);
auto point_pos = line.find(':');
l.token = line.substr(comma_pos + 1, point_pos - comma_pos);
l.value = line.substr(point_pos + 1);
return l;
}
void print_tokens(const std::list<line_content>& tokens)
{
for (const auto& line: tokens) {
std::cout << "Line number : " << line.line_number << std::endl;
std::cout << "Token : " << line.token << std::endl;
std::cout << "Value : " << line.value << std::endl;
}
}
int main() {
std::string line;
std::ifstream infile;
std::list<line_content> tokens;
infile.open("./data.txt");
while (std::getline(infile, line)) {
tokens.push_back(tokenize_line(line));
}
print_tokens(tokens);
return 0;
}
I think you should be able to do what you what.
Compiled as follow : g++ -Wall -Wextra --std=c++1y <your c++ file>
If you want to split a string on multiple delimiters, without having to worry about the order of the delimiters, you can use std::string::find_first_of()
#include <fstream>
#include <iostream>
#include <streambuf>
#include <string>
int
main()
{
std::ifstream f("./data.txt");
std::string fstring = std::string(std::istreambuf_iterator<char>(f),
std::istreambuf_iterator<char>());
std::size_t next, pos = 0;
while((next = fstring.find_first_of(",:\n", pos)) != std::string::npos)
{
std::cout.write(&fstring[pos], ++next - pos);
pos = next;
}
std::cout << &fstring[pos] << '\n';
return 0;
}

Method that converts uint8_t to string

I have this:
uint8_t key[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31};
How can I convert it to char or something so that I can read its contents? this is a key i used to encrypt my data using AES.
Help is appreciated.
Thanks
String converter(uint8_t *str){
return String((char *)str);
}
If I have understood correctly you need something like the following
#include <iostream>
#include <string>
#include <numeric>
#include <iterator>
#include <cstdint>
int main()
{
std::uint8_t key[] =
{
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
};
std::string s;
s.reserve( 100 );
for ( int value : key ) s += std::to_string( value ) + ' ';
std::cout << s << std::endl;
}
The program output is
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
You can remove blanks if you not need them.
Having the string you can process it as you like.
If the goal is to construct a string of 2-character hex values, you can use a string stream with IO manipulators like this:
std::string to_hex( uint8_t data[32] )
{
std::ostringstream oss;
oss << std::hex << std::setfill('0');
for( uint8_t val : data )
{
oss << std::setw(2) << (unsigned int)val;
}
return oss.str();
}
This requires the headers:
<string>
<sstream>
<iomanip>
#include <sstream> // std::ostringstream
#include <algorithm> // std::copy
#include <iterator> // std::ostream_iterator
#include <iostream> // std::cout
int main(){
uint8_t key[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31};
std::ostringstream ss;
std::copy(key, key+sizeof(key), std::ostream_iterator<int>(ss, ","));
std::cout << ss.str();
return 0;
}
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,
30,31,
You can use a stringstream:
#include <sstream>
void fnPrintArray (uint8_t key[], int length) {
stringstream list;
for (int i=0; i<length; ++i)
{
list << (int)key[i];
}
string key_string = list.str();
cout << key_string << endl;
}