该程序旨在从输入的ISBN代码中删除'-,例如"978-123456-789〃;被输入;978123456789";输出。相反,我得到的是";978123456789978123456789"-它正在打印两次。有人能向我解释一下原因吗?感谢
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
int main(void)
{
char ISBN[16], arrayClean[12];
int i,j,k,a;
printf("Enter your ISBN: ");
scanf("%s",&ISBN);
for(i=0; i<=13; i++)
{
a = ISBN[i] - 48;
if(a==-3)
{
for(j=i;j<=13;j++)
{
k++;
ISBN[j]=ISBN[j+1];
}
k=0;
i=0;
}
}
for(i=0; i<=11; i++)
arrayClean[i]=ISBN[i];
printf("%s",arrayClean);
return 0;
}
一个数字中似乎有12个字符(不包括虚线.14)。
因此,循环不能处理输出的字符0到11,以及输入的字符0至13。这就忘记了终端"\0",它也需要在输出中的位置12。
(如果你100%确定会有12个字符,那么你可以通过在打印前在末尾添加arrayClean[12]=0
来解决这个问题。但这不是一个好主意。因为这将取决于用户键入的内容)。
此外,即使是您的数组的声明";arrayClean";不考虑对终端CCD_ 2的需要。您需要13个字节来容纳一个12个字符的字符串。
其他备注:
你使用scanf("%s", &ISBN);
是危险的。
首先,它应该是scanf("%s", ISBN);
。您需要传递scanf
的是存储其读取内容的地址。当您读取单个int x;
时,实际上,您应该使用scanf("%d", &x);
,让scanf将结果存储在存储x的地址。但是对于字符串来说,ISBN
已经是一个地址(字符ISBN[0]
、ISBN[1]
…的地址)。所以你不应该传递ISBN的地址。
这里需要注意的是,由于ISBN不是一个变量(它是一个数组,是一个常量指针),因此在C中,&ISBN
和ISBN
在这个上下文中是相同的。所以,它碰巧工作是偶然的。
但是,如果ISBN是一个变量(例如,分配了malloc
的char *
),那么这种使用将导致内存错误。因此,您应该养成不将&ISBN
传递给scanf
而将ISBN
传递的习惯。
同一行的另一个问题是:扫描时,你不能相信用户会键入你期望的确切字节数。这里,如果用户键入16个或更多字节,这些字节将被写入ISBN
的16个字节之后的任何内存。这将导致非常严重的问题。即使是安全性问题,如果用户故意这样做是为了覆盖某些体系结构上的其他变量甚至代码。
所以,经验法则:永远不要scanf("%s", ...)
。始终限制scanf可以读取的字节数。例如CCD_ 20。
终止字符串不是null。您只将ISBN中的12个字符复制到arrayClean中。您需要在' '
1的末尾添加一个null终止符。可以通过在for循环之后添加arrayClean[12] = ' ';
来完成此操作。
char ISBN[16], arrayClean[12];
int i, j, k, a;
printf("Enter your ISBN: ");
scanf("%s", &ISBN);
for (i = 0; i <= 13; i++)
{
a = ISBN[i] - 48;
if (a == -3)
{
for (j = i; j <= 13; j++)
{
k++;
ISBN[j] = ISBN[j + 1];
}
k = 0;
i = 0;
}
}
for (i = 0; i <= 11; i++)
arrayClean[i] = ISBN[i];
arrayClean[12] = ' ';
printf("%s", arrayClean);