繁体   English   中英

C基本字符串返回函数

[英]C Basic String Return Function

我对C还是很陌生。我仍然对指针一无所知。 我试图做一个返回String的方法。 这是功能,仍然不完整。

char getS(char *fileName){
    FILE *src;
    if((src = fopen(fileName, "r")) == NULL){
        printf("%s %s %s", "Cannot open file ", fileName, ". The program is now ending.");
        exit(-1);
    }
    char *get = " ";        
    //insert getting a random word here
    return(*get);
}

我试图像这样调用方法

char *article = getS("articles.txt");
char *noun = getS("nouns.txt");
char *verb = getS("verbs.txt");

编译器给我这个:

error: invalid type argument of unary ‘*’ (have ‘int’)

我该怎么办?

以下信息可能会比您想要的要多得多。 不必太担心现在就吸收它,但是以后可能会需要它。

首先,有关术语的重要说明。 C没有“字符串”类型。 引用ISO C标准:

字符串是由第一个空字符终止并包括第一个空字符的连续字符序列。 [...] 指向字符串的指针是指向其初始(最低寻址)字符的指针。

特别是, char*值是一个指针, 而不是字符串(尽管我们通常使用char*指针来访问和操作字符串)。 即使数组本身也可以不是字符串,尽管它可以包含字符串。

对于您的(相对简单的)函数,您要返回的char*值指向字符串文字(的第一个字符),因此内存管理不是问题。 坦率地说,对于更复杂的情况,该语言并不是特别有用,您必须自己做一些工作来管理内存。

函数可以轻松地返回指向字符串的char*值,从而使调用者可以对该字符串进行操作,但是构成该字符串的字符存储在哪里?

有(至少)三种常见方法。

(1)该函数返回一个指向char 静态数组开头的指针:

char *func(void) {
    static char result[100];
    // copy data into result
    return result;
}

这行得通,但是有一些缺点。 result数组只有一个副本,对func()连续调用将破坏该数组的内容。 数组的大小是固定的; 它必须足够大以容纳它可以返回的最大字符串。 标准的C asctime()函数以这种方式工作。

(2)调用者可以传递一个指向字符串的指针,然后让函数将其填充:

void func(char *buffer) {
    // code to copy data into the array pointed to by buffer
}

这给调用方带来了负担,该调用方必须分配一个char数组,尤其是必须知道它需要多大。

(3)该函数可以使用malloc()为字符串分配内存:

char *func(void) {
    char *result = malloc(some_number);
    if (result == NULL) {
         // allocation failed, cope with the error
    }
    // copy data into the array pointed to by result
    return result;
}

这样做的好处是该函数可以决定需要分配多少内存。 但是调用者必须知道该字符串是在堆上分配的,因此以后可以通过调用free()释放它。 malloc()free()函数也可能相对昂贵(但不要担心,除非您确定程序的性能不够好)。

实际上,有第四种方法,但这是错误的

char *bad_func(void) {
    char result[100];
    // copy data into result
    return result; // equivalent to "return &result[0];"
}

这里的问题是result在函数中是局部的,并且没有定义为static ,因此一旦函数返回,数组对象就不再存在。 调用方将收到一个指向不再保留的内存的指针,该指针可以在您的背后重复使用。 您可以返回指向本地static对象的指针(因为在程序生命周期中存在单个副本),并且可以返回本地非static对象的 ,但是您不能安全地返回本地的地址static对象。

comp.lang.c FAQ是一个很好的资源。

您的函数应该返回一个char *(一个字符串),而不是一个char,并且它应该返回相同的值。 因此该函数变为:

char * getS(char *fileName) {
    FILE *src;
    if((src = fopen(fileName, "r")) == NULL) {
        printf("%s %s %s", "Cannot open file ", fileName, ". The program is now ending.");
        exit(-1);
    }

    char *get = " ";        
    //insert getting a random word here

    return get;
}

这完全取决于您的字符串是否具有恒定大小。 通常,人们会为此类函数使用缓冲区参数,因为如果您在函数内部分配字符串存储空间,并返回指向该函数的指针,那么您将必须在函数外部释放内存,如果不这样做,您将丢失内存引用会导致内存泄漏。

因此,返回字符串的函数的最佳方法是这样的:

void getS(char *fileName, char *output, size_t len)
{
    FILE *src;
    if((src = fopen(fileName, "r")) == NULL)
    {
        printf("Cannot open file '%s'. The program is now ending.", fileName);
        exit(-1);
    }
    fread(output, sizeof(char), len, src); // Just an example without error checking
    fclose(src);
}

然后,您将像这样使用它:

char content[512];
getS("example.txt", content, 512);
// From now, you can use 'content' safely

或使用malloc.h进行动态分配:

char *content = (char *)malloc(512 * sizeof(char));
getS("example.txt", content, 512);
// Use 'content', and after using it, free its memory:
free(content);

但这是从时间开始您将学会正确使用它的时间。 但是,如果要以任何方式返回文字字符串(除了不完整的示例代码,情况并非如此),则必须使用char *作为函数的返回类型,并return get; 而不是*get ,因为使用*get可以返回一个字符(例如第一个字符),而不是指向字符串的指针。

FrankieTheKneeMan的答案对于您了解返回的内容以及代码为何不起作用非常有用。

getS的类型为char但您将其分配给char*类型的变量。 大概您希望getS返回一个字符串,所以它的类型应该是char* ,并且应该返回get而不是*get (这只是get的第一个字符)。

C中的指针是其他一些信息的地址。 C带有两个一元运算符来处理。

*

解引用指针-或在指向的内存空间中获取信息。

&

获取您正在谈论的信息的地址,因此:

int p;
int* q = &p; //int* is a pointer to an it.

q==p; //Error (or at least a warning)
*q == p; //true
q == &p; //true
*q == &p; //ERROR
&q == &p; //false, but also probably an error, depending on your compiler and settings

因此,当您声明char * get ,即是在声明“指向char的指针”-C知道,按照惯例,它可以视为char数组。 但是,当您尝试return * get ,C认为您正在尝试通过get寻址的内存返回char。

因此, return get ,您将返回要查找的指针。

这是否使全能指针神秘化?

(此外:您可能希望对char *进行malloc分配,以避免指针被堆栈存储器清除,但这是另一个完全不同的问题)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM