-2

I am trying to convert a string into its equivalent matrix form in C. The matrix would have 3 rows and as many columns as required. The following code doesn't compile, and I haven't figured out what's going wrong.

The error that GCC throws is:

app.c:10:25: error: subscripted value is not an array, pointer, or vector
      printf("%d\n", arr[i][k]);
                     ~~~^~
1 error generated.

Main file (app.c):

#include <stdio.h>
#include "converter.h"

int main() {

  char source[] = "This is the source. "; // placeholder text
  int arr = convert(source);
  for (int i = 0; i < 21; i++) {
    for (int k = 0; k < 3; k++) {
      printf("%d\n", arr[i][k]); // error occurs at this line.
    }
  }

  return 0;
}

converter.c file:

// Converts an input string to its respective ASCII matrix.

#include <string.h>
#include <stdio.h>
#include "converter.h"

// Converts the entire string into an multi-dimensional array.
int convert(char text[]){

    // copy the input text into a local store.
    char store[strlen(text)];
    strcpy(store, text);

    // make sure the length of the input string is a multiple of 3 or make it so.
    int excess = strlen(store)%3;
    char excess_spaces[3] = "   ";
    if (excess != 0) {
      strncat(store, excess_spaces, 3-excess);
    }

    // covert the source into an array
    int arr[3][strlen(store)/3];
    int steps = strlen(store)/3;
    for (int i = 0; i < steps; i++) {
      int t[3];
      for (int k = 0; k < 3; k++) {
        t[k] = (int) store[3*i+k];
        arr[k][i] = t[k];
      }
    }

    return arr;

}

converter.h file:

int convert(char text[]);
2
  • 4
    not an array, pointer, or vector. That seems pretty clear. What type do you understand arr to be after this: int arr = convert(source);? Commented Apr 11, 2021 at 5:58
  • 4
    The convert function has multiple issues. Its return type is an int and not an array. Also, you can't return a reference to a local variable as it becomes invalid as soon as the function exits - pass in an array for the function to fill in or use dynamic memory allocation. How to return matrix (2D array) from function? (C) Commented Apr 11, 2021 at 6:00

1 Answer 1

0

There are multiple issues in this code.

  1. The allocating storage for string, one must include one byte for a null terminator. Replace:
char store[strlen(text)];

with:

char store[strlen(text) + 1];

Additionally store must be big enough to contain the excess which is up to 3 spaces.

char store[strlen(text) + 3 + 1];
  1. In C you cannot use an array as a value. It is converted to a pointer to it's first element in pretty must every context. Therefore it is not possible to return an array directly. It could be workaround by wrapping an array with a struct but it a topic for another day.

As result return arr will be equivalent to return &arr[0] which is int (*)[XXX] a pointer to int array of size XXX.

  1. Never ever return a pointer to an object with automatic storage. It's Undefined Behaviour. I know that the intention was returning an array not a pointer to it. Create an object with dynamic storage with malloc-like function to safely return a pointer.

  2. Returning Variable Length Array (VLA) by value is not possible because Variably Modified (VM) types cannot be defined at file scope.

  3. It looks that indices are swapped in:

printf("%d\n", arr[i][k]);

I guess it should be arr[k][i].

Now... let's solve it.

Returning VLA is tricky. One solution is to pass a pointer to VLA as an argument. See https://stackoverflow.com/a/14088851/4989451. The issue with this solution is that the caller must be able to compute the dimensions.

The other way it to wrap the result of the convert() to a struct. Note that the function and the struct can share the name. The result with have the sizes of VLA as n and m members and the pointer to the data as arr. The caller need to cast it to proper VM type.

To cumbersome casts between the non-trivial pointer types, one can cast via void*.

When all work with the array is done, release it memory with free().

// Converts an input string to its respective ASCII matrix.

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

// Converts the entire string into an multi-dimensional array.
struct convert {
    int n, m;
    int *arr;
} convert(char text[]){

    // copy the input text into a local store.
    size_t textlen = strlen(text);
    char store[textlen + 3 + 1];
    strcpy(store, text);

    // make sure the length of the input string is a multiple of 3 or make it so.
    int excess = textlen % 3;
    char excess_spaces[3] = "   ";
    if (excess != 0) {
      strncat(store, excess_spaces, 3-excess);
    }
    size_t storelen = strlen(store);

    // allocate VLA with dynamic storage
    int (*arr)[storelen / 3] = malloc(3 * sizeof *arr);

    // covert the source into an array
    int steps = storelen / 3;
    for (int i = 0; i < steps; i++) {
      int t[3];
      for (int k = 0; k < 3; k++) {
        t[k] = (int) store[3*i+k];
        arr[k][i] = t[k];
      }
    }

    return (struct convert){ .n = 3, .m = steps, .arr = (int*)arr };
} 

int main() {

  char source[] = "This is the source. "; // placeholder text

  struct convert res = convert(source);
  int n = res.n, m = res.m;
  int (*arr)[m] = (void*)res.arr;

  for (int i = 0; i < n; i++, puts("")) {
    for (int k = 0; k < m; k++) {
      printf("%d ", arr[i][k]); // error occurs at this line.
    }
  }
  free(arr);

  return 0;
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.