函数main从子例程接收到不正确的值

时间:2015-01-29 00:58:44

标签: c

此代码不起作用 - 将数据从子例程传递到main并分配内存的问题。

子程序内的计算是正确的,但是main接收的值是不正确的 - main中的变量具有随机值,例如sRates。

#include <stdio.h>
#include <malloc.h>
#include "sndfile.h"

int main(int argc, char *argv[])
{
    int sRates , sRatem , ret;
    long    nSamples=0, nSamplem;   
    float   *datas, *datam;


    printf("Read Test\n");
    if (argc != 3) {
        fprintf(stderr, "Expecting two wav file as argument\n");
        return 1;
    }


    ret =  readWav(argv[1], nSamples, sRates, &datas );
    if (ret != 0) {
    printf("Error\n");
    }
    // Output Info
    printf("Read %ld frames from %s, Sample rate: %d, Length: %fs\n",
        nSamples, argv[1], sRates, (float)nSamples/sRates);
    printf("Read %ld frames from %s, Sample rate: %d, Length: %fs\n",
        nSamples, argv[1], sRates, (float)nSamples/sRates);

//  free(datas);

    return 0;
}

int  readWav(char *fname, long *numFrames, int *sRate, float **buffer  ) 
{

    // Open sound file
    SF_INFO sndInfo;
    SNDFILE *sndFile = sf_open(fname, SFM_READ, &sndInfo);
    if (sndFile == NULL) {
        fprintf(stderr, "Error reading source file '%s': %s\n", fname, sf_strerror(sndFile));
        return 1;
    }


    printf("1Format of the audio file = %i\n", sndInfo.format);
    printf("2Number of channels = %i\n", sndInfo.channels);
    printf("3Sample Rate  = %d\n", sndInfo.samplerate);
    printf("4 Sample count  = %ld\n", (long)sndInfo.frames);
    sRate= sndInfo.samplerate;

    // Allocate memory
    buffer = (float *)malloc(sndInfo.frames * sndInfo.channels * sizeof(float));
    if (buffer == NULL) {
        fprintf(stderr, "Could not allocate memory for file\n");
        sf_close(sndFile);
        return 1;
    }

      // Load data
    numFrames = sf_readf_float(sndFile, buffer, sndInfo.frames);

    // Check correct number of samples loaded
    if (numFrames != sndInfo.frames) {
        fprintf(stderr, "Did not read enough frames for source\n");
        sf_close(sndFile);
        free(buffer);
//      return 1;
    }
    else {
        printf("Successfully read file\n");
        numFrames = sndInfo.frames;
    }
    // Output Info
    printf("Read %ld frames from %s, Sample rate: %d, Length: %fs\n",
//      numFrames, fname, sndInfo.samplerate, (float)numFrames/sndInfo.samplerate);
        numFrames, fname, sRate, (float)numFrames/sndInfo.samplerate);


    sf_close(sndFile);
//  return(buffer);
    return(0);

}

2 个答案:

答案 0 :(得分:3)

在C中,所有参数都按值传递,因此如果你想要一个类似于参数的参数,你必须传递一个指针。由于您想要返回float*,因此需要传递float**

实际上你传递的是,但你没有正确使用它(请使用-Wall或等效的编译器来启用警告。)

代码应该或多或少地像这样:

int  readWav(const char *fname, long *numFrames, int *sRate, float **buffer) 
{
    *buffer = malloc(...);
    //if you do not feel comfortable writing `*buffer` everywhere:
    float *data = *buffer;
    ///....
    *numFrames = sf_readf_float(...);
    ///....
    *sRate = sndInfo.samplerate;
    ///....
}

int main()
{
    long nSamples;
    int sRates;
    float *datas;
    ret =  readWav(argv[1], &nSamples, &sRates, &datas);
    //...
}

答案 1 :(得分:1)

您的代码中有几处错误

  1. 您没有声明readWav()并且您从main()调用它,它巧合,即因为它确实返回int。< / p>

  2. 您正在将datas的地址传递给readWav(),请注意&datas的类型为float **readWav()期待{{1} }}

    如果你打开了编译器警告,你就会注意到这一点。

  3. 您正在将float *nSamples的值传递给sRate,并且您希望主网中的readWav()nSamples获得初始化后,您需要传递其地址。

  4. 您检查sRate的返回值,但仍尝试访问readWav()指针。

  5. 这是您的代码的固定版本

    datas

    提示:您应该尝试以只有一个退出点的方式编写您的函数,我喜欢使用#include <stdio.h> #include "sndfile.h" int readWav(const char *const fname, long *numFrames, int *sRate, float **buffer); int main(int argc, char *argv[]) { int sRates, sRatem, ret; long nSamples = 0, nSamplem; float *datas, *datam; printf("Read Test\n"); if (argc != 3) { fprintf(stderr, "Expecting two wav file as argument\n"); return 1; } ret = readWav(argv[1], &nSamples, &sRates, &datas); if (ret != 0) { printf("Error\n"); return 1; } // Output Info printf("Read %ld frames from %s, Sample rate: %d, Length: %fs\n", nSamples, argv[1], sRates, (float)nSamples/sRates); printf("Read %ld frames from %s, Sample rate: %d, Length: %fs\n", nSamples, argv[1], sRates, (float)nSamples/sRates); free(datas); return 0; } int readWav(const char *const fname, long *numFrames, int *sRate, float **buffer) { // Open sound file SF_INFO sndInfo; if ((sRate == NULL) || (numFrames == NULL) || (buffer == NULL)) { fprintf(stderr, "Invalid arguments passed to readWav()\n"); return 1; } SNDFILE *sndFile = sf_open(fname, SFM_READ, &sndInfo); if (sndFile == NULL) { fprintf(stderr, "Error reading source file '%s': %s\n", fname, sf_strerror(sndFile)); return 1; } printf("1Format of the audio file = %i\n", sndInfo.format); printf("2Number of channels = %i\n", sndInfo.channels); printf("3Sample Rate = %d\n", sndInfo.samplerate); printf("4 Sample count = %ld\n", (long)sndInfo.frames); // Allocate memory *buffer = malloc(sndInfo.frames * sndInfo.channels * sizeof(float)); if (*buffer == NULL) { fprintf(stderr, "Could not allocate memory for file\n"); sf_close(sndFile); return 1; } *sRate = sndInfo.samplerate; // Load data *numFrames = sf_readf_float(sndFile, *buffer, sndInfo.frames); // Check correct number of samples loaded if (*numFrames != sndInfo.frames) { fprintf(stderr, "Did not read enough frames for source\n"); sf_close(sndFile); free(*buffer); } else { printf("Successfully read file\n"); *numFrames = sndInfo.frames; } // Output Info printf("Read %ld frames from %s, Sample rate: %d, Length: %fs\n", *numFrames, fname, *sRate, (float)*numFrames/sndInfo.samplerate); sf_close(sndFile); return(0); } ,尽管宗教程序员相信goto 1}},它使您的代码更具可读性和可维护性。

    我的意思是你可以有一个标签,你可以从函数中返回错误代码并进行所有清理,如下所示

    goto