Shames
Shames

Reputation: 21

How to go through a array of strings using pointers alone

I'm trying to create a function that will receive an array of strings and the size and will return a string made of the biggest ASCII value's letter of each word, and the size of the string has to be precised and I'm not allowed using operator [](which is my main issue).

so for:

char *strArr[SIZE] = { "hello", "and", "good", "morning" };

the function shall return a string with the word

"onor"

.

So i thought of creating a double for loop, first one will lead me into the location of each word in the array and the inside one will help me go through each word.

currently I'm having trouble finding the right format with my pointers to actually go through the letters of my first word.

I'm aware i haven't checked if my memory allocation is valid and also didn't free my memory yet as I'm trying to figure out whats wrong first.

char *bigLetters(char *str[], int size)
{
char *strNew = (char *)malloc((size + 1) * sizeof(char));
char max = 'a';

for (int i = 0; i < size; i++)
{
    for (int j = 0; (*(str + i)+j) != NULL; j++)
    {
        if ((*(str + i) + j) >= max)
        {
            max = (*(str + i) + j);
        }

    }
    *(strNew + i) = max;
}
    *(strNew +(size+1)) = NULL;
return *(strNew);
}    

void main()
{
char *strArr[SIZE] = { "hello", "and", "good", "morning" };
char *res = bigLetters(strArr, SIZE);
printf("The new string is --> %s\n", res);

system("pause");
}    

Upvotes: 2

Views: 139

Answers (5)

H.S.
H.S.

Reputation: 12669

str[i] is equivalent to *(str + i) and str[i][j] is equivalent to *(*(str + i) + j).
In your code you are using (*(str + i) + j) which is incorrect.

When char *[] passed to function, it will decay to char **. So, in bigLetters(), you can give char **str as the parameter. Also, it is inline with you requirement - not allowed using operator [].

Instead of hardcoding the dimension SIZE in char *strArr[SIZE], you can give the empty [] and let the compiler assign the dimension based on the size of initializer. In your case, size of initializer is 4 as you have given 4 strings in the strArr initializer. You can compute the size of strArr like this:

sizeof(strArr)/sizeof(strArr[0]);

You can do:

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

char *bigLetters(char **str, size_t size) {

        char *strNew = calloc(size + 1, 1); // sizeof(char) is always 1
                                            // calloc will initialize all bytes in the allocated storage to zero.
                                            // You dont need to add the null terminating character at the end of strNew
        if (strNew == NULL)
                exit(EXIT_FAILURE);

        for (size_t i = 0; i < size; i++) {
                for (size_t j = 0; *(*(str + i)+j) != '\0'; j++) {
                        if (*(*(str + i) + j) > *(strNew + i)) {
                                // You can directly fill the allocated memory with biggest ASCII
                                *(strNew + i) = *(*(str + i) + j);
                        }
                }
        }

        return strNew;
}

int main(void) {
        char *strArr[] = { "hello", "and", "good", "morning" };

        char *res = bigLetters(strArr, sizeof(strArr)/sizeof(strArr[0]));

        if (res != NULL) {
                printf("The new string is --> %s\n", res);
                free (res);
        }
        else
                printf("bigLetters returned NULL\n");

        return 0;
}

Note that void return type main() is not as per standard. Instead, you should use int as return type of main().

Upvotes: 0

Titouan Le Floch Riche
Titouan Le Floch Riche

Reputation: 172

First, (*(str + i)+j) isn't the good way.

You could replace all

(*(str + i) + j)

by :

str[i][j]

Then, you need to reset the max to "a", because it's 'o' when you leave the loop, so your condition become str[i][j] >= o which is not what you want. Do it before the second for.

And I would have used while instead of for for the first loop.

I edited your code and this version is working fine for me :

#include <stdlib.h>


char *bigLetters(char *str[], int size)
{
    char *strNew = (char *)malloc((size + 1) * sizeof(char));
    int i = 0;

    while (i < size) {
        char max = 'a';
        for (int j = 0; str[i][j]; j++) {
            if (str[i][j] >= max) {
                max = str[i][j];
            }
        }
        strNew[i] = max;
        i++;
    }
    strNew[i] = '\0';
    return strNew;
}    

void main()
{
    char *strArr[5] = { "hello", "and", "good", "morning"};
    char *res = bigLetters(strArr, 4);
    printf("The new string is --> %s\n", res);
    return 0;
}

Upvotes: 0

purec
purec

Reputation: 318

You can use pointers as position indicators and advance them as needed.

#include <stdio.h>
#include <stdlib.h>
#define SIZE 4

char
biggest_ascii(char* str)
{
 char c = 0;
 int i;

 for (i = 0; *str; str++)
    if (*str > c)
        c = *str;
 return c;
}


int
main()
{
 int i;
 char* strArr[SIZE] = {"hello", "and", "good", "morning"};
 char** ppch;// current string
 char res_str[SIZE + 1] = {0};/* resulting string, 
            initilized to 0 to be 0-terminated */
 char* pch;// current char position

 for (i = 0, ppch = strArr, pch = res_str; i < SIZE; i++, ppch++, pch++)
    *pch = biggest_ascii(*ppch);

 printf("%s\n", res_str);   
 return 0;
}

Upvotes: 0

Chris Turner
Chris Turner

Reputation: 8142

If you didn't impose odd and unhelpful restrictions upon your coding, you'd be able to quickly see the problems with your code or even avoid making them in the first place. The problem is that the following statement makes no sense - you're comparing a char * with a char as you're only de-referencing str once.

if ((*(str + i) + j) >= max)

This is the same as writing

if ((str[i] + j) >= max)

which you can see the obvious mistake since what you're trying to write is the equivalent of

if ((str[i][j]) >= max)

which would be

if (*(*(str + i) + j) >= max)

Your compiler should be throwing up warnings because comparing between a pointer and an integer is rarely something you'd want to do.

Upvotes: 0

Weather Vane
Weather Vane

Reputation: 34585

It will be easier to use the pointers if you separate the string pointer from its character pointer. Also, the max needs to be reset for each string, and you were writing the final string terminator outside of the memory allocated. You also use NULL where you should be using the character '\0'.

Finally the function was returning the first character of the new string (which I later free).

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

#define SIZE 4

char *bigLetters(char *str[], int size)
{
    char *strNew = malloc(size + 1);                    // no cast or sizeof necessary

    for (int i = 0; i < size; i++)
    {
        char ch;
        char max = 'a';                                 // moved inside loop
        char *ptr = *(str + i);                         // use a separate pointer
        for (int j = 0; (ch = *(ptr + j)) != '\0'; j++) // pull out the character
        {
            if (ch > max)                               // >= is not necessary
            {
                max = ch;
            }

        }
        *(strNew + i) = max;
    }
    *(strNew + size) = '\0';                            // correct the bounds error
    return strNew;                                      // just the pointer not its target
}    

int main(void)                                          // correct signature
{
    char *strArr[SIZE] = { "hello", "and", "good", "morning" };
    char *res = bigLetters(strArr, SIZE);
    printf("The new string is --> %s\n", res);
    free(res);                                          // clean up
    system("pause");
}

Program output

The new string is --> onor
Press any key to continue . . .

Upvotes: 2

Related Questions