Sam Thers
Sam Thers

Reputation: 67

Array out of bounds, index -1

I basically want to store a array of student names, based on a given number. For example, if the user wants to insert 5 names, then the array size will be 5. If the user wants to insert 10 names, then the array size will be 10.

I have a method like this to set a name to a specific element in an array.

void setNames(char *names){
     strcpy(name[i], names);
}

Thing is, how do I do array bound checks? I heard that you can only add when the index is -1.

Upvotes: 1

Views: 172

Answers (4)

Paulo Lieuthier
Paulo Lieuthier

Reputation: 446

When programming in C/C++ (unless using C++11 or newer), you will manipulate arrays as pointers. That means you won't know the size of an array unless you save it. What char str[10] really means is str's address + 10 * sizeof(char). You are directly dealing with memory here.

If you want a high level approach for that, take a look at C++11. std::array and std::vector are there for you. From the documentation, look how std::array is defined:

template <
    class T,
    std::size_t N
> struct array;

It means it stores its own size and has useful functions as well, such as size(), at(), back() etc.

Upvotes: 0

chux
chux

Reputation: 154592

C code needs to keep track of the array size in another variable.

typedef struct {
  char **name;
  size_t n;
} Names_T;

void Names_Set(Names_T *names, size_t index, const char *name) {
  // See if it is a special value and then append to the array
  if (index == (size_t) -1) {
    index = names->n;
  }
  if (index >= names->n) {
    size_t newsize = index + 1;
    // OOM error handling omitted
    names->name = realloc(names->name, newsize * sizeof *names->name);
    while (names->n < newsize) {
      names->name[names->n++] = NULL;
    }
  }
  char *oldname = names->name[index];
  names->name[index] = strdup(name);
  free(oldname);
}

void Names_Delete(Names_T *names) {
  while (names->n > 0) {
    names->n--;
    free(&names->name[names->n]);
    names->name[names->n] = NULL;
  }
  free(names->name);
  names->name = NULL;
}

int main(void) {
  Names_T names = { NULL, 0 };
  Names_Set(&names, 3, "Sam");              // set array element 3
  Names_Set(&names, (size_t) -1, "Thers");  // Append to array
  Names_Delete(&names);
  return 0;
}

Upvotes: 0

syntagma
syntagma

Reputation: 24354

EDIT (as the OP indicated he actually wants C):

C answer

What you can do is either create a char array:

char [N][name_length]

where N - number "user wants" (I assume the user will somehow input it into your program), name_length - maximum length the name can have (a C-string, i.e. null-terminated string).

or create an array of your own structs (each holding a separate name and maybe some other information).


C++ answer

A typical way to do this in C++ is by using std::vector<std::string> (assuming you only want to store names, as std::string).

You then add new elements using using push_back() function. And, as vector is implemented as a dynamic array in C++, you won't have to do bound checking.

Upvotes: 1

ash
ash

Reputation: 3484

Arrays don't maintain their own size, you have to do that for them. This is part of the reason why vectors are so much easier to deal with, and why everyone will say "wtf, raw arrays? use a vector". An array is just a contiguous chunk of memory, thats it. a vector contains an array, and lets you use it like an array to some extent, but it handles a lot of the housekeeping details for you.

Anyway, if you really want to use a raw array, then you'll need to pass around size information along with it. C strings are a null-terminated array -- just a plain old array, but the last element is \0. This way you can read from it without knowing it's size ahead of time, just don't read past the null character at the end (dragons be there).

Upvotes: 1

Related Questions