0

I need to write a function called MakeString. The function returns a pointer to a string, which contains one word composed of each row of the small matrix in order, so that each line break will be expressed as a single space between the words In the string. (After the last word there will be no space.)

Inference: In the function there is no use of [], but executes by working with pointers.

Function. In addition, trips should be carried out with the voters, meaning that they will actually move to vote for each other

Whatever it takes, and will not stay in the same location all the time. The 'answer' that the function returns, which is a pointer, will be input into a pointer in MAIN.

I tried to do the function, but It NOT like instruction and not good...

#define SIZE 4
static char allocbuf[SIZE][];
static char *allocp = allocbuf;

char matrix[SIZE][SIZE]
{
    {U,N,T,E},
    {C,P,G,X},
    {D,L,A,B},
    {J,T,N,N}
};
char MakeString(int n)  /*return pointer to n charachters*/
{
    if (allocbuf + SIZE - allocp >=n)
    {
        allocp += n;
        return  allocp - n;
    }
    else
        return 0;
}

For example:

Small matrix:

U N T E

C P G X

D L A B

J T N N

pStr = UNTE CPGX DLAB JTNN

Thanks (:

10
  • What is allocbuf supposed to be? An array of strings? Will the strings have a fixed static (at compile-time) size? Or will they need to be dynamically allocated? Commented Apr 17, 2019 at 20:25
  • Also, your MakeString function doesn't "make" a string. And it doesn't return anything that can be used as a string either. And I really don't see the need for all that pointer arithmetic either, what's wrong with a simple index that's compared to SIZE? Commented Apr 17, 2019 at 20:25
  • Our lecture force us use pointers. I know it unnecessary.... My function Not good also \: The strings not static BUT dynamically allocated. Must not use [][] ONLY USE POINTERS. @Some programmer dude Commented Apr 17, 2019 at 20:37
  • So then allocbuf should be an array of pointers really? And your MakeString function needs to allocate the correct size (not forgetting the string null-terminator) and then return the pointer? Commented Apr 17, 2019 at 20:39
  • 1
    The only times you can use [] in an array declaration is in a function parameter or when declaring an array with an initialization list (the size comes from the number of items in the list). Commented Apr 17, 2019 at 20:42

2 Answers 2

1

If I understand your question, you want write a function to read the characters from matrix (a 2D array of char) into an allocated string placing a space between each rows worth of characters and returning the nul-terminated string back to the calling function. You need to do this using pointers and without array [index] notation.

To begin, your declaration of matrix is wrong. E isn't a character, it is a variable. 'E' is a character literal. (note the single-quotes) So a proper declaration of matrix would be:

    char matrix[SIZE][SIZE] = { {'U','N','T','E'},  /* don't use globals   */
                                {'C','P','G','X'},  /* declare in main and */
                                {'D','L','A','B'},  /* pass as a parameter */
                                {'J','T','N','N'} };

(note: simply char matrix[][SIZE] = {{...}}; is sufficient, where the number of rows will be sized based on your initialization)

As noted in the comment, avoid the use of global variables unless absolutely necessary. (very limited cases -- not here). Instead, declare matrix in the scope where it is required and pass matrix as a parameter to any function that needs to process the data. By contrast, defining is constant with #define is perfectly correct, and you should define constants as needed to avoid using magic-numbers in your code.

Since matrix is a 2D array, to pass it as a parameter, you must include the number of columns as part of the parameter passed. You can either declare the parameter as char matrix[SIZE][SIZE] or equivalently as char (*matrix)[SIZE] reflecting the fact that the first level of indirection is converted to a pointer to the first element on access. See: C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3) (paying attention to the 4-exceptions)

Within your makestring() function you must allocate storage of at least SIZE * SIZE + SIZE (space for each character + 3 spaces + the nul-terminating character). Assigning the starting address of your new block of memory to a pointer, and then creating a second pointer to the block will allow you to iterate over it, copying characters to it -- while preserving a pointer to the beginning.

Putting those pieces together, you could do something similar to:

char *makestring (char (*a)[SIZE])
{
    char *str = malloc (SIZE * SIZE + SIZE), *p = str;  /* allocate */
    if (!str) {                         /* validate EVERY allocation */
        perror ("malloc-str");
        return NULL;
    }
    for (int i = 0; i < SIZE; i++) {    /* for each row   */
        if (i)                          /* if row not 1st */
            *p++ = ' ';                 /*    add space   */
        for (int j = 0; j < SIZE; j++)  /* for each char  */
            *p++ = *(*(a + i) + j);     /*    copy to str */
    }
    *p = 0;         /* nul-terminate string */

    return str;     /* return pointer to allocated string */
}

(note: while not an error, C generally avoids the use of camelCase or MixedCase variable names in favor of all lower-case while reserving upper-case names for use with macros and constants.)

Putting it altogether in a short example, you could do:

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

#define SIZE 4

char *makestring (char (*a)[SIZE])
{
    char *str = malloc (SIZE * SIZE + SIZE), *p = str;  /* allocate */
    if (!str) {                         /* validate EVERY allocation */
        perror ("malloc-str");
        return NULL;
    }
    for (int i = 0; i < SIZE; i++) {    /* for each row   */
        if (i)                          /* if row not 1st */
            *p++ = ' ';                 /*    add space   */
        for (int j = 0; j < SIZE; j++)  /* for each char  */
            *p++ = *(*(a + i) + j);     /*    copy to str */
    }
    *p = 0;         /* nul-terminate string */

    return str;     /* return pointer to allocated string */
}

int main (void) {

    char matrix[SIZE][SIZE] = { {'U','N','T','E'},  /* don't use globals   */
                                {'C','P','G','X'},  /* declare in main and */
                                {'D','L','A','B'},  /* pass as a parameter */
                                {'J','T','N','N'} },
        *str;

    if ((str = makestring (matrix))) {  /* validate call to makestring */
        printf ("str: '%s'\n", str);    /* output string */
        free (str);                     /* free allocated memory */
    }
}

(note: don't forget to free the memory you allocate. While it will be freed on program exit, get in the habit of tracking your allocations and ensuring all blocks you allocate are freed)

Example Use/Output

$ ./bin/makestring
str: 'UNTE CPGX DLAB JTNN'

Memory Use/Error Check

In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.

It is imperative that you use a memory error checking program to insure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.

For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.

$ valgrind ./bin/makestring
==6576== Memcheck, a memory error detector
==6576== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==6576== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==6576== Command: ./bin/makestring
==6576==
str: 'UNTE CPGX DLAB JTNN'
==6576==
==6576== HEAP SUMMARY:
==6576==     in use at exit: 0 bytes in 0 blocks
==6576==   total heap usage: 1 allocs, 1 frees, 20 bytes allocated
==6576==
==6576== All heap blocks were freed -- no leaks are possible
==6576==
==6576== For counts of detected and suppressed errors, rerun with: -v
==6576== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Always confirm that you have freed all memory you have allocated and that there are no memory errors.

Look things over and let me know if you have further questions.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks (: I tried in my linux eclipse... Not work /: Any idea? @David C. Rankin
You have an eclipse problem. What compiler is eclipse using? MinGW? VS (cl.exe)? Do you have a Developer Command Prompt or MinGW Msys shell? Let me know and I'll show you how to compile it from the command line (which you should be doing anyway -- that way you would know what to tell eclipse to do....)
0

You need to specify the size of allocbuf so it can hold the entire result:

char allocbuf[SIZE * (SIZE + 1)];

There's no need for allocp, because the array name will decay to a pointer when used in calculations. In MakeString, you need to loop over the rows and characters of matrix, copying them to allocbuf.

char *MakeString()
    for (int i = 0; i < SIZE; i++) {
        memcpy(allocbuf + i * SIZE, matrix + i, SIZE);
        if (i < SIZE - 1) {
            // write space between rows
            *(allocbuf + i * SIZE + SIZE) = ' ';
        } else {
            // write null at end
            *(allocbuf + i * SIZE + SIZE) = 0;
        }
    }
    return allocbuf;
}

The instructions don't mention the n argument to MakeString(), so I removed it.

4 Comments

Thanks (: How can i change it get from user matrix? Does declaration of char allocbuf is on main Or in method MakeString() @Barmar?
It's a global variable, just like you wrote in the question.
I put the char allocbuf above the method in the file.c but it not print anything via main.. and I changed it get values char **smallMat \: I will update all up. Thanks @Barmar
Don't remove your original code when you update the question, add this new code as an addition at the bottom.

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.