【问题标题】:Return a value inside and outside the while loop in C在 C 中的 while 循环内部和外部返回一个值
【发布时间】:2026-02-16 12:30:01
【问题描述】:

我想编写一个程序来读取文件并分解其内容。该文件基本上包含一个包含 ID 的字符串。文件内容如下:

[root@ben-pc ~]# cat file
1,2,3

我想从解析函数中分别返回 ID 1、2、3。在我的代码中,我得到了 while 循环内的前两个 ID 和 while 循环外的最后一个 ID。但我无法正确返回所有这些值。我知道我不能在这样的代码中使用两个return 调用。任何人都可以建议我如何按需要进行这项工作。这是我的代码:

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

char *get_group_members (char* file)
{
    FILE *fp;
    char *str;
    char filename[64];
    int c;
    size_t n = 0;

    snprintf(filename, sizeof(char) * 64, "/home/ben/%s", file);
    fp = fopen(filename, "r");

    if(fp == NULL)
    {
            perror("Error opening file");
    }

    str = malloc(100);

    while ((c = fgetc(fp)) != EOF )
    {
            if(c != ',')
            {
                    str[n++] = (char) c;
            }
            else
            {
                    //return str; Not working
                    printf("%s,", str);
                    n = 0;
            }
    }
    //return str; Not working
    printf("%s", str);
    fclose(fp);
}

int main (void)
{
printf("Group Members are ::\n");
printf("%s\n", get_group_members("file"));
return 0;
}

【问题讨论】:

  • while 循环中的第一个 return 将终止函数。其余代码被跳过。
  • 可以返回一个char *的数组。
  • 函数结束返回怎么样?
  • 在从函数返回之前,您不会以 0 终止您的计算。您还应该关闭get_group_members 中的文件,即使这不是问题,因为程序将在调用get_group_members 后立即退出。
  • @EOF 在函数末尾返回只会给出最后一个数字。

标签: c linux while-loop return


【解决方案1】:

这里有两个主要选项:返回一个字符串数组,或者进行增量解析。

  • 增量解析:您无需在函数中打开文件,而是将已打开的FILE* 传递给它。然后该函数返回下一个成员(作为单个字符串),如果没有更多成员,则返回 0。 fopen/fclose 必须由调用函数管理,用法可能如下所示(省略错误检查):

    FILE *fd = fopen(...);
    char *member;
    while((member = get_member(fd))) {
        // do sth.
    
        free(member);
    }
    fclose(fd);
    

    增量解析的好处在于,您无需一次将所有返回的数据存储在内存中,也无需事先知道要返回的元素数量(为它们分配存储空间),也无需处理重新分配读取比预期更多的元素。

    示例实现:

    char *get_group_member (FILE *fp)
    {
        char *str = malloc(100);
        int n = 0;
        int c;
    
        while ((c = fgetc(fp)) != EOF)
        {
            if(c != ',')
            {
                str[n++] = (char) c;
            }
            else
            {
                break;
            }
        }
    
        if(n)
        {
            str[n++] = 0;
            return str;
        }
    
        free(str);
        return 0;
    }
    

    注意:此实现与您的原始实现一样,如果任何单个成员的长度超过 99 个字符,则会出现缓冲区溢出。

  • 字符串数组:返回一个char **,其大小为numberOfItems + 1,以0结尾。

    在这样的数组上迭代很容易,看起来像这样:

    char ** result = get_members...;
    char *current_member;
    
    while((current_member = result++)) {
        // do something with current_member
    }
    
  • 或者通过使用两个输出参数,像这样:

    void get_members_...(char ** result, int *result_size);

    然后您分配一个适当大小的数组并相应地设置 result_size。

  • 您也可以创建类似链表的东西,但这会使使用结果更加复杂,并且通常需要更多代码。

【讨论】:

  • 感谢您解释得如此清楚。我会尝试以同样的方式实现。