C中的字符串操作会导致随机的字符串内容

问题描述

我正在为必须使用Flex的学校分配作业。我正在尝试执行一些简单的字符串操作,但是遇到了一些我不理解的奇怪结果。以下代码应该用相应的数字替换输入的第二个字母。

我的代码

uid           [a-z][a-z][a-z]+
%%

{uid}   {
                char ID[strlen(yytext)];
                strncat(ID,yytext,1);
                char comp = yytext[1];
                if (comp=='a'||comp=='j'||comp=='s'){
                  strcat(ID,"1");
                }else if(comp=='b'||comp=='k'||comp=='t'){
                  strcat(ID,"2");
                }else if(comp=='c'||comp=='l'||comp=='u'){
                  strcat(ID,"3");
                }else if(comp=='d'||comp=='m'||comp=='v'){
                  strcat(ID,"4");
                }else if(comp=='e'||comp=='n'||comp=='w'){
                  strcat(ID,"5");
                }else if(comp=='f'||comp=='o'||comp=='x'){
                  strcat(ID,"6");
                }else if(comp=='g'||comp=='p'||comp=='y'){
                  strcat(ID,"7");
                }else if(comp=='h'||comp=='q'||comp=='z'){
                  strcat(ID,"8");
                }else if(comp=='i'||comp=='r'){
                  strcat(ID,"9");
                }
                strncat(ID,yytext+2,strlen(yytext)-2);
                printf("%s\n",ID);
                printf("ID strlen: %d\n",strlen(ID));
                return 1;

运行以上代码后得到的结果是:

Result

所以我不太确定为什么会得到上述结果,该结果也不是完全可重复的,我得到的随机字母和字符总是不同的。我查找了有关如何操作字符串的多种指南,但无法弄清自己一生中做错了什么。第一个输入的结果是正确的,但是我尝试输入的第二个输入的结果中包含不可读的字符。

解决方法

C99可变长度数组(VLA)

char ID[strlen(yytext)];

的大小不足以容纳完整的yytext。如果C字符串s的长度(即strlen(s)n,则需要n+1个字节的存储空间。这是因为字符串以空字节结尾。

strncat(ID,yytext,1);

strncat函数需要使用有效字符串作为参数:以null终止的字符数组。它将字符附加到左参数。但是ID数组尚未初始化。

另一个问题是strncat函数和它的strncpy堂兄一样,不会以空字符终止目标缓冲区(在琐碎的情况下,字符串短于指定的{{1}时除外) }。

这里可能是其中之一:

n

snprintf(ID,1,"%s",yytext);

sprintf(ID,"%.1s",yytext);

我将按照以下内容写整件事:

char ID[strlen(yytext)] = ""; // zero-initialize it
ID[0] == yytext[0];           // ID now string of length 1.

这个想法似乎只是用数字代码代替第二个字符,或者根本不用任何代码。我们知道char ID[strlen(yytext)+1]; int comp = yytext[1]; int code = -1; switch (comp) { case 'a': case 'j': case 's': code = 1; break; // ... similarly for other cases: } if (code != -1) sprintf(ID,"%c%d%s",yytext[0],code,yytext + 2); else sprintf(ID,"%c%s",yytext + 2); 足够大,可以容纳ID的结果,只要sprintf是0到9范围内的整数。

这是另一种方式:

code