1

apologies if this is a basic question but I haven't been able to figure it out from other posts. I'm trying to read a bunch of images that are labelled "1.jpg" "2.jpg" "3.jpg" etc. I'd like to do so using a for loop. The file reader (I'm using SOIL here, as recommended in the OpenGL nehe tutorial I'm following), requires a const char* as the filename input.

char numbers[6] = "123456"; 

for (int i=0;i<6;i++)
{
   const char* filestring = new char[5];
   *filestring = numbers[i] + ".jpg";

   texture[i] = SOIL_load_OGL_texture(filestring, ...
   ...  // filestring should be const char* form
}

The errors are:

(1) error: initializer-string for array of chars is too long [-fpermissive]

but i don't see what is wrong with char numbers[6] = "123456"?

error: assignment of read-only location '* filestring'

error: invalid conversion from 'const char*' to 'char' [-fpermissive]

I'm a bit baffled. Would be grateful for any advice!

Thanks.

James M
  • 18,506
  • 3
  • 48
  • 56
3lbom
  • 139
  • 1
  • 1
  • 11

5 Answers5

3

Change this:

char numbers[6] = "123456";

To this:

const char numbers[] = "123456";

The size of the array is determined automatically by the compiler, so you don't need to specify it explicitly. You are trying to set it too small anyway because it is actually 7 bytes wide because of the trailing null terminator.

It's not strictly necessary for it to be const, but it makes it clearer what your intention is if you do mark it as such.

Also, this won't work:

*filestring = numbers[i] + ".jpg";

You can't concatenate C strings that way. Easiest thing to do would be this:

string filestring = string(1, numbers[i]) + ".jpg";

When you need to use it as a C string you can do this:

SOIL_load_OGL_texture(filestring.c_str(), ...
spencercw
  • 3,320
  • 15
  • 20
  • You might want to explain to him *why* that's the problem. – Perry Feb 27 '12 at 17:31
  • "because it resides in the read-only area"... no it doesn't. Read http://stackoverflow.com/questions/7082786/char-array-vs-char – Ben Voigt Feb 27 '12 at 17:39
  • Re "your string literal needs to be declared `const`": only if the variable is a pointer. Here, it's a local array initialised by copying a string literal, and so doesn't need to be `const`. Although perhaps it should be `const char *` in this case. – Mike Seymour Feb 27 '12 at 17:40
  • Thanks all for your helpful explanations & array of solutions! Very much appreciated – 3lbom Feb 27 '12 at 20:37
2

I don't see what is wrong with char numbers[6] = "123456"

Write it like this:

char numbers[6] = { '1', '2', '3', '4', '5', '6', 0 };

That's exactly equivalent. Do you see the problem now?


numbers[i] + ".jpg"

That's not string concatenation. In fact, since numbers[i] == 0x31 + i (for i = 0 to 5), that gives

&(".jpg"[49 + i])

which is a pointer to an address off the end of the string literal.

In C, sprintf would be useful here, but remember to leave room for the terminating NUL. In C++, use std::string.

Better version:

char filestring[] = "n.jpg";
for( int i = 0; i < 6; i++ ) {
    filestring[0] = '1' + i;
    texture[i] = //...
}
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
1
std::string numbers [count] = { "1", "2", "3", ... }
for (int i = 0; i < count; ++i) {
  std::string filename = numbers[i] + ".jpg";
  texture[i] = SOIL_load_OGL_texture(filename, ...
  //or
  //texture[i] = SOIL_load_OGL_texture(filename.c_str(), ...
}
hired777
  • 485
  • 3
  • 10
0

It'd be cleaner to do it like this:

for(int i = 0; i < 6; i ++)
{
    char filename[8];
    sprintf(filename, "%d.jpg", i + 1);
    texture[i] = SOIL_load_OGL_texture(filename, ... 
James M
  • 18,506
  • 3
  • 48
  • 56
0

Using an ostringstream:

#include <sstream>
...
...
for (int i = 0; i < 6; i++)
{
  std::ostringstream ss;
  ss << i << ".jpg";

  texture[i] = SOIL_load_OGL_texture(ss.str().c_str(), ...
}
nerozehl
  • 463
  • 1
  • 7
  • 19