I have a function for converting integers into std::string.
std::stringstream Tools::toStringConverter;
std::string Tools::tempString;
std::string Tools::intToString(int num) {
toStringConverter.str(std::string());
toStringConverter << num;
toStringConverter >> tempString;
return tempString;
}
When I try to use this method while using iterators, I get correct result
for(Button b : buttons) {
std::cout << Tools::intToString(b.id);
}
Also output is correct if I try this:
std::cout<< intToString(3);
But when I use simple for loop, I always get 0.
for(int i = 0; i < NetworkManager::MAX_PLAYERS; i++) {
std::cout << Tools::intToString(i) << " ";
}
std::string Tools::intToString(int num) {
std::stringstream toStringConverter;
toStringConverter << num;
return toStringConverter.str();
}
Don't use global variables.
Related
I need help for my university homework. i'm still new to this.
Basically i am doing a run-length encoding and i don't know how to add the letter after the counter:
#include <iostream>
#include <string>
#include <vector>
#include <stdexcept>
void error(std::string str)
{
throw std::runtime_error(str);
}
int main()
{ int counter = 1;
std::string id;
std::vector<int> v;
std::cout << "Enter the data to be compressed: ";
std::cin >> id;
try
{ for(int i = 0; i < id.size(); i++)
{
if(std::isdigit(id[i]))
error("invalid input");
}
std::cout << "The compressed data is: ";
for(int i = 0; i < id.size(); i++)
{
if(id[i] == id[i+1])
{
counter++;
}
else if(id[i]!= id[i+1])
{
v.push_back(counter);
v.push_back(id[i]);
counter=1;
}
}
for(int j = 0; j < v.size(); j++)
std::cout << v[j];
}
catch(std::runtime_error& str)
{
std::cerr << "error: " << str.what() << std::endl;
return 1;
}
return 0;
}
For example if i input aaabbb, the probram should output 3a3b. The problem is that it outputs 397398 97 and 98 being the ascii code for a and b.
i don't know how to put the letter after the counter and for them to be in the same vector.
If you want to serialize as a string try this :
#include <iostream>
#include <string>
#include <vector>
#include <stdexcept>
#include <sstream>
void error(std::string str) {
throw std::runtime_error(str);
}
int main() {
std::ostringstream stream;
int counter = 1;
std::string id;
std::cout << "Enter the data to be compressed: ";
std::cin >> id;
try {
for (int i = 0; i < id.size(); i++) {
if (std::isdigit(id[i]))
error("invalid input");
}
std::cout << "The compressed data is: ";
for (int i = 0; i < id.size(); i++) {
if (id[i] == id[i + 1]) {
counter++;
} else if (id[i] != id[i + 1]) {
stream << counter;
stream << (char) id[i];
counter = 1;
}
}
std::cout << stream.str() << std::endl;
} catch (std::runtime_error& str) {
std::cerr << "error: " << str.what() << std::endl;
return 1;
}
}
v[j] from std::cout << v[j] is of type int and that is why std::cout writes a number. To write it as a character, you should cast v[j] to char as follows: std::cout << (char)v[j]. In this way, std::cout will use the char specialization, not the int one.
While the other answers might give you the output you need, I believe the idiomatic way to solve this is using a class to hold both the character and its count. There are two obvious choices.
std::pair
Could also be std::tuple if you prefer it for consistency or whatever reason. Save your results in a std::vector<std::pair<char, int>. This saves the information, but to print it you would need to define an appropriate function. Add elements via
v.emplace_back(character, count);
Wrapper Class
If you want to offer some functionality without outside helper classes, define a custom wrapper class such as the following.
class CharacterCount {
private:
char character;
int count;
public:
CharacterCount(char character, int count):
character(character), count(count) {}
explicit operator std::string() const { return std::to_string(count) + character;
// Other helper functions or constructors you require
}
This simplifies printing
for (auto& character_count : v)
std::cout << static_cast<std::string>(character_count);
I believe because std::ostream::operator<< is templated, you cannot get an implicit conversion to std::string to work. I would advise against implicit conversion anyway.
You can use the same emplace_back syntax as before because we offer an appropriate constructor.
So you take your input in a string and ultimately just need to stream this information out, ultimately meaning there's really no reason to store the information in a vector, just output it! You can use find_if with a lambda to find the non-consecutive character (or find_if_not if you prefer.)
for(string::const_iterator finish, start = cbegin(id); start != cend(id); start = finish) {
finish = find_if(start, cend(id), [value = *start](const auto i) { return i != value; } );
cout << distance(start, finish) << *start;
}
Live Example
I am reading a text file which contains integers separated by a new line. Like this.
5006179359870233335
13649319959095080120
17557656355642819359
15239379993672357891
3900144417965865322
12715826487550005702
From this file, I want to access each integer in a loop and compare it with another, in order to match those two. In function File_read() I can print the integers. But what I want is to get it integer by integer outside the function. For example in main method, if there is a integer called x, I want to check whether x equals one of the integers in my text file.
string File_read() {
std::ifstream my_file("H:\\Sanduni_projects\\testing\\test.txt",
std::ifstream::binary);
if (my_file) {
string line;
for (int i = 0; i < 25; i++){
getline(my_file, line);
//cout << line << endl;
return line;
}
if (my_file)
std::cout << "all characters read successfully."<<endl;
my_file.close();
}
return 0;
}
Never return unconditionally inside a loop.
You are returning unconditionally from inside the loop. This causes the caller to exit the loop and return from the function during the first iteration.
for (int i = 0; i < 25; i++){
getline(my_file, line);
return line; // <-- Return from function (rest of iterations unreachable). Bad.
}
No need to reinvent stuff
Use the standard library to read the numbers, e.g., into a container std::vector.
std::vector<unsigned long long> v{std::istream_iterator<unsigned long long>{my_file},
std::istream_iterator<unsigned long long>{}};
Notice the value type of unsigned long long that is needed to fit the large numbers (you're pushing ~64 bits here).
Find a match
Use, e.g., std::find to find a possible match among the parsed numbers.
auto key = 15239379993672357891ull;
if (auto it = std::find(std::begin(v), std::end(v), key); it != std::end(v)) {
std::cout << "Key found at line " << std::distance(std::begin(v), it) + 1 << std::endl;
}
Here, I'm using a C++1z if(init; condition) statement to limit the scope of the iterator it to inside the if statement. It's optional of course.
Live example
You are, currently, just returning the first number (as a std::string and not a number). If you remove the return statement in your loop you can, of course, print each of them. Here is a slightly modified version of your File_read function that will return a std::vector<unsigned long long> that contains all the numbers. Then you can use this vector in, e.g., your main function to do your processing.
std::vector<unsigned long long> File_read()
{
std::vector<unsigned long long> numbers;
std::ifstream my_file("H:\\Sanduni_projects\\testing\\test.txt"); // Text files are not 'binany', i.e., removed std::ifstream::binary
if (my_file)
{
std::string line;
for (int i = 0; i < 25; i++)
{
std::getline(my_file, line);
numbers.push_back(std::stoull(line));
}
if (my_file)
{
std::cout << "all characters read successfully." << std::endl;
}
// my_file.close(); // Do not do this manually
}
return numbers;
}
Usage example:
int main()
{
unsigned long long x = /* some number */;
// Read all the numbers
std::vector<unsigned long long> vl = File_read();
// Run through all the numbers
for (unsigned long long y : vl)
{
// Check if any of the numbers are equal to x
if (x == y)
{
// There is a match...
// Do stuff
}
}
}
Update
The numbers cannot be held by in a long, however unsigned long long is sufficient.
std::vector<long> File_read(){
vector<long> numbers;
ifstream my_file("H:\\Sanduni_projects\\testing\\test.txt",
std::ifstream::binary);
if (my_file) {
string line;
for (int i = 0; i < frames_sec; i++){
getline(my_file, line);
numbers.push_back(std::stol(line));
}
if (my_file)
std::cout << "all characters read successfully." << endl;
else
std::cout << "error: only " << my_file.gcount() << " could be read" << endl;
my_file.close();
}
else{
cout << "File can not be opened" << endl;
}
return numbers;
}
Although the someone gives the answers that works correctly, I want to share my code.
#include <memory>
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
#define MAX_SIZE 4096
class FileRead
{
public:
FileRead(string path) :_file(path)
{
Reset();
}
void Reset()
{
memset(_buff, 0, MAX_SIZE);
}
string ReadLine()
{
if (!_file.is_open())
{
cout << "error open file" << endl;
return "";
}
if (!_file.eof())
{
Reset();
_file.getline(_buff,MAX_SIZE);
return string(_buff);
}
else
{
cout << "read file finished." << endl;
return "";
}
}
private:
ifstream _file;
string _line;
char _buff[MAX_SIZE];
};
int _tmain(int argc, _TCHAR* argv[])
{
FileRead fr("H:\\Sanduni_projects\\testing\\test.txt");
string line;
while (!(line = fr.ReadLine()).empty())
{
//do some compare..
}
return 0;
}
The other answers are correct about how return works, but there is something that acts how you thought return acted.
using string_coro = boost::coroutines::asymmetric_coroutine<std::string>
void File_read(string_coro::push_type & yield) {
std::ifstream my_file("H:\\Sanduni_projects\\testing\\test.txt", std::ifstream::binary);
if (my_file) {
string line;
for (int i = 0; i < 25; i++){
getline(my_file, line);
yield (line);
}
if (my_file)
std::cout << "all characters read successfully." << std::endl;
my_file.close();
}
}
Which is used like this
string_coro::pull_type(File_read) strings;
for (const std::string & s : strings)
std::cout << s << endl;
So this is a fragment of my code:
void reverse(string query, string reverseQuery) {
unsigned int i;
for(i=0; i<query.length(); i++) {
reverseQuery[i] = query[query.length()-1-i];
}
cout << reverseQuery << endl;
return;
}
The headers for iostream, string and using namespace std were also included in the code. The problem I am facing is that when I try to output the string reverseQuery nothing comes out. Anyone knows why? Thanks!
Your fragment should look like:
std::string reverse(const string& query) {
std::string reverseQuery(query.length(),0); // <<<<< Ensure that the size is the same
for(unsigned i=0; i<query.length(); i++) {
reverseQuery[i] = query[query.length()-1-i];
}
// cout << reverseQuery << endl;
return reverseQuery;
}
The way shorter and idiomatic code to achieve that with a standard c++ string is
std::string reverseQuery(query);
std::reverse(std::begin(reverseQuery),std::end(reverseQuery));
I am trying to create an array of String that contain numbers. These numbers are the names of folders that I need to access. Currently I am declaring it as shown below:
String str1[] = { "001", "002", "003", "004", "005", "006", "007", "008", "009", "010", "011", "012", "013", "014", "015", "016", "017", "018", "019", "020", };
I have 124 folders and naming them in such fashion is tedious. Is there a better way to do this? I am working with C++.
You can use stringstreams and set the format options to fill the integer to a certain number of characters and set the filling character.
Edit: Ok my code doesn't begin with 1 but 0, but I'm sure you can figure that out :)
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
#include <vector>
using namespace std;
int main()
{
std::vector<std::string> strs;
for (int i = 0; i < 124; i++)
{
std::ostringstream os;
os << std::setfill('0') << std::setw(3) << i;
strs.push_back(os.str());
}
for (const auto& s : strs)
{
std::cout << s << "\n";
}
}
Live example: http://ideone.com/TEV2iq
use a stringstream and for loop.
Example:
uint32_t t150()
{
std::vector<std::string> strVec; // i.e. String str1[]
for (int i=1; i<125; ++i)
{
std::stringstream ss;
ss << std::setw(3) << std::setfill('0') << i;
strVec.push_back(ss.str());
}
for (int i=0; i<124; ++i)
std::cout << strVec[i] << std::endl;
return(0);
}
An alternative is something like:
std::string t150b(int i) {
std::stringstream ss;
ss << std::setw(3) << std::setfill('0') << i;
return (ss.str());
}
// not tested, and no range check
which returns the formatted string for the value i ... I imagine you have the loop at some higher level code.
Another alternative is to skip the vector, just build the string with white spaces between ... then fetch them like you fetch any file item ...
void t150c(std::stringstream& ss)
{
for (int i=1; i<125; ++i) {
ss << std::setw(3) << std::setfill('0') << i << " ";
// white space between values -------------------^^
}
}
Usage example:
{
std::stringstream ss;
t150c(ss); // 'fill' stream with desired strings
do {
if(ss.eof()) break;
std::string s;
ss >> s; // extract string one at a time
std::cout << s << std::endl; // and use
}while(1);
}
std::string str1[124];
for(int i = 1; i <= 124; i++){
str1[i-1] = convertTo3Digit(i);
}
Then just write the convertTo3Digit function to take the numerical value and format it into a 3-digit string.
Another less elegant way would be to format a column in excel to be three-digit numbers and generate 001-124 and then copy-paste into your static initializer. You can use regex to add the quotes and commas.
here is my problem. i have some two dimensional data with changing dimensionality, that i want to read into an 2d-array of doubles. Furthermore, there are at some points not number in the file but "NaN"s, that i want to be replaced by a zero. I made my code working so far, but i only managed to read integers. Maybe you could help me out to read it as doubles?
Here is what i got so far:
void READER(char filepath [], int target [129][128])
{
//---------------------------- header double & int
int rowA = 0;
int colA = 0;
std::string line;
std::string x;
std::cout << "reading file: " << filepath << "\n";
std::cout << std::endl;
std::ifstream fileIN;
fileIN.open(filepath);
if (!fileIN.good())
std::cerr << "READING ERROR IN FILE: " << filepath << std::endl;
while (fileIN.good())
{
while (getline(fileIN, line))
{
std::istringstream streamA(line);
colA = 0;
while (streamA >> x)
{
boost::algorithm::replace_all(x, "NaN", "0");
boost::algorithm::replace_all(x, ",", ""); //. rein
// std::cout << string_to_int(x) << std::endl;
target [rowA][colA] = string_to_int(x);
colA++;
}
rowA++;
if(rowA%5 ==0)
{
std::cout << "*";
}
}
}
std::cout << " done." <<std::endl;
}
this writes the files into 'target'. The function string to int looks the following:
int string_to_int (const std::string& s)
{
std::istringstream i(s);
int x;
if(!(i >> x))
return 0;
return x;
}
here you find some example data:
"exactly, thats what i thought about doing with the line boost::algorithm::replace_all(x, ",", ""); by replacing , by ."
Use following function to convert to any type, say double :-
template <typename T>
T StringToNumber ( const std::string &Text )
{
std::istringstream ss(Text);
T result;
return ss >> result ? result : 0;
}
Call using :
boost::algorithm::replace_all(x, ",", "."); // Change , to .
std::cout << StringToNumber<double>(x) << std::endl;
Or
you can simply use boost::lexical_cast
std::cout<<boost::lexical_cast<double>( x )<<std::endl;
Make sure you have a double 2D array