从 C 函数返回字符串(或 char *)

问题描述 投票:0回答:2

我需要一个函数来返回各种大小的字符串。 这是我的代码:

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

char *get_option_argument(char *arg, char *shortopt, char *longopt) {
    int len = strlen(arg) ;
    int len_shortopt = strlen(shortopt) ;
    int len_longopt = strlen(longopt) ;

    char shortopt2[len_shortopt + 1] ;
    char longopt2[len_longopt + 1] ;

    strcat(shortopt2, shortopt) ;
    strcat(shortopt2, " ") ;
    strcat(longopt2, longopt) ;
    strcat(longopt2, " ") ;

    int shortopt_boucle = 0 ;
    int longopt_boucle = 0 ;
    int find_shortopt = 0 ;
    int find_longopt = 0 ;
    int j = 0 ;
    int k = 0 ;

    for (int i=0; i<len && !(find_shortopt || find_longopt); i++) {
        if (!shortopt_boucle && arg[i] == shortopt2[0]) {
            shortopt_boucle = 1 ;
            j = 0 ;
        }
        if (!longopt_boucle && arg[i] == longopt2[0]) {
            longopt_boucle = 1 ;
            k = 0 ;
        }
        if (shortopt_boucle && j <= len_shortopt)
            if (arg[i] == shortopt2[j])
                j++ ;
            else
                j=0 ;
        if (longopt_boucle && k <= len_longopt)
            if (arg[i] == longopt2[k])
                k++ ;
            else
                k=0 ;
        if (j == len_shortopt + 1)
            find_shortopt = 1, j = i+1 ;
        if (k == len_longopt + 1)
            find_longopt = 1, k = i+1 ;
    }

    char *result = malloc(sizeof(char)*len) ; // on utilise une allocation dinamique pour pouvoire le retourner

    if (find_shortopt)
        for (int i=0; arg[j+i] != ' ' && arg[j+i] != '\0' && j+i < len ; i++)
            result[i] = arg[j+i] ;
    else if (find_longopt)
        for (int i=0; arg[k+i] != ' ' && arg[k+i] != '\0' && k+i < len ; i++)
            result[i] = arg[k+i] ;

    return result ;
}

void affiche_vache(char *arg) {
    char *eyes = get_option_argument(arg, "-e", "--eyes") ;
    free(eyes) ;
    char *hat = get_option_argument(arg, "-h", "--hat") ;
    if (strlen(eyes)!=2)
        eyes = "oo" ;
    if (strlen(hat)!=6)
        hat = " ^__^ " ;
    char *corp1 = "____" ;
    char *corp2 = "    " ;
    char *corp3 = "----" ;
    printf("         \\ %s\n", hat) ;
    printf("          \\ (%s)\\_%s__\n", eyes, corp1) ;
    printf("            (__)\\ %s  )\\/\\\n", corp2) ;
    printf("                ||%sw |\n", corp3) ;
    printf("                ||     ||\n") ;
    // free(eyes) ;
    // free(hat) ;
}

int main() {
    affiche_vache("--eyes 00 --hat _|@#|_") ;
    return 0 ;
}

函数

get_option_argument
必须从给定字符串中提取选项, 例如,
get_option_argument("-e $$", "-e", "--eyes")
必须返回
"$$"
,并且在我第一次调用它时返回,但随后就出错了。

我认为问题出在记忆上。 我首先使用这种方式声明我的字符串:

char result[size]
,但它会导致分段错误和以下警告:
function returns address of local variable
。 这就是为什么我使用
malloc
,但似乎它并没有真正起作用。
malloc 
每次都会在不同的地方分配内存吗? 带有
free
的行是注释,因为它会引发分段错误。

我为我的嘈杂示例道歉,我尝试用更简单的代码重现相同的情况,但我不太明白它何时工作或不工作。

arrays c segmentation-fault dynamic-memory-allocation
2个回答
0
投票

您可以使用以下代码为您的选项分配空间:

char shortopt2[len_shortopt + 1] ;
char longopt2[len_longopt + 1] ;

strcat(shortopt2, shortopt) ;
strcat(shortopt2, " ") ;
strcat(longopt2, longopt) ;
strcat(longopt2, " ") ;

但是对

strcat
的第二次调用会覆盖数组中的空终止符,这将允许进一步的代码进入日落状态。您需要将上面四行替换为:

strcpy(shortopt2, shortopt);
strcpy(longopt2, longopt);

我无法确切地弄清楚以下代码中的这些循环在做什么,但我怀疑您可以再次超过任一字符串的末尾,因为您使用的数组长度是

for
循环中的终端值,而不是
length - 1
。您可能需要通过调试器运行它,以准确查看失败的位置以及导致哪些变量。

另请注意 Yano 对您的

free
'ed 数组的早期
malloc
的评论。


0
投票

您的代码从第一行调用未定义的行为。

shortopt2
longopt2
未初始化,
strcat
需要有效的 C 字符串作为目标。而且它们太短,无法容纳空间
" "

    char shortopt2[len_shortopt + 2] ;
    char longopt2[len_longopt + 2] ;

    strcpy(shortopt2, shortopt) ;
    strcat(shortopt2, " ") ;
    strcpy(longopt2, longopt) ;
    strcat(longopt2, " ") ;

此外,

strlen
返回
size_t
而不是
int

我没有分析其余的代码

© www.soinside.com 2019 - 2024. All rights reserved.