为什么末尾的连接字符串与代码完全不同?
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'雷区,否则如果试图读取受保护的内存,我需要用头撞墙。
感谢您的帮助!
下面的代码看似庞大,其实很简单。我想在 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'雷区,否则如果试图读取受保护的内存,我需要用头撞墙。
感谢您的帮助!