3

The function should simply read a matrix. Why does it freeze after I enter the first character?

#include "stdafx.h"
#include <iostream>

using namespace std;

void as(char **p,int n,int m)
{
    int i, j;
    for (i = 0; i < n; i++)
        for (j = 0; j < m; j++)
        {
            cout << "p[" << i << "][" << j << "]=";
            cin >> p[i][j];
        }
}

int main()
{
    char *a[100];
    as(a, 3, 3);
    return 0;
}
ivan_pozdeev
  • 33,874
  • 19
  • 107
  • 152
  • 4
    Undefined behaviour. You have an array of uninitialised pointers, not a two-dimensional array of ints. –  Aug 21 '17 at 21:35
  • You might need to refer to [this](https://stackoverflow.com/questions/1052818/create-a-pointer-to-two-dimensional-array) post for how to correctly use high dimensional arrays. – pwwpche Aug 21 '17 at 21:39
  • Possible duplicate of [C, passing 2 dimensional array](https://stackoverflow.com/questions/13750247/c-passing-2-dimensional-array) – ivan_pozdeev Aug 18 '18 at 17:21

3 Answers3

3

This is undefined behavior: your array is an array of 100 pointers to char. But you've never initialized them. So when you address p[i] it gets an uninitialized pointer that could point anywhere, and when you dereference it with p[i][j] you might then freeze or suffer of anyother symptom of undefined behavior.

If you want to learn to use pointers and arrays:

Solution 1: define your array as char a[100][100];

Solution 2: in the outer loop of as(), start to allocate the chars with p[i] = new char[m];

If you want to learn modern C++:

Solution 3: Forget about memory allocation and deallocation and use vectors instead. The vectors are totally dynamic, so no maximum of 100 rows anymore:

void as(vector<vector<char>> &p, int n, int m)
{
    p.resize(n); 
    int i, j;
    for (i = 0; i < n; i++) {
        p[i].resize(m); 
        for (j = 0; j < m; j++)
        {
            cout << "p[" << i << "][" << j << "]=";
            cin >> p[i][j];
        }
    }
}

int main()
{
    vector<vector<char>>a;
    as(a, 3, 3);
    return 0;
}

If you want to try online...

Solution 4: you want modern C++, but you'd like to use your the elements in a[] as they were a string, for easy output and manipulation, just use the same code as above but replace vector<vector<char>> with vector<string>

And here you can look online the slightly simplified code.

Community
  • 1
  • 1
Christophe
  • 68,716
  • 7
  • 72
  • 138
  • And the array is a 1d array, not 2d. – Javia1492 Aug 21 '17 at 21:36
  • @Javia1492 indeed, but this is not the problem: You can address array elements with `a[i][j]` whether `a` is defined as a 2d array `char a[MAXI][MAXJ]` or a 1d array of pointers `char *a[MAXI]` (provided you initialize the pointers in this 1D array). – Christophe Aug 21 '17 at 22:11
  • Thank you! I've one question though. Why the need to reference p in "vector> &p"? – Beach Williams Aug 21 '17 at 22:35
  • @BeachWilliams when you pass an array ad parameter, it is passed by reference (i.e. A pointer to the start of the array will be passed). So changing a value of the array in the function will change the original array. Vectors are passed by value unless you explicitly pass them by reference as here. So if the & would be missing you would change a local copy of the vector and the original one would remain empty. By the way, an alternative could be to create the vector in the function and return it as result (by value). – Christophe Aug 22 '17 at 05:21
0

I have for you simple pseudo array on mallocs reallocs and pointers. Maybe it will be interesting for you:

typedef struct arr_str_t{
    size_t rows, columns;
    char **table;
}dynamicStringTable_t;

int CreateStringTable(dynamicStringTable_t **ptr, int rows, int columns)
{
    int result = 0;
    *ptr = (dynamicStringTable_t *)malloc(sizeof(dynamicStringTable_t));
    if (ptr == NULL) return - 1;
    (*ptr)->rows = rows;
    (*ptr)->columns = columns;
    (*ptr) -> table = (char *)malloc(rows * columns * sizeof(char *));
    if (*ptr == NULL)
    {
        free(*ptr);
        return -1;
    }
    for (int i = 0; i < rows * columns; i++) (*ptr)->table[i] = NULL;
    return 0;
}

char *getString(dynamicStringTable_t *ptr, int x, int y)
{
    char *result = (ptr == NULL || x >= ptr->columns || y >= ptr->rows || !x || !y) ? NULL : "";
    if (result != NULL)
    {
        result = ptr->table[x + y * ptr->rows];
    }
    return result;
}

int putString(dynamicStringTable_t *ptr, int x, int y, const char *str)
{
    int result = (ptr == NULL || x >= ptr->columns || y >= ptr->rows || str == NULL || !x || !y) * -1;
    if (!result)
    {
        char *tmp = (char *)realloc(ptr->table[x + y * ptr->rows], (strlen(str) + 1) * sizeof(char));
        if (tmp == NULL) result = -2;
        else
        {
            ptr->table[x + y * ptr->rows] = tmp;
            strcpy(tmp, str);
        }
    }
    return result;
}

int removeString(dynamicStringTable_t *ptr, int x, int y)
{
    int result = (ptr == NULL || x >= ptr->columns || y >= ptr->rows || !x || !y) * -1;

    if (!result)
    {
        free(ptr->table[x + y * ptr->rows]);
        ptr->table[x + y * ptr->rows] = NULL;
    }

        return result;
}

int destroyStringTable(dynamicStringTable_t *ptr, int x, int y)
{
    int result = (ptr == NULL || x >= ptr->columns || y >= ptr->rows || !x || !y) * -1;

    if (!result)
    {
        if (ptr->table != NULL)
        {
            for (int i = ptr->rows * ptr->columns - 1; i >= 0; i--)
                free(ptr->table[i]);
            free(ptr->table);
        }
        free(ptr);
    }
    return result;
}
0___________
  • 60,014
  • 4
  • 34
  • 74
0

You have a great problem in your code. You are facing a UB in:

char *a[100]; // an array of 100 pointer to a character
// it is not initialized yet
  • Above no element is initialized (even not allocated).

To correct your code:

char *a[100];
// Allocating the array of 100 elements on the heap:
for(int i(0); i < 100; i++){
    a[i] = new char[100]; // let's say your array is n = m
}

as(a, 3, 3);

for(int i = 0; i < 3; i++){
    for(int j(0); j < 3; j++)
        cout << a[i][j] << ", ";
    cout << endl;
}

Last but not least Don't forget to free up memory when you are done with the dynamic array:

for(int i = 0; i < 100; i++)
    delete[] a[i];
Raindrop7
  • 3,889
  • 3
  • 16
  • 27