Preprocessor directive to create file names - c++

I have to open files one by one for reading in C/C++. The name of the files are in0, in1, in2, in3.....
I tried to use preprocessor directive to create file names.
i want something like.
for(int i=0;i<n;i++)
{
string inp_file="/path/"+"in"+APPEND(i); //to generate /path/in1 etc
open(inp_file);
}
where APPEND is a MACRO.
Since
#define APP(i) i
can generate the value
#define APP(i) #i
can convert a token to string.
I am trying to combine them both in many ways but failed.
How to get the desired result or is it even possible to get the such a result with macro?

In your case, the variable i is not a compile-time constant and so it is impossible to use pre-processor or template specialization because the value is simply not known at a time of compilation. What you can do is convert integer into string - boost.lexical_cast is one of the easiest to use solutions:
for (int i = 0; i < n; ++i) {
// Generate /path/in1 etc
std::string inp_file = "/path/in"+ boost::lexical_cast<std::string>(i);
open(inp_file);
}
If you happen to have a compiler with C++11 support, you could use std::to_string(). For example:
for (int i = 0; i < n; ++i) {
// Generate /path/in1 etc
std::string inp_file = "/path/in" + std::to_string(i);
open(inp_file);
}
Hope it helps. Good Luck!

Addendum to Vlad's answer -- if for some reason you're not able/willing to use Boost, you can accomplish what you want using standard C++ with the stringstream class:
#include <sstream>
void Foo() {
for (int i = 0; i < n; ++i) {
std::stringstream converter;
converter << "/path/in" << i;
open(converter.str());
}
}

If you're not using boost, try this:
namespace StringUtils
{
// Converts any type which implements << to string (basic types are alright!)
template<typename T>
std::string StringUtils::toString(const T &t)
{
std::ostringstream oss;
oss << t;
return oss.str();
}
}
Use it this way:
for(int i=0;i<n;i++)
{
string inp_file="/path/"+"in"+ StringUtils::toString(i); //to generate /path/in1 etc
open(inp_file);
}

Just an addition to the existing answers which are all great, if you are using a newer compiler and standard library, c++11 introduces std::to_string(). So you can write code like this:
for(int i = 0; i < n; i++) {
string inp_file = "/path/in"+ std::to_string(i);
open(inp_file);
}

The C solution is this :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int n =4;
char nstr[12];
sprintf(nstr, "%d", n);
int nlen = strlen( nstr );
const char *fd = "/path/in";
char buff[ strlen(fd) + nlen + 1 ];
sprintf( buff, "%s%d", fd, n );
/* for testing */
printf( "%s\n", buff );
}

Related

C++ How to write function that return char pointer

I want to write a function that receive an int argument then converter to a char pointer (c-string), but my code output is not right.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
char *stoc(int n){
stringstream stream;
stream <<"Log"<<n<<".txt";
string name;
stream >>name;
int len = name.length();
char ch[len+1];
for(int i=0; i<len; i++){
ch[i]=name[i];
}
ch[len+1] = '\0';
return ch;
}
int main() {
char *name = stoc(3);
cout << name << endl;
return 0;
}
Summarising the comments:
You normally do not use C-style-strings in C++, just stick to std::strings. Therefor you should rather return name instead of your converted ch, especially since you have already created a std::string. Having access to at least C++11 you can then easily convert your rather long function into a one-liner
C++11
std::string stoc(int n) {
return "Log" + std::to_string(n) + ".txt";
}
prior C++11
std::string stoc(int n) {
std::ostringstream oss;
oss << "Log" + n + ".txt";
return oss.str(); // by accessing a stringstreams content directly there is no need to use an extra variable
}
If you do need to use a C-style-string later on somewhere, e.g. as a parameter for a C-library function, you can use c_str to convert any std::string into it's C-style equivalent:
int main() {
std::string name = stoc(3);
std::cout << name << std::endl;
}
You should do this instead of returning a pointer to a local variable (which yields in undefined behaviour):
...
char *ch = new char[len+1];
for(int i=0; i<len; i++){
ch[i]=name[i];
}
ch[len] = '\0';
...
int main() {
char *name = stoc(3);
cout << name << endl;
delete [] name; // delete what has been allocated in stoc
return 0;
}
Also note the ch[len] = '\0' instead of ch[len + 1] = '\0'.
But in C++ you should rather use std::string and not deal with char arrays, new and delete at all.

C++ SDL 2.0 - Importing multiple textures using a loop

I don't know whether or not this is possible but I have used this technique in different languages but am struggling to use it in C++. I have 10 images that I am trying to load into an array using a loop as so:
for (int i = 0; i < 10; i++)
{
Sprite[i] = IMG_LoadTexture(renderer, "Graphics/Player" + i + ".png");
}
This however does not seem to work in C++ so I was wondering what I am doing wrong, or what can I do to get the same result without having to load each image individually like so:
Sprite[0] = IMG_LoadTexture(renderer, "Graphics/Player0.png");
My error is: "Expression must have integral or unscoped enum type"
Thanks for any help =)
You cannot do this:
"This is my number: " + (int)4 + "!";
This is illegal. It will give you an error for trying to operator+ a const char* and a const char[SOME_INT_GOES_HERE] or another error for trying to use operator+ to add an int onto a string. Things just don't work that way.
You'd either have to use C (i.e. snprintf()) or a string stream. Here's my test code for isolating your problem:
#include <iostream>
#include <string>
int main()
{
int a = 1;
std::string str = "blah";
std::string end = "!";
//std::string hello = str + a + end;// GIVES AN ERROR for operator+
std::string hello = "blah" + a + "!";
//const char* c_str = "blah" + a + "end";
//std::cout << c_str << std::endl;
std::cout << hello << std::endl;
return 0;
}
Here's an alternative solution using string streams.
#include <iostream>
#include <string>
#include <sstream>
int main()
{
int i = 0;
std::string str;
std::stringstream ss;
while (i < 10)
{
//Send text to string stream.
ss << "text" << i;
//Set string to the text inside string stream
str = ss.str();
//Print out the string
std::cout << str << std::endl;
//ss.clear() doesn't work. Calling a constructor
//for std::string() and setting ss.str(std::string())
//will set the string stream to an empty string.
ss.str(std::string());
//Remember to increment the variable inside of while{}
++i;
}
}
Alternatively, you can also use std::to_string() if you're using C++11 (which just requires -std=c++11) but std::to_string() is broken on some sets of compilers (i.e. regular MinGW). Either switch to another flavor where it works (i.e. MinGW-w64) or just write your own to_string() function using string streams behind the scenes.
snprintf() may be the fastest way of doing such a thing, but for safer C++ and better style, it is recommended you use a non-C way of doing things.
I had a similar problem and I solwed it this way:
#include <iostream>
using namespace std;
int main() {
string line;
for (int i = 0; i < 10; i++) {
line = "Graphics/Player" + inttostr(i) + ".png"; //I wrote inttostr function because built in inttostr functions messed up my program (see below)
char charger[line.length()]; //creating char array
for (int i = 0; i < sizeof(line); i++) {
charger[i] = line[i]; // copying string to char arry
}
Sprite[i] = IMG_LoadTexture(renderer, charger);
}
}
string inttostr(int integer) { //I know it isn't the best way to convert integer to string, but it works
string charakter;
int swap;
bool negativ = false;
if (integer < 0) {
integer = -integer;
negativ = true;
}
if (integer == 0) {
charakter = "0";
}
while (integer >= 1) {
swap = integer % 10;
integer = integer / 10;
charakter = char(swap + 48) + charakter;
}
if (negativ) {
charakter = "-" + charakter;
}
return charakter;
}

Dereferencing an unsigned char pointer and storing its values into a string

