函数返回字符串 - c语言返回数组




使用C返回一个数组 (7)

C对数组的处理与Java的处理非常不同,因此您必须相应地调整思路。 C中的数组不是一流的对象(也就是说,在大多数情况下,数组表达式不会保留它的“数组性”)。 在C中,除非数组表达式是sizeof或unary &运算符的操作数,否则类型“ T N元素数组”的表达式将被隐式转换(“decay”)为“指向T指针”类型的表达式,或者如果数组表达式是一个字符串文字用于初始化声明中的另一个数组。

除此之外,这意味着您不能将数组表达式传递给函数并将其作为数组类型接收; 该函数实际上收到一个指针类型:

void foo(char *a, size_t asize)
{
  // do something with a
}

int bar(void)
{
  char str[6] = "Hello";
  foo(str, sizeof str);
}

在对foo的调用中,表达式strchar [6]转换为char * ,这就是为什么foo的第一个参数被声明为char *a而不是char a[6] 。 在sizeof str ,由于数组表达式是sizeof运算符的操作数,因此它不会转换为指针类型,因此您可以获得数组中的字节数(6)。

如果你真的感兴趣,你可以阅读Dennis Ritchie的“C语言的发展”来理解这种治疗方法的来源。

结果是函数不能返回数组类型,这很好,因为数组表达式不能作为赋值的目标。

最安全的方法是让调用者定义数组,并将其地址和大小传递给应该写入该数组的函数:

void returnArray(const char *srcArray, size_t srcSize, char *dstArray, char dstSize)
{
  ...
  dstArray[i] = some_value_derived_from(srcArray[i]);
  ...
}

int main(void)
{
  char src[] = "This is a test";
  char dst[sizeof src];
  ...
  returnArray(src, sizeof src, dst, sizeof dst);
  ...
}

另一种方法是让函数动态分配数组并返回指针和大小:

char *returnArray(const char *srcArray, size_t srcSize, size_t *dstSize)
{
  char *dstArray = malloc(srcSize);
  if (dstArray)
  {
    *dstSize = srcSize;
    ...
  }
  return dstArray;
}

int main(void)
{
  char src[] = "This is a test";
  char *dst;
  size_t dstSize;

  dst = returnArray(src, sizeof src, &dstSize);
  ...
  free(dst);
  ...
}

在这种情况下,调用者负责使用free库函数释放数组。

请注意,上面的代码中的dst是一个简单的指向char的指针,而不是指向char数组的指针。 C的指针和数组语义是这样的,你可以将下标运算符[]应用于数组类型指针类型的表达式; src[i]dst[i]都将访问​​数组的第i个元素(即使只有src具有数组类型)。

可以声明一个指向T的N元素数组的指针,并执行类似的操作:

char (*returnArray(const char *srcArr, size_t srcSize))[SOME_SIZE]
{
  char (*dstArr)[SOME_SIZE] = malloc(sizeof *dstArr);
  if (dstArr)
  {
    ...
    (*dstArr)[i] = ...;
    ...
  }
  return dstArr;
}

int main(void)
{
  char src[] = "This is a test";
  char (*dst)[SOME_SIZE];
  ...
  dst = returnArray(src, sizeof src);
  ...
  printf("%c", (*dst)[j]);
  ...
}

上述几个缺点。 首先,C的老版本期望SOME_SIZE是一个编译时常量,意味着该函数只能处理一个数组大小。 其次,在应用下标代码之前,必须先取消引用指针。 在处理多维数组时,指向数组的指针可以更好地工作。

我对C相对比较陌生,在处理数组的方法方面需要一些帮助。 来自Java编程,我习惯于能够说int [] method()为了返回一个数组。 但是,我发现用C语言你必须在返回数组时使用指针。 作为一名新程序员,即使在我浏览过很多论坛的时候,我也完全不理解这一点。

基本上,我试图编写一个方法返回一个字符数组在C中我将提供一个数组的方法(让我们称之为returnArray)。 它将从前一个数组中创建一个新数组并返回一个指向它的指针。 我只需要一些帮助,了解如何启动它,以及如何在将指针发送出阵列时读取指针。 任何帮助解释这一点表示赞赏。

数组返回函数的建议代码格式

char *returnArray(char array []){
 char returned [10];
 //methods to pull values from array, interpret them, and then create new array
 return &(returned[0]); //is this correct?
} 

函数的调用者

int main(){
 int i=0;
 char array []={1,0,0,0,0,1,1};
 char arrayCount=0;
 char* returnedArray = returnArray(&arrayCount); ///is this correct?
 for (i=0; i<10;i++)
  printf(%d, ",", returnedArray[i]);  //is this correctly formatted?
}

我还没有测试过,因为我的C编译器目前不工作,但我想弄清楚这一点


你不能从C中的函数返回数组。你也不能(不应该)这样做:

char *returnArray(char array []){
 char returned [10];
 //methods to pull values from array, interpret them, and then create new array
 return &(returned[0]); //is this correct?
} 

returned会创建自动存储持续时间,一旦它离开其声明范围(即函数返回时),对它的引用将变为无效。

您将需要动态分配函数内部的内存或填充调用者提供的预分配缓冲区。

选项1:

