0

The two arrays passed in are constants so I made two new arrays. The first array stores a group of chars and the second array stores a second group of chars. So far I assume that the first group is bigger than the second ex. (a,b,c,d > x,y). What the program hopes to accomplish is to make two new arrays that contain the same letters but the shorter array in this case arr2 (newarr2) has it's last char repeated until it matches the length of the first array. examples of correct solutions. (a,b,c,d < x,y) --> equate_arr --> (a,b,c,d = x,y,y,y)

void equate_arr(char arg2[], char arg1[]){
    size_t i = 0;
    size_t len1 = strlen(arg1);
    size_t len2 = strlen(arg2);
    char newarr2[512];
    char newarr1[512];

    while(i < (strlen2 - 1))
    {
        newarr2[i] = arg2[i];
        i++;
    }

    i = 0;

    while(i < (strlen1 - 1))
    {
        newarr1[i] = arg1[i];
        i++;
    }

    i = 0;

    while(strlen(newarr2) < strlen(newarr1))
    {
        newarr2[strlen(newarr2)] = newarr2[strlen(newarr2)-1]
    }   
}

Currently I have no idea what is happening because once I fiddle with this function in my code the program does not seem to run anymore. Sorry about asking about this project I'm working on so much but I really do need some assistance.

I can put the whole program in here if needed.

Revised

void tr_non_eq(char arg1[], char arg2[], int len1, int len2)
{
int i = 0;
char* arr2;
arr2 = (char*)calloc(len1+1,sizeof(char));
while(i < len2)
{
    arr2[i] = arg2[i];
    i++;
}

while(len2 < len1)
{
    arr2[len2] = arg2[len2-1];
    len2++;
}

tr_str(arg1, arr2);
}

Right now with inputs (a,b,c,d,e,f) and (x,y) and a string "cabbage" to translate the program prints out "yxyyx" and with string "abcdef" it prints out "xyy" which shows promise. I am not too sure why the arr2 array does not get filled with "y" chars as intended.

TheUnknown
  • 53
  • 2
  • 10
  • 2
    There is `memcpy`... But anyway, your function has no return-value, no side-effects, and it always terminates => It's an elaborate nop. – Deduplicator Feb 07 '15 at 22:55
  • Would it work if the original arrays contain arguments passed in through command line? When the program is ran you are supposed to put in two sets of arguments like ./a abcd xy Then when the program starts it is supposed to exchange the first set of letters for the second set and if one of the sets is shorter to run the equate_array function. edit: Would addint return newarr2; be an improvement? – TheUnknown Feb 07 '15 at 22:57
  • I'm a little surprised it runs at all - fiddling or no :) See some of the items in my answer. This might have been a better candidate for codereview.stackexchange.com – kdopen Feb 07 '15 at 23:30
  • @kdopen This part indicates that it is not a better candidate for Code Review: *"Currently I have no idea what is happening because once I fiddle with this function in my code the program does not seem to run anymore"* – Simon Forsberg Feb 07 '15 at 23:43
  • Yeah, it's a narrow call. But the generic question would just be about "How do I modify C strings so that they are the same length". This is more "Why doesn't my code work, and please explain some fundamentals". As it stands, this code doesn't have much hope of working. I could provide a working solution ... but then the OP doesn't learn as much. – kdopen Feb 08 '15 at 00:07

2 Answers2

1

Since you declared

char newarr2[512];
char newarr1[512];

as size 512 and not assigned any data, strlen will always return size of newarr1 and newarr2 as garbage since you not ended the string with a proper NULL character.

while(strlen(newarr2) < strlen(newarr1))
{
    newarr2[strlen(newarr2)] = newarr2[strlen(newarr2)-1]
} 

this while loop will not work properly.

for ( i = len2; i < len1; ++i )
    newarr2[i] = newarr2[len2-1]

if len2 is always less than len1, you can use the above loop if you do not know the which array will be bigger than,

size_t len1 = strlen(arg1);
size_t len2 = strlen(arg2);
char* newarr1;
char* newarr2;
int i;

if ( len1 >= len2 )
{
    newarr1 = (char*)calloc(len1+1,sizeof(char));
    newarr2 = (char*)calloc(len1+1,sizeof(char));
}
else
{
    newarr1 = (char*)calloc(len2+1,sizeof(char));
    newarr2 = (char*)calloc(len2+1,sizeof(char));
}
for ( i = 0; i < len1; ++i)
    newarr1[i] = arg1[i];
for ( i = 0; i < len2; ++i)
    newarr2[i] = arg2[i];
if( len1 >= len2 )
{
   for ( i = len2; i < len1; ++i )
      newarr2[i] = newarr2[len2-1];
}
else
{
   for ( i = len1; i < len2; ++i )
      newarr1[i] = newarr1[len1-1];
}

free the memory later

