代码
#include <stdio.h>void main()
{char arr[4];scanf("%s",arr);printf("%s\n",arr);for(int i = 0 ; arr[i] != '\0' ; i++){printf("%c\n",arr[i]);}char temp;for(int i = 0;i < 3;i++){for(int j = 0;j < 3-i;j++){if(arr[j]>arr[j+1]){temp = arr[j];arr[j] = arr[j+1];arr[j+1] = temp;}}}for(int i = 0 ;arr[i] != '\0' ;i++){printf("%c\n",arr[i]);}
}
为什么这段代码最后会多输出一个2出来?
这个问题的根源在于char arr[4];
数组的大小和如何使用它。
当你用scanf("%s", arr);
读取一个字符串到一个字符数组中时,C语言会自动在字符串末尾添加一个空字符('\0'
)作为字符串的终止符。这意味着,如果你的数组大小为4,你最多只能安全地存储3个字符的字符串,保留最后一个位置给终止符'\0'
。
如果你输入了一个3字符的字符串,例如"123",那么在内存中arr
会是{'1', '2', '3', '\0'}
。但是,如果你输入的字符串超过了3个字符,scanf
函数会覆盖数组的边界,可能会导致未定义行为,包括覆盖内存中的其他数据。
在你的代码中,你进行了冒泡排序,这个过程本身没有问题,因为你正确地限制了循环次数以避免访问数组边界之外的元素。然而,如果用户输入的字符串长度恰好为3(不包括终止符),则排序后的字符串仍然会是三个字符加一个终止符,这意味着你需要一个至少为5个元素的数组来安全地容纳4个字符的输入(3个可见字符加上终止符和一个额外的位置以防止溢出)。
当你使用过小的数组而输入的字符串长度达到或超过数组大小时,可能会导致内存越界、覆盖重要的内存区域,并可能在打印时遇到奇怪的行为,比如多打印出一个字符。这个额外的"2"可能是内存中紧接着你的arr
数组之后的值,由于内存被意外覆盖,导致'\0'
终止符不在预期的位置,所以for
循环继续执行并打印出了额外的字符。
为了避免这种情况,你应该增加数组的大小以容纳更长的字符串和终止符,或者使用scanf
来限制输入的字符数,如下所示:
#include <stdio.h>void main()
{char arr[4];scanf("%s",arr);printf("%s\n",arr);for(int i = 0 ; arr[i] != '\0' ; i++){printf("%c\n",arr[i]);}char temp;for(int i = 0;i < 3;i++){for(int j = 0;j < 3-i;j++){if(arr[j]>arr[j+1]){temp = arr[j];arr[j] = arr[j+1];arr[j+1] = temp;}}}for(int i = 0 ;arr[i] != '\0' ;i++){printf("%c\n",arr[i]);}
}