1

I need your help with C/С++ arrays. I've been programming in Python for three years, and its array (which is called list) is pretty easy to work with.

>>> array = [1,2,3,4]
>>> array.append(5)
>>> array
[1,2,3,4,5]

As I've read in C/C++ I need to create a pointer to array. Could you, please, make a small sketch of class which contains array of char and has only one method append, which is called append and receives a char as a parameter. This method increases size of array by 1 and adds the given char to this array.

Someone may think that this is a homework, but I just can't understand the principle of how arrays, pointers and memory allocation work. I guess it's not hard, but it's hurd after languages like Python, because I didn't care about such things in Python. Could you, please, provide a small piece of code with explanations?

Thanks in advance!

Shoe
  • 74,840
  • 36
  • 166
  • 272
ghostmansd
  • 3,285
  • 5
  • 30
  • 44
  • 1
    Look up `std::string` for char arrays. http://www.cplusplus.com/reference/string/string/ – Coding Mash Nov 24 '12 at 15:14
  • 1
    "I guess it's not hard, but it's hard after languages like Python, because I didn't care about such things in Python." - And I'm being snubbed and being told that C is not good as a first programming language... –  Nov 24 '12 at 15:14
  • 4
    Step one: stop talking about C/C++. There's no such thing. Either you're coding in C, or in C++. C++ has a lot of standard containers you can use. – Mat Nov 24 '12 at 15:14
  • Bear in mind that a python list is quite different to a C or a C++ array, or any of the C++ standard library containers. In C++, containers can only hold elements of the same type. In python, you could append e.g. a string to the list in your example. – juanchopanza Nov 24 '12 at 15:21
  • 1
    @Mat: *"Either you're coding in C, or in C++."* -- That's not true. You can code in both at the same time. There are, in fact, many very popular libraries which are written with the specific intention of being able to compile both as C, and as C++. So, you can consider C/C++ as the intersection of the two languages. – Benjamin Lindley Nov 24 '12 at 15:31
  • @BenjaminLindley: you can write libraries in Fortran and link that to C and/or C++, so should Fortran/C/C++ be considered as a language too? The fact that you can make headers (and some code) that is valid and idiomatic in both languages doesn't mean they're the same. – Mat Nov 24 '12 at 15:35
  • 2
    @BenjaminLindley that doesn't mean that C and C++ are not two different (and not interchangeable) languages. –  Nov 24 '12 at 15:35
  • 1
    @Mat and H2CO3: I don't see how what you said applies to my comment. I didn't say they were the same. I said that C/C++ can be considered the intersection of C and C++. So, if someone asks how to do something in C/C++, then you don't recommend variable length arrays, and you don't recommend `std::vector`. – Benjamin Lindley Nov 24 '12 at 15:37
  • @Mat: If you write a program or library that is can compile as C, C++ or as Fortran, then fine, call it Fortran/C/C++. Linking though is not the same as compiling, and would require two seperate compilers. – Benjamin Lindley Nov 24 '12 at 15:39
  • @BenjaminLindley I understand, but in general, saying it is an error. There are corner cases for which even the syntactically common subset of C and C++ behaves differently. –  Nov 24 '12 at 15:41
  • You can learn all about arrays in C++ here: http://stackoverflow.com/questions/4810664/how-do-i-use-arrays-in-c. – R. Martinho Fernandes Nov 24 '12 at 15:44

5 Answers5

5

This is a standard C++ program:

#include <iostream>
#include <vector>
using namespace std;

int main()
{
    vector<int> array = {1, 2, 3, 4};
    array.push_back( 5 );

    for( auto const item : array )
    {
        cout << item << " ";
    }
    cout << endl;
}

Visual C++ specific.

Even the latest version of Microsoft’s Visual C++, namely the November 2012 CTP, which is version 11.0 with a bunch of fixes to support the C++11 standard, does not yet support the general initialization used above.