Sridhar Nagarajan
  • 1,085
  • 6
  • 14
  • what should this program return in theory – TheUnknown Feb 08 '15 at 00:06
  • I you want to modify the string data passed to a function, dont pass them as const, if u have no other option but to pass the two strings as const itself then use another two argument to return the newly created strings. – Sridhar Nagarajan Feb 08 '15 at 00:14
  • if you are not sure about the size of the string then use dynamic memory allocation. as @kdopen said in another answer, use NULL(End of string for c) to terminate string, with out that C cannot find the end of the string. – Sridhar Nagarajan Feb 08 '15 at 00:20
  • what does warning assignment makes integer from pointer without a cast mean? newarr1[i] = arr1[i]; – TheUnknown Feb 08 '15 at 00:26
  • @TheUnknown if you try to assign a pointer to a char variable, the compiler will through a warning integer from pointer without a cast, when compiler tries to implicitly type case a pointer to a char. – Sridhar Nagarajan Feb 08 '15 at 00:30
  • `newarr2[strlen(newarr2)+1] = '\0';` add this line inside the while loop, as the first line, `newarr2[i] = '\0';` before `i=0` and same goes for `newarr1` and while copying the data to `newarr2` and use the `while` condition as `i < len2` and similar for `newarr1`. and top change the function arguments to `void equate_arr(char arg1[] , char arg2[])`. print and verify your answer – Sridhar Nagarajan Feb 08 '15 at 01:47
1

As de-duplicator says, as your code stands it effectively achieves nothing. More importantly, what it tries to do is fraught with peril.

The fact that you use strlen to determine the length of your arguments is a clear indicator that equate_arr does not expect to receive two arrays of char. Instead, it wants two NUL-terminated C-style strings. So the declaration should be more like:

void equate_arr(const char *arg2, const char *arg1)

This makes the contract a little clearer.

But note the return type: void. This says your function will not return any values to the caller. So, how did you plan to return the modified arrays?

The next big peril lies in these lines:

char newarr2[512];
char newarr1[512];

What happens if this function is called with a string which is larger than 511 characters (plus the NUL)? The phrase "buffer overrun" should be jumping out at you here.

What you need is to malloc buffers large enough to hold a duplicate of the longest string passed in. But that raises the question of how you will hand the new arrays back to the caller (remember that void return type?).

There are numerous other problems here, largely down to not having a clear definition of the contract this function is meant to meet.

One more for now while I look more closely

while(strlen(newarr2) < strlen(newarr1))
{
    newarr2[strlen(newarr2)] = newarr2[strlen(newarr2)-1]
}   

The very first pass through this loop overwrites the terminating NUL in newarr2, which means the next call to strlen is off into undefined behavior as it is completely at the mercy of whatever junk is sitting in your stack.

If you are unclear on C-style strings, take a look at my answer to this question which goes into great detail about them.

The following is whiteboard-code (i.e. not compiled, not tested) which would sort of do what you are wanting to achieve. It's purely for reference

    // Pad a string so that it is the same length as another. Padding is done
    // by replicating the final character.
    //
    // @param padThis:   A C-style string in a non-constant buffer.
    // @param bufLength: The size of the buffer containing padThis
    // @param toMatchThis: A (possibly) const C-style string to act
    //                     as a template for length
    //
    // Pre-conditions:
    //    - Both padThis and toMatchThis reference NUL-terminated sequences
    //      of chars
    //    - strlen(padThis) < bufLength. Violating this will exit the program.
    //    - strlen(toMatchThis) < bufLength. If not, padThis will be padded
    //      to bufLength characters.
    //
    // Post-conditons:
    //    - The string referenced by toMatchThis is unchanged
    //    - The original string at padThis has been padded if necessary to 
    //      min(bufLength, strlen(toMatchThis))

    void padString(char * padThis, size_t bufLength, const char * toMatchThis)
    {
        size_t targetLength = strlen(toMatchThis);
        size_t originalLength = strlen(padThis);

        if (originalLength >= bufLength)
        {
            fprintf(stderr, "padString called with an original which is longer than the buffer!\n");
            exit(EXIT_FAILURE);
        }


        if (targetLength  >= bufLength)
            targetLength = bufLength -1; // Just pad until buffer full

        if (targetLength <= strlen(padThis))
            return; // Nothing to do

        // At this point, we know that some padding needs to occur, and
        // that the buffer is large enough (assuming the caller is not
        // lying to us).

        char padChar = padThis[originalLength-1];
        size_t index = originalLength;
        while (index < targetLength)
            padThis[index++] = padChar;
        padThis[index] = '\0';
    }
Community
  • 1
  • 1
kdopen
  • 8,032
  • 7
  • 44
  • 52
  • Thanks, I was actually really confused about how c worked with char arrays as strings. This helped out. A question I would have to ask is, how would I expand an array then? I need to somehow make the short string become longer. – TheUnknown Feb 07 '15 at 23:46
  • That is what I meant about defining the "contract" more precisely. A function's contract covers its inputs, outputs, preconditions, exit conditions, and assumptions. For example, part of this function's contract is that its inputs *must* be NUL-terminated C-style strings. Another is that you (currently) assume neither is more than 511 characters long. I think this needs to move to codereview, or be asked differently. – kdopen Feb 08 '15 at 00:02