简体   繁体   中英

I tried to make an array of strings and now I have an issue with my code which I don't know how to fix

I'm trying to make an array of strings by using pointers but for some reason (which I hope you would know) the program is crashing after I type the second string. I have been trying for hours to find what's wrong with this code and I'm hoping for your help! During debugging, after I realloced the input it says "error reading characters of string." Here is the code:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>


int main()
{
    char **input = (char **)calloc(1, sizeof(char)), ch;
    *input = (char *)calloc(1, sizeof(char));
    int size = 1,sizeinput=1,current = 0,currentarr=0,i=0,j=0;
    while (i<5)
{

    printf("please enter a word\n");
    scanf("%c", &ch);
    while (ch != '\n')
    {
        *(input+i) = (char*)realloc(*(input+i), (size++)*sizeof(char));
        *(*(input + i) + j++) = ch;
        scanf("%c", &ch);
    }

    *(*(input + i) + j) = '\0';
    j = 0;
    input = (char**)realloc(input, (sizeinput++)*sizeof(char*));
    i++;
    }
    free(input);
}

(char **)calloc(1, sizeof(char))

should be

(char **)calloc(1, sizeof(char*))

Also, after you reallocate input , the last element is an uninitialized pointer! Add this at the end of the loop, so it points to something useful and which you can reallocate later:

input[sizeinput - 1] = calloc(1, sizeof(char));

Cosmetic issues:

There's no need to cast the results of calloc and realloc - although doing so won't prevent your program from working, it does make it uglier.

Also, you can use input[i] instead of *(input + i) and input[i][j] instead of *(*(input + i) + j) - again, it won't affect how your program executes, but it can make it easier to read.

The problem is happening due to a reallocation happening in non-allocated memory. Consider your original code. When you call realloc for the first time, you call it for *(input + i) , which was previously allocated because i is zero at this point. This allocation happens in the second line of your main function. The problem is that you never allocate for position 1, which you try to (re!)allocate later. This fixes it:

int main()
{
    char **input = (char **)calloc(1, sizeof(char)), ch;

    // Don't do it here
    //*input = (char *)calloc(1, sizeof(char));

    int size = 1,sizeinput=1,current = 0,currentarr=0,i=0,j=0;

    while (i<5)
    {
        printf("please enter a word\n");
        scanf("%c", &ch);

        // Do it here instead
        *(input + i) = (char *)calloc(1, sizeof(char));

        while (ch != '\n')
        {
            // Now this reallocation is actually being given something that was allocated before
            *(input+i) = (char*)realloc(*(input+i), (size++)*sizeof(char));
            *(*(input + i) + j++) = ch;
            scanf("%c", &ch);
        }

        *(*(input + i) + j) = '\0';
        j = 0;
        input = (char**)realloc(input, (sizeinput++)*sizeof(char*));
        i++;
    }

    free(input);
}

There are several other issues with this, but as my first suggestion would be to take a different approach I'll leave other issues off the discussion. Let me know if you are interested, anyway.

Note: This causes one extra reallocation per loop. But as I said, it's just a quick fix.

the following code incorporates the comments, compiles cleanly, uses a function: cleanup() which I did not define, however, cleanup() will pass each word to free() then pass the 'array of pointers to char' to free()

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include <conio.h>

// prototypes
void cleanup( char ** input );

int main()
{
    char **input = calloc(1, sizeof(char*));
    char ch;
    *input = calloc(1, sizeof(char));
    size_t size = 1;
    size_t sizeinput=1;
    int i=0;
    int j=0;

    while (i<5)
    {

        printf("please enter a word\n");
        if( 1 != scanf("%c", &ch) )
        {
            perror( "scanf failed" );
            cleanup( input );
            exit( EXIT_FAILURE );
        }

        while (ch != '\n')
        {
            size++;
            char *temp = realloc(*(input+i), size);
            if( NULL == temp)
            {
                perror( "realloc for word failed" );
                cleanup( input );
                exit( EXIT_FAILURE );
            }
            *(input+i) = temp;

            *(*(input + i) + j) = ch;
            j++;

            if( 1 != scanf("%c", &ch) )
            {
                perror( "scanf failed" );
                cleanup( input );
                exit( EXIT_FAILURE );
            }

        }

        // NUL terminate word
        *(*(input + i) + j) = '\0';
        j = 0;

        sizeinput++;
        char** lineTemp = realloc(input, sizeinput*sizeof(char*));
        if( NULL == lineTemp )
        {
            perror( "realloc failed" );
            cleanup( input );
            exit( EXIT_FAILURE );
        }

        input = lineTemp;
        i++;
    }
    free(input);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM