【问题标题】:How to go through a array of strings using pointers alone如何仅使用指针遍历字符串数组
【发布时间】:2019-01-18 13:41:23
【问题描述】:

我正在尝试创建一个函数,它将接收一个字符串数组和大小,并将返回一个由每个单词的最大 ASCII 值字母组成的字符串,并且字符串的大小必须精确,我' m 不允许使用运算符 [](这是我的主要问题)。

所以:

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

该函数应返回一个带有单词的字符串

“上”

.

所以我想到了创建一个双 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");
}    

【问题讨论】:

  • str[i][j] 比你正在做的更具可读性
  • @ChrisTurner 我不允许在编写此代码时使用 [] 运算符。
  • @Shames 真的吗?你有这样的“编码规则”吗? !
  • @bruno 是的,这是一项家庭任务。如果我可以使用 [ ],我认为我的内部“for”循环不会有问题

标签: c arrays string function pointers


【解决方案1】:

如果将字符串指针与其字符指针分开,则使用指针会更容易。此外,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");
}

程序输出

新字符串是 --> onor 按任意键继续 。 . .

【讨论】:

  • 非常感谢!我什至不知道我可以像那样使用 malloc。
  • 请注意,sizeof(char) 根据定义1。另请参阅Do I cast the result of malloc?
【解决方案2】:

如果您没有对您的编码施加奇怪且无益的限制,您将能够快速发现您的代码存在的问题,甚至可以避免一开始就出现问题。问题是以下语句没有意义 - 您将 char *char 进行比较,因为您只取消引用 str 一次。

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

这和写是一样的

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

您可以看到明显的错误,因为您尝试编写的内容相当于

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

应该是

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

您的编译器应该会抛出警告,因为您很少会在指针和整数之间进行比较。

【讨论】:

  • 非常感谢您抽出宝贵的时间,我和您表达的感觉一样,但是由于我单独使用指针时遇到了麻烦,现在我可以理解这项任务背后的意义了!谢谢你教我怎么做!
【解决方案3】:

您可以使用指针作为位置指示器,并根据需要推进它们。

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

【讨论】:

    【解决方案4】:

    首先,(*(str + i)+j) 不是好方法。

    你可以全部替换

    (*(str + i) + j)

    作者:

    str[i][j]

    然后,您需要将max 重置为“a”,因为当您离开循环时它是“o”,所以您的条件变为str[i][j] &gt;= 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;
    }
    

    【讨论】:

    • (*(str + i) + j)str[i][j] 不同 - 没有足够的取消引用
    • *strstr[] 不是取消引用方法吗?
    • 是 - (*(str + i) + j) 仅取消引用一次,因此与 str[i]+j 相同
    • 是的,但他为什么要再取消引用一次?我的解决方案效果很好,这是一个幸运的镜头吗? (顺便说一句,我意识到我不应该与 NULL 或 NULL 分配进行比较)
    • 再次取消引用以达到与 str[i][j] 相同的位置,因为 OP 无法使用 []
    【解决方案5】:

    str[i] 等价于*(str + i)str[i][j] 等价于*(*(str + i) + j)
    在您的代码中,您使用的是 (*(str + i) + j),这是不正确的。

    char *[] 传递给函数时,它会衰减到char **。因此,在bigLetters() 中,您可以将char **str 作为参数。此外,它符合您的要求 - 不允许使用运算符 []

    除了在char *strArr[SIZE] 中硬编码维度SIZE,您还可以给出空的@9​​87654332@,并让编译器根据初始化程序的大小来分配维度。在您的情况下,初始化程序的大小是 4,因为您在 strArr 初始化程序中给出了 4 字符串。您可以像这样计算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() 的返回类型。

    【讨论】:

      猜你喜欢
      • 2021-11-14
      • 1970-01-01
      • 1970-01-01
      • 2013-06-09
      • 1970-01-01
      • 2021-05-29
      • 1970-01-01
      • 2018-06-30
      • 2012-11-06
      相关资源
      最近更新 更多