With Visual C++, as in C++03, that notation is only supported for so called aggregate types, which essentially are pure raw arrays or pure raw structs (which may contain more C++'ish types), or built-in types. So with Visual C++ one way to do this is to use that notation for a raw array, and then use that raw array to initialize the vector:

#include <iostream>
#include <iterator>     // std::begin, std:.end
#include <vector>
using namespace std;

int main()
{
    int const   data[]  = {1, 2, 3, 4};
    vector<int> array( begin( data ), end( data ) );
    array.push_back( 5 );

    for( auto const item : array )
    {
        cout << item << " ";
    }
    cout << endl;
}

And this compiles fine also with the base Visual C++ 11.0 as shipped with Visual Studio 2012.

However, the range based for loop will probably not compile with Visual C++ 10.0 (corresponding to Visual Studio 2010).

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • 1
    List initializers for vectors are only for C++11 – Sebastian Cabot Nov 24 '12 at 15:24
  • 1
    @SebastianCabot ...and so is auto, and range-based loops. Still standard, though. :-) – HostileFork says dont trust SE Nov 24 '12 at 15:27
  • 2
    @SebastianCabot: C++11 is the current C++ standard. – Cheers and hth. - Alf Nov 24 '12 at 15:27
  • @HostileFork and author: I'm well aware this is the latest standard as you two are well aware that there is no single compiler out there that implements it in full. GCC comes close but even GCC still doesn't implement it all. And I see you have edited your answer. Good - now I can upvote it. Although you are making his life easy. It's really bad advise to go with vector when you don't know how a regular array works. – Sebastian Cabot Nov 24 '12 at 15:31
  • @Sebastian: can you explain what intricate knowledge of how a "regular array" works is necessary to use vector properly? – R. Martinho Fernandes Nov 24 '12 at 15:32
  • @R.MartinhoFernandes - It's not necessary to use vector - It's necessary to use C++. – Sebastian Cabot Nov 24 '12 at 15:33
  • @Sebastian Oh. But it so happens that knowing vector is also necessary to use C++. I fail to see the point, then. – R. Martinho Fernandes Nov 24 '12 at 15:35
  • @R.MartinhoFernandes - I don't agree std::vector is API. It's very useful API but you can write it yourself if you know how "regular arrays" work - not the other way around. – Sebastian Cabot Nov 24 '12 at 15:36
  • @SebastianCabot Hmm, nope. You don't build vectors out of "regular arrays". You build vectors out of functions to allocate and release uninitialized storage, and features to invoke constructors and destructors directly (placement new, explicit destructor calls). Maybe that's what we should be teaching people. – R. Martinho Fernandes Nov 24 '12 at 15:39
  • You could, but that's completely irrelevant and nobody does. – Puppy Nov 24 '12 at 15:39
  • @R.MartinhoFernandes You are right. People should know what memory is and how to access it, how to allocate it and how to free it. How to allocate it on the stack using "regular arrays" and how to allocate it dynamically as if they were "regular arrays". And if you read the question this is just what he asked for. – Sebastian Cabot Nov 24 '12 at 15:41
  • Hm, maybe I should add info on how to abuse the comma operator to get C++03 compatible code closer to Python? ... he he, no – Cheers and hth. - Alf Nov 24 '12 at 15:42
  • @DeadMG I don't create it myself never will. But there are plenty of opportunities for one to create similar containers to do some specific job. Hope you did it at least once... – Sebastian Cabot Nov 24 '12 at 15:43
  • 3
    You're not a real C++ programmer until you write the compiler yourself, using only the letter 'o'. http://search.dilbert.com/comic/We%20Didn't%20Have%20Zeros – HostileFork says dont trust SE Nov 24 '12 at 15:49
2

C and C++ are different languages.

In modern C++, you often don't use raw arrays, but e.g. std::vector which provides you with the push_back member function.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
1

