1

I am new in learning C. I have an issue in returning double star pointer from the function.

This is my code.

#include <stdio.h>
#include <stdbool.h>

#include "api.h"

void init() {
  // You can initiate and calculate things here
}

/**
 * Return the given list in reversed order. Each element in the given list contains a single character.
 * 
 * typedef struct {
 *   int count;
 *   const char * * elements;
 * } string_list;
 * 
 * list_of_chars: string_list
 * 
 * returns: string_list
 */
string_list reverse(string_list list_of_chars) {
  // Write your code here
  char X[list_of_chars.count];
  
  //X[0] = *list_of_chars.elements[0];
  
  for (int i = 0; i < list_of_chars.count;i++){
  X[i] = *list_of_chars.elements[i];
  }
  printf("%c", X[0]);

  string_list return_value = {
    .count = 0,
    .elements = &X[0],
  };
  return return_value;
}

But I am getting initialization of 'const char **' from incompatible pointer type 'char *'. I tried multiple solutions but non of them worked.

Ali Amma
  • 43
  • 6
  • @Dai it's in the code comments above the function – Craig Estey May 14 '22 at 17:46
  • `X` is function scoped (on the stack). It goes out of scope when the function returns. You want: `char *X = malloc(list_of_chars.count);` – Craig Estey May 14 '22 at 17:50
  • I did not got what is the use of the comments above the code (e.g., init function and the struct) But I tried to malloc the X pointer with return X instead of &X, but still not worked. maybe I missed something. – Ali Amma May 14 '22 at 17:55
  • I missed the original intent. You want: `char **X = malloc(list_of_chars.count * sizeof(*X));` and `X[list_of_chars.count - 1 - i] = strdup(*list_of_chars.elements[i]);` – Craig Estey May 14 '22 at 18:01
  • implicit declaration of function 'strdup'; did you mean 'strcmp'? [-Werror=implicit-function-declaration] 30 | X[list_of_chars.count - 1 - i] = strdup(*list_of_chars.elements[i]); | ^~~~~~ | strcmp solution.c:30:36: error: assignment to 'char *' from 'int' makes pointer from integer without a cast [-Werror=int-conversion] 30 | X[list_of_chars.count - 1 - i] = strdup(*list_of_chars.elements[i]); | ^ – Ali Amma May 14 '22 at 18:09
  • Also, `.count = list_of_chars.count` – Craig Estey May 14 '22 at 18:09
  • Tried it but got implicit declaration of function 'strdup'; did you mean 'strcmp'? And error: assignment to 'char *' from 'int' makes pointer from integer without a cast – Ali Amma May 14 '22 at 18:11
  • 1
    Oops, I'm on mobile. Remove `*` from the `strdup` call – Craig Estey May 14 '22 at 18:12
  • Add: `#include ` – Craig Estey May 14 '22 at 18:13
  • done it but still error :( *** X[list_of_chars.count - 1 - i] = strdup(list_of_chars.elements[i]); – Ali Amma May 14 '22 at 18:16

1 Answers1

1

Side note: As I mentioned in the top comments, I was limited to what I could do on mobile. I'm back at my desk.

Issues were:

  1. X is function scoped, so it goes out of scope when the function returns. We need to use malloc [so we need stdlib.h]
  2. Because elements is a const char **, then we need const char **X

We need to use [should use] strdup to duplicate the elements.

Otherwise, both lists will share the same data. This may the desired intent. But, it's not clear from the problem description what the correct code should be.

Most lists should be fully independent from one another. The original code does not do this. So, the lists are sharing the data. But, if that's true, why bother to create a separate list? We could just "reverse" it by indexing in the reverse direction without creating a new list:

for (int i = list.count - 1;  i >= 0;  --i)

So, I've chosen to duplicate the strings. Original behavior (shared strings) when compiled with -DNODUP.

Here's the refactored code:

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

#if 0
#include "api.h"
#else
typedef struct {
    int count;
    const char **elements;
} string_list;
#endif

void
init()
{
    // You can initiate and calculate things here
}

/**
 * Return the given list in reversed order. Each element in the given list contains a single character.
 *
 * typedef struct {
 *   int count;
 *   const char * * elements;
 * } string_list;
 *
 * list_of_chars: string_list
 *
 * returns: string_list
 */
string_list
reverse(string_list list)
{
    const char **X = malloc(sizeof(*X) * list.count);

    // share the strings
#if NODUP
    for (int i = 0; i < list.count; i++)
        X[list.count - 1 - i] = list.elements[i];

    // make lists independent (more usual/expected)
#else
    for (int i = 0; i < list.count; i++)
        X[list.count - 1 - i] = strdup(list.elements[i]);
#endif

    string_list ret = {
        .count = list.count,
        .elements = X,
    };

    return ret;
}

UPDATE:

In the link above was the exercise page where we can choose GCC for C. I pasted your code exactly to the website bit still see same errors.

Okay, finally ... ;-)

  1. The website uses an ancient version of the C standard (e.g. C99). This does not have strdup.
  2. The website will [forcibly] do a #include "api.h" before including the code, so there is a conflict with the definition I used.

Here is the corrected code (which runs successfully on the website):

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

#if 1
#include "api.h"
#else
typedef struct {
    int count;
    const char **elements;
} string_list;
#endif

void
init()
{
    // You can initiate and calculate things here
}

/**
 * Return the given list in reversed order. Each element in the given list contains a single character.
 *
 * typedef struct {
 *   int count;
 *   const char * * elements;
 * } string_list;
 *
 * list_of_chars: string_list
 *
 * returns: string_list
 */
string_list
reverse(string_list list)
{
    const char **X = malloc(sizeof(*X) * list.count);

    // share the strings
#if 1
    for (int i = 0; i < list.count; i++)
        X[list.count - 1 - i] = list.elements[i];

    // make lists independent (more usual/expected)
#else
    for (int i = 0; i < list.count; i++)
        X[list.count - 1 - i] = strdup(list.elements[i]);
#endif

    string_list ret = {
        .count = list.count,
        .elements = X,
    };

    return ret;
}

Side note: I'd get a good book on C and study that to get more basic knowledge of C. Trying to use "competition" websites isn't the best way, IMO.

A number of the issues you've seen (but did not understand) would have been obvious with a better basic understanding of C syntax and semantics.

Here's a list: The Definitive C Book Guide and List

Craig Estey
  • 30,627
  • 4
  • 24
  • 48
  • Thank you alot for answer. I tried it but I got these * solution.c:10:3: error: conflicting types for 'string_list' * note: previous declaration of 'reverse' was here * : implicit declaration of function 'strdup'; did you mean 'strcmp'? [-Werror=implicit- https://app.futureskill.com/exercise/5f609c49aa3c5b44f6359a26 – Ali Amma May 14 '22 at 19:44
  • @AliAmma Try using my posted code _exactly_ (i.e. copy and paste it). It compiles cleanly even with `-Wall -O2`. You must be mixing and matching. I commented out: `#include "api.h"` [because you didn't post it] and copied the `struct` definition from the function comments. If you do "both", they will conflict. I'm not sure why you're linking to _python_ code. – Craig Estey May 14 '22 at 19:51
  • @AliAmma Also, I added necessary [but missing] `#include` statements. So, just copying the updated function may not be enough. – Craig Estey May 14 '22 at 19:57
  • In the link above was the exercise page where we can choose GCC for C. I pasted your code exactly to the website bit still see same errors. – Ali Amma May 14 '22 at 20:03
  • Thank you for your answer and your suggestion. will do as you said :) – Ali Amma May 14 '22 at 20:30