Как пройти через массив строк, используя только указатели - PullRequest
0 голосов
/ 18 января 2019

Я пытаюсь создать функцию, которая будет получать массив строк и размер и будет возвращать строку, состоящую из буквы наибольшего значения ASCII каждого слова, и размер строки должен быть точным, и я ' Нельзя использовать оператор [] (это моя главная проблема).

так для:

char * strArr [SIZE] = {"привет", "и", "хорошо", "утро"};

функция должна вернуть строку со словом

"Онор"

.

Итак, я подумал о создании двойного цикла for, сначала он приведет меня к расположению каждого слова в массиве, а внутренний поможет мне просмотреть каждое слово.

В настоящее время у меня возникают проблемы с поиском правильного формата с помощью моих указателей, чтобы на самом деле пролистать буквы моего первого слова.

Я знаю, что еще не проверил, правильно ли выделено мое память, и еще не освободил свою память, так как сначала пытаюсь выяснить, что не так.

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");
}    

Ответы [ 5 ]

0 голосов
/ 18 января 2019

str[i] эквивалентно *(str + i) и str[i][j] эквивалентно *(*(str + i) + j).
В вашем коде вы используете (*(str + i) + j), что неверно.

Когда char *[] передается в функцию, оно уменьшается до char **. Таким образом, в bigLetters() вы можете указать char **str в качестве параметра. Кроме того, это соответствует вашему требованию - запрещено использовать оператор [] .

Вместо жесткого кодирования измерения SIZE в char *strArr[SIZE], вы можете задать пустое [] и позволить компилятору назначить измерение на основе размера инициализатора. В вашем случае размер инициализатора составляет 4, поскольку вы дали 4 строки в инициализаторе strArr. Вы можете вычислить размер strArr следующим образом:

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

Вы можете сделать:

#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;
}

Обратите внимание, что void тип возврата main() не соответствует стандарту. Вместо этого вы должны использовать int в качестве типа возврата main().

0 голосов
/ 18 января 2019

Вы можете использовать указатели в качестве индикаторов положения и продвигать их по мере необходимости.

#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;
}
0 голосов
/ 18 января 2019

Если вы не наложили странные и бесполезные ограничения на кодирование, вы сможете быстро увидеть проблемы с вашим кодом или даже вообще не создавать их. Проблема в том, что следующее утверждение не имеет смысла - вы сравниваете char * с char, поскольку вы только разыменовываете str один раз.

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

Это то же самое, что писать

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

, в которой вы видите очевидную ошибку, поскольку то, что вы пытаетесь написать, эквивалентно

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

что будет

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

Ваш компилятор должен выдавать предупреждения, потому что сравнение между указателем и целым числом редко является чем-то, что вы хотели бы сделать.

0 голосов
/ 18 января 2019

Во-первых, (*(str + i)+j) не очень хороший путь.

Вы можете заменить все

(*(str + i) + j)

по:

str[i][j]

Затем вам нужно сбросить max на «a», потому что когда вы выходите из цикла, это «o», поэтому ваше состояние становится str[i][j] >= o, что не то, что вы хотите. Сделай это до второго for.

И я бы использовал while вместо for для первого цикла.

Я отредактировал ваш код, и эта версия отлично работает для меня:

#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;
}
0 голосов
/ 18 января 2019

Будет проще использовать указатели, если вы отделите указатель строки от его символьного указателя. Кроме того, max должен быть сброшен для каждой строки, и вы писали последний терминатор строки за пределами выделенной памяти. Вы также используете NULL, где вы должны использовать символ '\0'.

Наконец функция возвращала первый символ новой строки (который я позже 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");
}

Вывод программы

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