我需要一个函数来返回各种大小的字符串。 这是我的代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *get_option_argument(char *arg, char *shortopt, char *longopt) {
int len = strlen(arg) ;
size_t len_shortopt = strlen(shortopt) ;
size_t len_longopt = strlen(longopt) ;
// we add an extra space to provide the case when shortopt is included in longopt
char shortopt2[len_shortopt + 1] ;
char longopt2[len_longopt + 1] ;
strcpy(shortopt2, shortopt) ;
shortopt2[len_shortopt] = ' ' ;
strcpy(longopt2, longopt) ;
longopt2[len_longopt] = ' ' ;
// previous version who doesn't work
/* strcat(shortopt2, shortopt) ;
strcat(shortopt2, " ") ;
strcat(longopt2, longopt) ;
strcat(longopt2, " ") ; */
// printf("%s, %s\n", shortopt2, longopt2) ;
int shortopt_boucle = 0 ;
int longopt_boucle = 0 ;
int find_shortopt = 0 ;
int find_longopt = 0 ;
int j = 0 ;
int k = 0 ;
// We browse arg until we reach the end or find an option.
for (int i=0; i<len && !(find_shortopt || find_longopt); i++) {
// if we are not already browsing and we have found a potential start for one
if (!shortopt_boucle && arg[i] == shortopt2[0]) {
shortopt_boucle = 1 ;
j = 0 ;
}
// same for longopt
if (!longopt_boucle && arg[i] == longopt2[0]) {
longopt_boucle = 1 ;
k = 0 ;
}
// if we are procuring a potential option, we check the current character
if (shortopt_boucle && j <= len_shortopt)
if (arg[i] == shortopt2[j])
j++ ;
else
j=0 ;
// idem
if (longopt_boucle && k <= len_longopt)
if (arg[i] == longopt2[k])
k++ ;
else
k=0 ;
// if we have found one, then stop the loop and use i or j variable to mark the start of the option
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 dynamique pour pouvoir le retourner
// get the word just after the option marker
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") ;
char *hat = get_option_argument(arg, "-h", "--hat") ;
if (strlen(eyes)!=2)
eyes = "oo" ;
if (strlen(hat)!=6)
hat = " ^__^ " ;
char *corp1 = "____" ; // this part is for a next implementation
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("-e 00 -h _|@#|_") ;
return 0 ;
}
函数
get_option_argument
必须从给定字符串中提取选项。
例如,get_option_argument("-e $$", "-e", "--eyes")
必须返回"$$"
,并且在我第一次调用它时返回,但随后就出错了。
我认为问题出在记忆上。 我首先使用这种方式声明我的字符串:
char result[size]
,但它会导致分段错误和以下警告:function returns address of local variable
。
这就是为什么我使用malloc
,但似乎它并没有真正起作用。
malloc
每次都会在不同的地方分配内存吗?
并且带有 free
的行被注释掉,因为它引发了分段错误。
我为我的嘈杂示例道歉,我尝试用更简单的代码重现相同的情况,但我不太明白它何时工作或不工作。
您可以使用以下代码为您的选项分配空间:
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
的评论。
您的代码从第一行调用未定义的行为。
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
。
我没有分析其余的代码
我明白了! 事实上,这个bug来自于strcat, 感谢@OldBoy,我在我的代码中添加了以下内容:
printf ("%s, %s\n", shortopt2, longopt2);
,就在要检查的相关行之后,它显示了以下内容:
打电话后
char *eyes = get_option_argument(arg, "-e", "--eyes") ;
char *hat = get_option_argument(arg, "-h", "--hat") ;
代码连续打印,
-e , --eyes
-e -h , --eyes --hat
这意味着由于一个模糊的原因(这当然有一个很好的理由,但对我来说这是不可理解的),变量
shortopt2
和 longopt2
保持它的内容。这就是为什么该函数在第二次调用期间没有找到任何内容。
所以我修改了
strcat(shortopt2, shortopt) ;
strcat(shortopt2, " ") ;
strcat(longopt2, longopt) ;
strcat(longopt2, " ") ;
到
strcpy(shortopt2, shortopt) ;
shortopt2[len_shortopt] = ' ' ;
strcpy(longopt2, longopt) ;
longopt2[len_longopt] = ' ' ;
现在一切正常!
但是如果有人知道为什么这些变量保留其内容......