哪根弦最长

Which string is the longest

我的代码: 我想要做的是输入两个字符串,然后 return 最长的一个。如果它们的长度相同,则 return NULL。现在,代码只是输出乱码,我无法找出原因。函数 return 是指向最大字符串的第一个字符的指针。然后它通过 while 循环,我试图取消引用指针并打印出它的值。

注意:我正在复习考试,我们只能使用指针,不能将字符串视为数组。

#include<stdio.h>

char* string_ln(char*, char*);
 
int main() {
    char str1[20];
    char str2[20];
    char* length;
   
    scanf("%s%s", str1, str2);
   
    length = string_ln(str1, str2);
   
    while (length != '[=10=]') {
        printf("%c", *length);
        length++;
    }
}
 
char* string_ln(char*p1, char*p2) {
    int count1 = 0;
    while (*p1 != '[=10=]') {
        count1++;
        p1++;
    }
   
    int count2 = 0;
    while (*p2 != '[=10=]') {
        count2++;
        p2++;
    }
   
    if (count1 > count2) {
        return p1;
    }
    else if (count2 > count1) {
        return p2;
    }
    else {
        return NULL;
    }
}

我认为您没有取消对指针的引用。而不是

while(length!='[=10=]')

你需要

while(*length!='[=11=]')

就是说,在被调用的函数中,您在增量之后重复指针,即 returned 指针不再指向字符串的开头。您需要确保 return 指向字符串开头的指针。您可以将代码更改为

int count1 = 0;
while (p1[count1] != '[=12=]') {
   count1++;
}

int count2 = 0;
while (p2[count2] != '[=12=]') {
   count2++;
}

这样 p1p2 就不会改变。

这里有一些问题。首先,您要在函数中修改 p1p2,因此实际上 return 不是指向最大字符串开头的指针,而是指向其结尾的指针。避免这种情况的一种方法是迭代 p1p2:

的副本
char* string_ln(char*p1, char*p2)
{
   char* tmp1 = p1;
   int count1 = 0;
   while (*tmp1 != '[=10=]') {
      count1++;
      tmp1++;
   }
   
   char* tmp2 = p2;
   int count2 = 0;
   while (*tmp2 != '[=10=]') {
      count2++;
      tmp2++;
   }
   
   if(count1>count2){
       return p1;
   }
   else if(count2>count1){
       return p2;
   }
   else{
       return NULL;
   }
}

其次,在您的 main 中,您使用的是 %c 格式字符串,它适用于单个 char,而不是整个字符串。由于无论如何你都有一个字符串,你可以避免格式字符串并直接打印它。另外,请注意,您应该明确检查 NULLs:

int main() {
   char str1[20];
   char str2[20];
   char* longest;
   
   scanf("%s%s", str1, str2);
   
   longest = string_ln(str1, str2);
   
   if (longest) {
       printf(longest);
   } else {
       printf("They are the same length");
   }
}

在写作 string_ln 时,您完全遍历两个字符串以找到它们的长度,然后比较这些数字。这可行,但您实际上 不需要 执行此操作。你只需要知道哪个更长。更长的字符串有多长并不重要。

char *string_ln(char *str1, char *str2) {
    char *iter1, *iter2;

    for (iter1 = str1, iter2 = str2;
         *iter1 && *iter2;
         iter1++, iter2++);

    if (!(*iter1 || *iter2)) {
        return NULL;
    }
    else if (*iter1) {
        return str1;
    }
    else {
        return str2;
    }
}

我们只需要遍历两个字符串,直到至少有一个字符串命中 NULL 字符。一旦我们到达那个点,我们就可以测试看看哪个迭代器是 NULL。如果两者都是,则它们的长度相同。如果第一个迭代器不为 NULL,则第一个字符串更长。否则,第二个字符串更长。

这种方法的好处是我们避免了不必要的工作,并且可以更快地比较不同长度的字符串。

对于初学者来说,函数应该这样声明

char * string_ln( const char *, const char * );

因为传递的字符串不会在函数内更改。

您正在 return 从函数中获取已修改的指针 p1 或 p2,该指针正在 while 循环之一中更改

while (*p1 != '[=11=]') {
   count1++;
   p1++;
}

while (*p2 != '[=11=]') {
   count2++;
   p2++;
}

因此 returned 指针指向字符串的终止零 '[=14=]'

而且在这个while循环之前的main中

长度=string_ln(str1, str2);

while(长度!='\0'){ printf("%c", *长度); 长度++; }

您没有检查指针 length 是否等于 NULL。因此,程序可以调用未定义的行为。

函数本身可以仅使用指针按以下方式定义。

char * string_ln( const char *p1, const char *p2 )
{
    const char *s1 = p1;
    const char *s2 = p2;

    while ( *s1 != '[=12=]' && *s2 != '[=12=]' )
    {
        ++s1;
        ++s2;
    }

    if ( *s1 == *s2 )
    {
        return NULL;
    }
    else if ( *s1 == '[=12=]' )
    {
        return ( char * )p2;
    }
    else
    {
        return ( char * )p1;
    }        
}

主要是你需要写

char *length = string_ln( str1, str2 );

if ( length != NULL )
{
    while ( *length )
    printf( "%c", *length++ );
}  

注意函数的return类型是char *而不是const char *。这是因为在 C 中没有函数重载并且 returned 指针可以指向常量字符串或非常量字符串。这是 C 中声明字符串函数的通用约定。