动态分配函数内部的内存(调用者负责释放ret

char *foo(int count) {
    char *ret = malloc(count);
    if(!ret)
        return NULL;

    for(int i = 0; i < count; ++i) 
        ret[i] = i;

    return ret;
}

像这样称呼它:

int main() {
    char *p = foo(10);
    if(p) {
        // do stuff with p
        free(p);
    }

    return 0;
}

选项2:

填充调用者提供的预分配缓冲区(调用者分配buf并传递给函数)

void foo(char *buf, int count) {
    for(int i = 0; i < count; ++i)
        buf[i] = i;
}

并称它是这样的:

int main() {
    char arr[10] = {0};
    foo(arr, 10);
    // No need to deallocate because we allocated 
    // arr with automatic storage duration.
    // If we had dynamically allocated it
    // (i.e. malloc or some variant) then we 
    // would need to call free(arr)
}

你可以使用这样的代码:

char *MyFunction(some arguments...)
{
    char *pointer = malloc(size for the new array);
    if (!pointer)
        An error occurred, abort or do something about the error.
    return pointer; // Return address of memory to the caller.
}

当你这样做的时候,通过将地址传递给空闲,以后可以释放内存。

还有其他选项。 例程可能会返回一个指向某个数组(或数组的一部分)的指针,该指针是某个现有结构的一部分。 调用者可以传递一个数组,而例程只是写入数组,而不是为新数组分配空间。


你的情况,你正在堆栈上创建一个数组,一旦你离开函数作用域,该数组将被释放。 相反,创建一个动态分配的数组并返回一个指向它的指针。

char * returnArray(char *arr, int size) {
    char *new_arr = malloc(sizeof(char) * size);
    for(int i = 0; i < size; ++i) {
        new_arr[i] = arr[i];
    }
    return new_arr;
}

int main() {

    char arr[7]= {1,0,0,0,0,1,1};
    char *new_arr = returnArray(arr, 7);

    // don't forget to free the memory after you're done with the array
    free(new_arr);

}

将数组声明为全局变量,以便每个函数都可以对其进行编辑。 这里是一个例子:

#include<stdio.h>
#include<conio.h> 


char a[1000];
void edit(char b);
main()
{
 edit(a);
 printf("%s", a);
}

void edit(char b)
{
 for(int i=0;i<sizeof(b);i++)
 a[i]=i;
}

我并不是说这是针对给定问题的最佳解决方案或首选解决方案。 但是,记住函数可以返回结构可能是有用的。 虽然函数不能返回数组,但数组可以包装在结构体中,并且函数可以返回结构体,从而携带数组。 这适用于固定长度的数组。

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

    typedef
    struct 
    {
        char v[10];
    } CHAR_ARRAY;



    CHAR_ARRAY returnArray(CHAR_ARRAY array_in, int size)
    {
        CHAR_ARRAY returned;

        /*
        . . . methods to pull values from array, interpret them, and then create new array
        */

        for (int i = 0;  i < size; i++ )
            returned.v[i] = array_in.v[i] + 1;

        return returned; // Works!
    } 




    int main(int argc, char * argv[])
    {
        CHAR_ARRAY array = {1,0,0,0,0,1,1};

        char arrayCount = 7;

        CHAR_ARRAY returnedArray = returnArray(array, arrayCount); 

        for (int i = 0; i < arrayCount; i++)
            printf("%d, ", returnedArray.v[i]);  //is this correctly formatted?

        getchar();
        return 0;
    }

我邀请对这种技术的优缺点进行评论。 我没有打扰过这么做。


这里有一个用不同选项传递字符串并返回字符串的小例子。

//include DPI
#include "svdpi.h"
//include the IO files
#include <stdio.h>
//include string functions
#include <string.h>
//include use of malloc
#include <stdlib.h>

//to add the ability to use printf
// same inputs as defined in SV



 /* function declaration text char stream passed as pointer value and text2 passed as pointer reference */
  char * return_string_in_c( char *text,  char **text2) {
    char *fix="This variable cannot be changed although it is a pointer, just as example";/*fix allocation and constant*/
    char dest[50]="Variable array created in a function:";/* String array max 50 chars allocated*/
    char *out = malloc(sizeof(char) * 100);/* Dynamic string max 100 chars allocated*/
    /* Concatenate input text and put in out of strcat*/
    strcat(out, text);/* initialize out using strcat and text string*/
    printf("fix : |%s|,dest : |%s|,text : |%s|,out : |%s|\n", fix,dest,text,out);
    *text2=dest;/* allocate pointer value with dest*/
    *text2=out;/* now do the same overwrite allocate pointer value with out*/
    return out;
}

 /* main */
 void main() {
    char text[100]="from_main_text_variable";/*max 100 chars allocated*/
    char *text2;/* pointer not allocated*/
    char *point = return_string_in_c(text, &text2);/* &text2 passing by reference*/
    printf("Final destination string : |%s|\n", text2);
    printf("point output : |%s|\n", point);

 }

输出将是:

fix:|尽管它是一个指针,但这个变量不能被改变,就像example |,dest:|在一个函数中创建的变量数组:| | text | | from_main_text_variable |,out:| from_main_text_variable |

最终目标字符串:| from_main_text_variable |

点输出:| from_main_text_variable |





char