I want to delete images from a file, the images are named: "1.jpg, 2.jpg ....", i have tried the code above but it gives me this error: no matching function for call to 'remove(std::__cxx11::string&)'
int i;
for (i=0;i<frame;i++)//frame contain the number of images i want to delete
{
std::stringstream ss;
ss << i;
std::string str = ss.str();
const char *cstr = str.c_str();
str=str+".jpg";
remove(str);
}
If someone can help thank you in advence.
You almost have it. remove requires a const char*, not a std::string. That means you need
remove(str.c_str());
We can also get rid of the stringstream and use std::to_string instead in something like
for (i=0; i<frame; i++)
{
const std::string str = to_string(i) + ".jpg";
remove(str.c_str());
}
Related
So I have this issue
//This holds 5 messages submitted prev by the user, temporarily stored
string arrayOfMessages[5];
lets say
arrayOfMessages[0]="This is my message"//The message in the first position.
I need to copy arrayOfMessages[0] to an array of char like this one;
char message [20];
I tried using strcpy(message,arrayOfMessages[0]) but I get this error :
error: cannot convert 'std::__cxx11::string' {aka 'std::__cxx11::basic_string<char>'} to 'const char*'|
Anyone know how I can accomplish this or if I'm doing something wrong, I cant set the string to be a const char bc the message was imputed prev by the user so it changes every time you run the program thus cannot be a constant variable.
There are many ways of doing it
By using the c_str() function of the string class
string message = "This is my message";
const char *arr;
arr = message.c_str();
By copying all the characters from the string to the char array
string message = "This is my message";
char arr[200];
for(int i = 0; i < 200 && message[i] != '\0'; i++){
arr[i] = message[i];
}
Be careful with the array sizes if you use the second approach.
You can also make it a function in order to make it easier to use
void copyFromStringToArr(char* arr, string str, int arrSize){
for(int i = 0; i<arrSize && str[i] != '\0'; i++){
arr[i] = str[i];
}
}
So in your case you can just call the function like this:
copyFromStringToArr(message,arrayOfMessages[0],20);
Also I am sure there are many more ways to do it but these are the ones I would use.
To copy the contents of std::string into a char[], use c_str():
std::string str = "hello";
char copy[20];
strcpy(copy, str.c_str());
But the datatype of copy must be only char* and not const char*. If you want to assign it to a const char*, then you can use direct assignment:
std::string str = "hello";
const char *copy = str.c_str();
I got an issue with sprintf buffer.
As you can see in the code down below I'm saving with sprintf a char array to the buffer, so pFile can check if there's a file named like that in the folder. If it's found, the buffer value will be assigned to timecycles[numCycles], and numCycles will be increased. Example: timecycles[0] = "timecyc1.dat". It works well, and as you can see in the console output it recognizes that there are only timecyc1.dat and timecyc5.dat in the folder. But as long as I want to read timecycles with a for loop, both indexes have the value "timecyc9.dat", eventhough it should be "timecyc1.dat" for timecycles[0] and "timecyc5.dat" for timecycles1. Second thing is, how can I write the code so readTimecycles() returns char* timecycles, and I could just initialize it in the main function with char* timecycles[9] = readTimecycles() or anything like that?
Console output
#include <iostream>
#include <cstdio>
char* timecycles[9];
void readTimecycles()
{
char buffer[256];
int numCycles = 0;
FILE* pFile = NULL;
for (int i = 1; i < 10; i++)
{
sprintf(buffer, "timecyc%d.dat", i);
pFile = fopen(buffer, "r");
if (pFile != NULL)
{
timecycles[numCycles] = buffer;
numCycles++;
std::cout << buffer << std::endl; //to see if the buffer is correct
}
}
for (int i = 0; i < numCycles; i++)
{
std::cout << timecycles[i] << std::endl; //here's the issue with timecyc9.dat
}
}
int main()
{
readTimecycles();
return 0;
}
With the assignment
timecycles[numCycles] = buffer;
you make all pointers point to the same buffer, since you only have a single buffer.
Since you're programming in C++ you could easily solve your problem by using std::string instead.
If I would remake your code into something a little-more C++-ish and less C-ish, it could look something like
std::array<std::string, 9> readTimeCycles()
{
std::array<std::string, 9> timecycles;
for (size_t i = 0; i < timecycles.size(); ++i)
{
// Format the file-name
std::string filename = "timecyc" + std::to_string(i + 1) + ".dat";
std::ifstream file(filename);
if (file)
{
// File was opened okay
timecycles[i] = filename;
}
}
return timecycles;
}
References:
std::array
std::string
std::to_string
std::ifstream
The fundamental problem is that your notion of a string doesn't match what a 'char array' is in C++. In particular you think that because you assign timecycles[numCycles] = buffer; somehow the chars of the char array are copied. But in C++ all that is being copied is a pointer, so timecycles ends up with multiple pointers to the same buffer. And that's not to mention the problem you will have that when you exit the readTimecycles function. At that point you will have multiple pointers to a buffer which no longer exists as it gets destroyed when you exit the readTimecycles function.
The way to fix this is to use C++ code that does match your expectations. In particular a std::string will copy in the way you expect it to. Here's how you can change your code to use std::string
#include <string>
std::string timecycles[9];
timecycles[numCycles] = buffer; // now this really does copy a string
So I have a function returning a std::string as follows:
string ReadShaderSource(const char* filename, GLint& shaderSize) // Load the shader source code.
{
ifstream::pos_type size;
string text;
ifstream file(filename, ios::in | ios::binary | ios::ate);
if (file.is_open())
{
size = file.tellg();
shaderSize = (GLuint)size;
text.resize(size);
file.seekg(0, ios::beg);
file.read(&text[0], text.size());
file.close();
return text;
}
else
{
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error!",
"Could not load the shader source code from the file.", NULL);
Lunar::Exit();
}
return "";
}
But When I call the function like this:
const char* testStr = ReadShaderSource("test.glsl", size).c_str();
The value of testStr is full of this:
0x036fdcd8
"îþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþ...
Which makes no sense. The function returns the right value, so when I return text in the function it contains the source code of the shader, but when I do
const char* testStr = ReadShaderSource("test.glsl", size).c_str();
testStr is full of rubbish.
Any ideas?
Thank you!
You need to use
string str = ReadShaderSource("test.glsl", size);
const char* testStr = str.c_str();
instead of
const char* testStr = ReadShaderSource("test.glsl", size).c_str();
When you use the second form, you are storing a pointer in testStr that is not valid any more since the returned value of the function is a temporary string.
As was pointed out by #IInspectable, you could also use a const& to extend the lifetime of the temporary object.
string const& str = ReadShaderSource("test.glsl", size);
const char* testStr = str.c_str();
The following program is well behaved:
#include <iostream>
#include <string>
std::string foo()
{
return "This is a test.";
}
void bar(std::string const& str)
{
std::cout << str.c_str() << std::endl;
}
int main()
{
std::string const& str = foo();
bar(str);
std::cout << str.c_str() << std::endl;
}
Re
“when I do const char* testStr = ReadShaderSource("test.glsl", size).c_str(); testStr is full of rubbish.”
you're initializing the pointer to point to a buffer in a temporary string, that has ceased to exist already when the initialization finishes.
Instead use a string for the result variable.
Note that the conclusion that the function returns garbage is unwarranted, it does not follow from that observation of garbage, but might still be true.
You should test anew, with proper result variable type, to check that.
whats the best way of creating a 'const char*' using available variables? For example, a function requires a const char* as a parameter to locate a file i.e. "invader1.png". If I have 5 different invader images, how can I iterate from 1:5 so "Invader1.png".."Invader2.png..etc etc
so i want "invader" + %d + ".png"
i tried sprintf and casting but to no avail.
I hope my description makes sense, thanks
update with code:
for (int y=0; y<250; y+=50){
stringstream ss;
ss << "invader" << (y/50) << ".png";
const char* rr = ss.str().c_str();
printf("%s", rr);
for (int x=0; x<550;x+=50){
Invader inv(rr, x+50, y+550, 15, 15, 1, false, (y/50 + 50));
invaders[i] = inv;
i++;
}
}
Use std::stringstream. Something like this:
std::stringstream ss;
ss << "invader" << my_int << ".png";
my_func(ss.str().c_str());
Since you're using C++, you can simply use std::string and then use the c_str() function to get a const char* which you can pass to the function. One simple way to construct such strings is to use std::ostringstream from <sstream>:
for (int i = 1; i <= 5; ++i) {
std::ostringstream ss;
ss << "invader" << i << ".png";
foo(ss.str().c_str()); // where foo is the specified function
}
You could also use sprintf() and a character array, but then you need to pay attention to things like the size of the buffer. For the sake of completeness, here's how to do the same with sprintf, but I suggest you go with the std::string approach, which is more C++-like:
for (int i = 1; i <= 5; ++i) {
char buf[13]; // big enough to hold the wanted string
std::ostringstream ss;
sprintf(buf, "invader%d.png", i);
foo(buf); // where foo is the specified function
}
Then i would guess your looking to cast an int variable to char, so you can iterate through your invader%d.png files.
Have you tried itoa function ?
http://www.cplusplus.com/reference/clibrary/cstdlib/itoa/
I'm using a stringstream to generate "dynamically", the name of the files I need to open and this is my code:
for (int img=0; img<5; img++)
{
stringstream stream;
string *s=new string("myfile");
stream << img << ".png"
s->append(stream.str());
.. other code
the problem is than the first time the program flows into the loop it works fine, the second time stream does not has the value "1.png", but has value null... so when I try to open the file I get a null pointer.
ho do I fix this?
A simpler solution:
for (int img = 0; img < 5; ++img)
{
std::string s = "myfile" + ('0' + img) + ".png";
// do something useful with s
}
If numbers are bigger than 9, you can use std::to_string(img) instead.
Try allocating your string before your loop.
string *s = new string("myfile");
for(;;;){} //forloop
// use s here.
delete s; // always delete dynamically allocated memory.