So I am working on a tool that dereferences the values of some addresses, it is in both C and C++, and although I am not familiar with C++ I figured out I can maybe take advantage of the string type offered by C++.
What I have is this:
unsigned char contents_address = 0;
unsigned char * address = (unsigned char *) add.addr;
int i;
for(i = 0; i < bytesize; i++){ //bytesize can be anything from 1 to whatever
if(add.num == 3){
contents_address = *(address + i);
//printf("%02x ", contents_address);
}
}
As you can see what I am trying to do is dereference the unsigned char pointer. What I want to do is have a string variable and concatenate all of the dereferenced values into it and by the end instead of having to go through a for case for getting each one of the elements (by having an array of characters or by just going through the pointers) to have a string variable with everything inside.
NOTE: I need to do this because the string variable is going to a MySQL database and it would be a pain to insert an array into a table...
Try this that I borrowed from this link:
http://www.corsix.org/content/algorithmic-stdstring-creation
#include <sstream>
#include <iomanip>
std::string hexifyChar(int c)
{
std::stringstream ss;
ss << std::hex << std::setw(2) << std::setfill('0') << c;
return ss.str();
}
std::string hexify(const char* base, size_t len)
{
std::stringstream ss;
for(size_t i = 0; i < len; ++i)
ss << hexifyChar(base[i]);
return ss.str();
}
I didn't quite understand what you want to do here (why do you assign a dereferenced value to a variable called ..._address)?.
But maybe what you're looking for is a stringstream.
Here's a relatively efficient version that performs only one allocation and no additional function calls:
#include <string>
std::string hexify(unsigned char buf, unsigned int len)
{
std::string result;
result.reserve(2 * len);
static char const alphabet[] = "0123456789ABCDEF";
for (unsigned int i = 0; i != len)
{
result.push_back(alphabet[buf[i] / 16]);
result.push_back(alphabet[buf[i] % 16]);
{
return result;
}
This should be rather more efficient than using iostreams. You can also modify this trivially to write into a given output buffer, if you prefer a C version which leaves allocation to the consumer.

char*-Array as Parameter

I want to put the following code in a function: (The code isn't complete, but I think it should be clear to you)
char *parsedData[SEPERATOR];
for(int i=0; i<SEPERATOR; i++)
{
parsedData[i]=tmp;
}
The function should look like the following:
int main()
{
char *parsedData[SEPERATOR];
Parser(WTString, parsedData);
}
int Parser(char *WTString, *parsedData[SEPERATOR])
{
for(int i=0; i<SEPERATOR; i++)
{
parsedData[i]=tmp;
}
}
The code works fine in one function. By dividing the code in two functions I got no usable data.
I would be grateful if someone could help me. I don't want to use further libraries.
If you don't want to use stl, I propose this function:
int PointToDefault(char* target, char** parsedData, unsigned int count)
{
for (unsigned int i=0; i<count; i++)
{
parsedData[i] = target;
}
}
and this call:
#define SEPERATOR 15
int main()
{
char tmp[] = "default string";
char *parsedData[SEPERATOR];
PointToDefault(tmp, parsedData, SEPERATOR);
}
char *parsedData[SEPERATOR]; Why?
Why do you need to use a raw array of pointers to char in C++?
Why don't you just use a std::vector<std::string> and spare yourself a whole load of misery and despair.
A C++ way of doing it would look like this:
#include <string>
#include <vector>
std::vector<std::string> Parser(const char *WTString)
{
std::vector<std::string> result;
for(std::size_t i = 0; i != SEPERATOR; ++i)
{
result.push_back(tmp); // whatever tmp is
}
return result;
}
I dont want to use further librarys.
Don't worry, my code sample only requries the standard library.

How to generate 'consecutive' c++ strings?

I would like to generate consecutive C++ strings like e.g. in cameras: IMG001, IMG002 etc. being able to indicate the prefix and the string length.
I have found a solution where I can generate random strings from concrete character set: link
But I cannot find the thing I want to achieve.
A possible solution:
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
std::string make_string(const std::string& a_prefix,
size_t a_suffix,
size_t a_max_length)
{
std::ostringstream result;
result << a_prefix <<
std::setfill('0') <<
std::setw(a_max_length - a_prefix.length()) <<
a_suffix;
return result.str();
}
int main()
{
for (size_t i = 0; i < 100; i++)
{
std::cout << make_string("IMG", i, 6) << "\n";
}
return 0;
}
See online demo at http://ideone.com/HZWmtI.
Something like this would work
#include <string>
#include <iomanip>
#include <sstream>
std::string GetNextNumber( int &lastNum )
{
std::stringstream ss;
ss << "IMG";
ss << std::setfill('0') << std::setw(3) << lastNum++;
return ss.str();
}
int main()
{
int x = 1;
std::string s = GetNextNumber( x );
s = GetNextNumber( x );
return 0;
}
You can call GetNextNumber repeatedly with an int reference to generate new image numbers. You can always use sprintf but it won't be the c++ way :)
const int max_size = 7 + 1; // maximum size of the name plus one
char buf[max_size];
for (int i = 0 ; i < 1000; ++i) {
sprintf(buf, "IMG%.04d", i);
printf("The next name is %s\n", buf);
}
char * seq_gen(char * prefix) {
static int counter;
char * result;
sprintf(result, "%s%03d", prefix, counter++);
return result;
}
This would print your prefix with 3 digit padding string. If you want a lengthy string, all you have to do is provide the prefix as much as needed and change the %03d in the above code to whatever length of digit padding you want.
Well, the idea is rather simple. Just store the current number and increment it each time new string is generated. You can implement it to model an iterator to reduce the fluff in using it (you can then use standard algorithms with it). Using Boost.Iterator (it should work with any string type, too):
#include <boost/iterator/iterator_facade.hpp>
#include <sstream>
#include <iomanip>
// can't come up with a better name
template <typename StringT, typename OrdT>
struct ordinal_id_generator : boost::iterator_facade<
ordinal_id_generator<StringT, OrdT>, StringT,
boost::forward_traversal_tag, StringT
> {
ordinal_id_generator(
const StringT& prefix = StringT(),
typename StringT::size_type suffix_length = 5, OrdT initial = 0
) : prefix(prefix), suffix_length(suffix_length), ordinal(initial)
{}
private:
StringT prefix;
typename StringT::size_type suffix_length;
OrdT ordinal;
friend class boost::iterator_core_access;
void increment() {
++ordinal;
}
bool equal(const ordinal_id_generator& other) const {
return (
ordinal == other.ordinal
&& prefix == other.prefix
&& suffix_length == other.suffix_length
);
}
StringT dereference() const {
std::basic_ostringstream<typename StringT::value_type> ss;
ss << prefix << std::setfill('0')
<< std::setw(suffix_length) << ordinal;
return ss.str();
}
};
And example code:
#include <string>
#include <iostream>
#include <iterator>
#include <algorithm>
typedef ordinal_id_generator<std::string, unsigned> generator;
int main() {
std::ostream_iterator<std::string> out(std::cout, "\n");
std::copy_n(generator("IMG"), 5, out);
// can even behave as a range
std::copy(generator("foo", 1, 2), generator("foo", 1, 4), out);
return 0;
}
Take a look at the standard library's string streams. Have an integer that you increment, and insert into the string stream after every increment. To control the string length, there's the concept of fill characters, and the width() member function.
You have many ways of doing that.
The generic one would be to, like the link that you showed, have an array of possible characters. Then after each iteration, you start from right-most character, increment it (that is, change it to the next one in the possible characters list) and if it overflowed, set it to the first one (index 0) and go the one on the left. This is exactly like incrementing a number in base, say 62.
In your specific example, you are better off with creating the string from another string and a number.
If you like *printf, you can write a string with "IMG%04d" and have the parameter go from 0 to whatever.
If you like stringstream, you can similarly do so.
What exactly do you mean by consecutive strings ?
Since you've mentioned that you're using C++ strings, try using the .string::append method.
string str, str2;
str.append("A");
str.append(str2);
Lookup http://www.cplusplus.com/reference/string/string/append/ for more overloaded calls of the append function.
it's pseudo code. you'll understand what i mean :D
int counter = 0, retval;
do
{
char filename[MAX_PATH];
sprintf(filename, "IMG00%d", counter++);
if(retval = CreateFile(...))
//ok, return
}while(!retval);
You have to keep a counter that is increased everytime you get a new name. This counter has to be saved when your application is ends, and loaded when you application starts.
Could be something like this:
class NameGenerator
{
public:
NameGenerator()
: m_counter(0)
{
// Code to load the counter from a file
}
~NameGenerator()
{
// Code to save the counter to a file
}
std::string get_next_name()
{
// Combine your preferred prefix with your counter
// Increase the counter
// Return the string
}
private:
int m_counter;
}
NameGenerator my_name_generator;
Then use it like this:
std::string my_name = my_name_generator.get_next_name();