In C++ one typically never uses raw (C-style) arrays, but instead containers like std::vector (dynamic size) or std::array (fixed size, in C++11). With these implementing your array class is straight-forward (you didn't specify a way to access the elements though, so pretty unusable).

class array {
    std::vector<char> v_;
  public:
    void append(char c) {
      v_.push_back(c);
    }
};
Benjamin Bannier
  • 55,163
  • 11
  • 60
  • 80
0

an array cannot change size. You can however use a list in C++

http://www.cplusplus.com/reference/list/list/

samael
  • 2,007
  • 1
  • 16
  • 34
  • 3
    Lists do not use contiguous memory. While other languages may implement "arrays" with linked list or otherwise under the hood, `std::vector` is the more natural C++ go-to class for "arrays" that can grow/shrink and you can also [access them as if they were C arrays](http://stackoverflow.com/questions/6485496/how-to-get-stdvector-pointer-to-the-raw-data). – HostileFork says dont trust SE Nov 24 '12 at 15:19
0

The term array both in C and in C++ is used to denote a contiguous block of memory containing one or more data elements of the same type.

There are two types of arrays: static arrays and dynamic arrays. static arrays are allocated in the memory when the program is compiled and stored in the data segment of your program. Dynamic arrays as their name implies are allocated in runtime from the heap (the data structure used to access the memory available to the program for dynamic allocation).

Both array types are accessed the same way using pointers and indexers (the [] operator).

Both in C and C++ a pointer is a variable that point to a place in memory. The memory it points to may contain a class or a primitive data type.

There are however differences between a static arrays and a dynamic arrays. Here are the important ones:

  1. dynamic arrays must be allocated to use them and freed to prevent memory leaks
  2. static arrays cannot be resized

In C you allocate memory using malloc and release it using free. You can resize it using realloc

In C++ you allocate memory using new and release it using delete. You have to write your own code to resize it.

For most purposes a dynamic array in C++ will be implemented using std::vector. In C if you want such a mechanism you will have to roll your own. You got a good answer from @Cheers and hth. - Alf on std::vector.

I don't think this is the place to write a full tutorial on dynamic memory in C or C++. You can get a good introduction from http://www.cplusplus.com/doc/tutorial/dynamic/

Here is however a sample code that will show you how to do what you want in C. For C++ use std::vector.

/*
C CODE
*/

#include <stdlib.h>
#include <limits.h>

typedef struct DARRAY dynamic_int_array_t;

typedef struct DARRAY
{
    int length;
    int *data;
    void (*alloc)(dynamic_int_array_t * the_array, int length);/*allocate*/
    void (*free)(dynamic_int_array_t * the_array);/*free*/
    void (*resize)(dynamic_int_array_t * the_array, int new_length);/*resize*/
    void (*append)(dynamic_int_array_t * the_array, int new_value);
    int (*get_at)(dynamic_int_array_t * the_array, int pos);/*use 1 based index getter*/
    void (*set_at)(dynamic_int_array_t * the_array, int pos, int value);/*use 1 based index setter*/
}dynamic_int_array_t;

void allocIntArray(dynamic_int_array_t * the_array, int length)
{
    /*
    Allocate memory to contain length number of integers
    */
    the_array->data = (int*)malloc(length*sizeof(int));
    the_array->length = length;
}

void freeIntArray(dynamic_int_array_t * the_array)
{
    if(NULL != the_array->data)
        free(the_array->data);/*Free the memory*/
    the_array->length = 0;/*Reset the length of the array*/
}

void resizeIntArray(dynamic_int_array_t * the_array, int new_length)
{
    if(NULL != the_array->data && the_array->length > 0 && new_length >= 0)
    {

        if(new_length == 0)/*Free the array if a value of 0 was requested*/
            the_array->free(the_array);
        else
        {
            /*Resize the memory block*/
            the_array->data = (int*)realloc(the_array->data, new_length*sizeof(int));
        }
        the_array->length = new_length;
    }
}

void appendIntArray(dynamic_int_array_t * the_array, int new_value)
{   
    the_array->resize(the_array, the_array->length + 1);
    the_array->data[the_array->length - 1] = new_value;
}

int getAt(dynamic_int_array_t * the_array, int pos)
{
    if(NULL != the_array->data && pos > 0 && pos <= the_array->length)
        return the_array->data[pos-1];
    return INT_MIN;/*use INT_MIN to indicate error*/
}

void setAt(dynamic_int_array_t * the_array, int pos, int value)
{
    if(NULL != the_array->data && pos > 0 && pos <= the_array->length)
        the_array->data[pos-1] = value;
}

int main(int argc, char **argv)
{
    dynamic_int_array_t int_array = 
    {
        0,
        NULL,
        allocIntArray,
        freeIntArray,
        resizeIntArray,
        appendIntArray,
        getAt,
        setAt       
    };

    int_array.alloc(&int_array, 4);
    int_array.data[0] = 1, int_array.data[1] = 2,
        int_array.data[2] = 3, int_array.data[3] = 4;
    printf("array length: %d, last member: %d\n", int_array.length, int_array.get_at(&int_array,4));
    int_array.resize(&int_array, 5);
    int_array.data[4] = 5;/* can also use int_array.set_at(&int_array,5) = 5; */
    printf("array length: %d, last member: %d\n", int_array.length, int_array.get_at(&int_array,5));
    int_array.append(&int_array, 6);
    printf("array length: %d, last member: %d\n", int_array.length, int_array.get_at(&int_array,5));
}
Sebastian Cabot
  • 1,812
  • 14
  • 18