为什么末尾的连接字符串与代码完全不同?

Why is the concatenated string at the end totally different from what the code does?

下面的代码看似庞大,其实很简单。我想在 C 中制作一个练习生成器,它连接乳胶格式的字符串,存储在函数局部数组中。

但是输出完全不是我预期的那样。我可能对指针做错了什么,或者在某处溢出了。

尝试了我能在互联网上找到的所有提示:

(1) 在位置0处用'\0'初始化一个字符串; (2) 使用指向字符串的指针传递给函数;

int create_exercise_string(char **s, int s_size) {
    // The format of the exercise is x+n=m;
    // ASCII 48-57 = '0' ... '9';
    int exercises_left = 10;
    char *exercise;
    char operation_list[][2] = {"+[=10=]", "-[=10=]"};
    char equal[] = "&=&"; // & is for centering on the item contained in latex;
    char array_begin[] = "\begin{eqnarray*}\n";
    char array_end[] = "\end{eqnarray*}";
    char number[1];

    strcat(*s, array_begin);
    s_size -= strlen(array_begin);

    //REMOVE
    puts("before exercise generation");
    while (exercises_left > 0 && s_size > 0) {
        exercise = malloc(256);
        if (!exercise) {
            puts("allocating error, quitting...");
            getchar();
            exit(1);
        }

        exercise[0] = '[=10=]';
// THE INTERESTED PART =================================================
        if (exercises_left < 10)
            strcat(exercise, "\\\n");
        printf("exercise number %d\n", exercises_left);
        strcpy(exercise, "x");
        //add an operator
        strcat(exercise, operation_list[rand() % 2]);
        // add a number
        number[0] = (rand() % 10) + 48;
        strcat(exercise, number);
        // add an equal
        strcat(exercise, equal);
        // add a number
        number[0] = (rand() % 10) + 48;
        strcat(exercise, number);
// END =================================================================
        s_size -= strlen(exercise);
        strcat(*s, exercise);
        free(exercise);
        exercises_left--;
    }
    //REMOVE
    puts("exercise generation ended");

    if (s_size < strlen(array_end)) {
        puts("create_exercise_string: buffer overflow detected, quitting...");
        getchar();
        exit(1); // for now... will be substituted with proper code
    }
    else strcat(*s, array_end);

    puts("allocation worked, returning in main");
    return exercises_left; // 0 if succesfull;
}

我期待输出是这样的

\begin{eqnarray*}
x-9&=&3\
x+3&=&12\
x-2&=&3\
... 7 other exercises
\end{eqnarray*}

但我实际上得到了

\begin{eqnarray*}
x-5\end{eqnarray*}&=&9\end{eqnarray*}x-9\end{eqnarray*}&=&2\end{eqnarray*}x+3\end{eqnarray*}&=&1\end{eqnarray*}x-7\end{eqnarray*}&=&0\end{eqnarray*}x+6\end{eqnarray*}&=&1\end{eqnarray*}x-6\end{eqnarray*}&=&5\end{eqnarray*}x+6\end{eqnarray*}&=&8\end{eqnarray*}x-8\end{eqnarray*}&=&6\end{eqnarray*}x+4\end{eqnarray*}&=&5\end{eqnarray*}x+1\end{eqnarray*}&=&5\end{eqnarray*}\end{eqnarray*}

整体没有添加\n,部分\end{eqnarray*}重复添加...

怎么了?

我设法修复了它。

我只能说,在处理字符串的时候,一定要注意有没有结束符,所以我需要加强对C中字符串分配的学习

问题出在变量 number[1] 上。

number[0] = rand() % 10 + 48;

此代码添加了 0 到 9 [48,57] 之间数字的字符表示形式的 ASCII。

但它不添加终止空字符!

每次我将 number 连接到 exercise 字符串时,它都会溢出到另一个具有终止空字符的局部变量,因此 strcat() 的 "undefined behaviour" 就是它一直在读取另一个局部变量。

幸运的是我在内存中有一个'\0'雷区,否则如果试图读取受保护的内存,我需要用头撞墙。

感谢您的帮助!