-2

出现“冲突类型”错误,所以我该怎么办,并且更喜欢一个好的替代方案。主要问题是从函数返回一个数组

#include<stdio.h>
int* freqofchar(char);
int main()
{

    char str[100];
    printf("Enter a sentence below :\n");
    gets(str);
    int* p = freqofchar(str);
    for(int i=0;i<128;i++){
        if(*p>0){
            printf("%c occurred %d times\n",(char) i , *p++);
        }
    }
    return 0;
}
int* freqofchar(char str[]){
    int freq[128] = {0};
    for(int i = 0;str[i] != '\0';i++){
        freq[ str[i] ]++;
    }
    return freq;
}

4

4 回答 4

1

你有2个问题:

1)冲突类型:

int* freqofchar(char)

在声明中,但是

int* freqofchar(char str[])

在定义中。

2)您正在从 freqofchar 返回分配在堆栈上的频率

于 2020-04-26T09:36:16.037 回答
1

您看到的错误是由于函数原型与其实际定义不匹配造成的。

但是,您也有其他问题:

  • gets函数已从 C 标准(因为)中删除,这是有充分理由的,在任何情况下都不应使用。您可以fgets改为使用来读取输入。但是如果fgets读入,则需要删除换行符。

  • 您正在返回一个指向局部变量的指针,该变量的生命周期在函数freqofchar返回后无效,这是未定义的行为。您可以改为传递另一个参数。一般来说,您可能需要考虑动态分配(例如 via malloc),但在这种情况下 - 您只需要一个小数组 - 主函数的本地数组,它具有自动存储持续时间,因此它的生命周期在持续时间内有效main()并且它可以被安全地传递给freqofchar函数,而不会无效或被取消分配,因为对象(freq这里是引用的对象)的生命周期在它被使用时仍然有效freqofchar()- 在这里更适合。

以下是固定解决方案的样子:

#include<stdio.h>
#include<string.h>

void freqofchar(char*, int*);

int main()
{
    char str[100] = {0};
    int freq[256] = {0};

    printf("Enter a sentence below :\n");
    fgets(str, sizeof str, stdin);

    /* Remove the newline if present. */
    char *p = strchr(str, '\n');
    if (p) *p = '\0';

    freqofchar(str, freq);

    for(size_t i = 0;i < sizeof freq; i++) {
        if(freq[i]) {
            printf("%c occurred %d times\n", i, freq[i]);
        }
    }
    return 0;
}

void freqofchar(char str[], int freq[])
{
    for(int i = 0;str[i] != '\0';i++) {
        freq[ str[i] ]++;
    }
}
于 2020-04-26T09:51:22.830 回答
-1

函数参数在函数声明中声明为具有类型char

int* freqofchar(char);
                ^^^^^

但是在函数声明中,同样是它的定义

int* freqofchar(char str[]){
                ^^^^^^^^^ 

该参数被声明为具有类型char [](由编译器调整为 type char *)。

这个错字是编译器消息的原因。

但在任何情况下,该函数至少应声明为

unsigned int * freqofchar( const char [] );

也就是说,将频率定义为有符号整数类型是没有意义的,并且参数应具有限定符const,因为传递的字符串在函数中没有被更改。

该程序具有未定义的行为,因为该函数返回指向具有自动存储持续时间的本地数组的指针,该数组在退出函数后将不再存在。

int* freqofchar(char str[]){
    int freq[128] = {0};
    //...
    return freq;
}

您应该动态分配数组或使用存储说明符声明它static。在最后一种情况下,每次调用函数时都需要将数组的元素重置为零。

该函数gets是一个不安全的函数,不再被 C 标准支持。而是使用标准 C 函数fgets

这是一个演示程序。

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

unsigned int* freqofchar( const char *);

int main( void )
{
    enum { N = 100 };
    char str[N];
    str[0] = '\0';

    printf( "Enter a sentence below : " );

    fgets( str, N, stdin );

    // remove the appended new line character '\n'
    str[ strcspn( str, "\n" ) ] = '\0';

    unsigned int *p = freqofchar( str );

    for ( size_t i = 0; i < 128; i++ )
    {
        if ( p[i] )
        {
            printf( "'%c' occurred %u times\n", ( char )i , p[i] );
        }
    }

    free( p );

    return 0;
}

unsigned int * freqofchar( const char str[] )
{
    enum { N = 128 };

    unsigned int *freq = calloc( N, sizeof( unsigned int ) );

    while ( *str ) ++freq[ ( size_t )*str++ ];

    return freq;
}

它的输出可能看起来像

Enter a sentence below : Hello World!
' ' occurred 1 times
'!' occurred 1 times
'H' occurred 1 times
'W' occurred 1 times
'd' occurred 1 times
'e' occurred 1 times
'l' occurred 3 times
'o' occurred 2 times
'r' occurred 1 times

如果使用静态存储说明符定义函数,则其定义可以如下所示。

#include <stdio.h>
#include <string.h>

unsigned int* freqofchar( const char *);

int main( void )
{
    enum { N = 100 };
    char str[N];
    str[0] = '\0';

    printf( "Enter a sentence below : " );

    fgets( str, N, stdin );

    // remove the appended new line character '\n'
    str[ strcspn( str, "\n" ) ] = '\0';

    unsigned int *p = freqofchar( str );

    for ( size_t i = 0; i < 128; i++ )
    {
        if ( p[i] )
        {
            printf( "'%c' occurred %u times\n", ( char )i , p[i] );
        }
    }

    return 0;
}

unsigned int * freqofchar( const char str[] )
{
    enum { N = 128 };

    static unsigned int freq[N];

    memset( freq, 0, N * sizeof( unsigned int ) );

    while ( *str ) ++freq[ ( size_t )*str++ ];

    return freq;
}
于 2020-04-26T10:06:28.190 回答
-3
  1. 您犯了 C 编程中最常见的错误之一。您返回指向函数返回后不存在的对象的指针。

可能的解决方案

一个。使用动态分配的内存

int* freqofchar(char *str)
{
    int *freq = malloc(128 * sizeof(*freq)); // or if you want to zero it calloc

    /* ... */    
    return freq;
}

但是您需要在不需要时释放分配的内存。

湾。使用静态数组或全局数组

int* freqofchar(char *str)
{
    static freq[128];

    /* ... */    
    return freq;
}

或者

static freq[128];

int* freqofchar(char *str)
{

    /* ... */    
    return freq;
}

此解决方案的缺点:函数不可重入,频率数组无法传递给异步任务和函数,因为如果再次调用函数,它可以更改。初始化仅在第一次调用该函数之前发生一次。

C。将其包装在 union 或 struct 中并返回整个对象

struct freqstruct {
    int freq[128];
};

struct freqstruct freqofchar(char *str)
{
    struct freqstruct freq = {0};

    /* ... */    
    return freq;
}

缺点 - 包装到的整个数组struct被复制。这不是很明智的内存和性能。

  1. 您的定义与函数的声明不匹配。说明你没有付出足够的努力。
int* freqofchar(char *str)

int* freqofchar(char *str)
{
     /* ... */
}

或 - 但我个人不喜欢这种表示法,因为它让初学者认为传递的是数组而不是指针。

int* freqofchar(char str[])

int* freqofchar(char str[])
{
     /* ... */
}
  1. 这个函数不是 const corrent - 参数str应该是const char *strorconst char str[]
于 2020-04-26T10:02:21.983 回答