仅当声明了伪字符数组[C]时,程序才起作用
如果仅当声明了伪字符数组[C]时,程序才起作用,c,C,如果char finalstr[2048],则以下代码将正确打印到文件中是声明的,但是如果我删除它(因为它没有在任何地方使用),程序会打印垃圾ascii。这让我相信这与记忆有关,但我没有任何线索 #include <stdio.h> #include <stdlib.h> int main() { FILE *fp; FILE *fp2; char str[2048]; char finalstr[2048]; fp = fop
char finalstr[2048],则以下代码将正确打印到文件中
是声明的,但是如果我删除它(因为它没有在任何地方使用),程序会打印垃圾ascii。这让我相信这与记忆有关,但我没有任何线索
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp;
FILE *fp2;
char str[2048];
char finalstr[2048];
fp = fopen("f_in.txt", "r");
fp2 = fopen("f_out.txt", "w");
while(fgets(str,2047,fp))//read line by line until end of file
{
int i;
for(i=0;i<=strlen(str);i++)//go trough the string cell by cell
{
if(str[i]>47 && str[i]<58 && str[i+1]>47 && str[i+1]<58)//from 0 to 9
{
char temp[2];//to hold temporary two digit string number
temp[0]=str[i];
i++;
temp[1]=str[i];
if(atoi(temp)<27)//if it's an upper case letter
fprintf(fp2,"%c",atoi(temp)+64);
else//if it's lowercase, skip the special characters between Z and a
fprintf(fp2,"%c",atoi(temp)+70);
}
else fprintf(fp2,"%c",str[i]);
}
}
fclose(fp);
fclose(fp2);
}
如果声明了finalstr[]
,则输出
This is a wonderful hex number: ffabcd. Isn' t it?
Another beautiful number I see is abcdefYXWVUTSRQP
Trust me. I know a lot!
如果未声明finalstr[]
,则输出
?99? 9? 9 ?9999?9?9 99? 9?999?: ffabcd. ??9' ? 9??
((((.(( (((((.((. ((.((( ( ((( .( abcdefYXWVUTSRQP
øòòøò øò. ø òòòò ø òòò!
我注意到第一个if()
语句可能会导致溢出,但是替换atoi(temp)
会导致未定义的行为。atoi
函数需要一个指向以null结尾的字符串的指针作为参数,但是您提供了一个指向两个字符的指针,但没有终止符
atoi
函数将读取数组的末尾。您的虚拟数组会影响这一点,因为它会更改temp
数组之后存在的垃圾
顺便说一句,您可以使用(str[i]-“0”)*10+(str[i+1]-“0”)
而不是atoi
atoi(temp)
导致未定义的行为。atoi
函数需要一个指向以null结尾的字符串的指针作为参数,但是您提供了一个指向两个字符的指针,但没有终止符
atoi
函数将读取数组的末尾。您的虚拟数组会影响这一点,因为它会更改temp
数组之后存在的垃圾
顺便说一句,您可以使用(str[i]-“0”)*10+(str[i+1]-“0”)
而不是atoi
据我所知,问题是程序可能会通过
fgets(str,2047,fp)
这意味着
i <= strlen(str)
i据我所知,问题是程序可能会在
fgets(str,2047,fp)
这意味着
i <= strlen(str)
i主要问题是使用的临时字符串。它不够长,无法存储空终止字符,因此您有一个未终止的字符串
将数组设为3字节长并添加终止符:
char temp[3];//to hold temporary two digit string number
temp[0]=str[i];
i++;
temp[1]=str[i];
temp[2]=0;
此外,在for
循环中,您的搜索距离数组末端太远。使用主要问题是使用的临时字符串。它不够长,无法存储空终止字符,因此您有一个未终止的字符串
将数组设为3字节长并添加终止符:
char temp[3];//to hold temporary two digit string number
temp[0]=str[i];
i++;
temp[1]=str[i];
temp[2]=0;
此外,在for
循环中,您的搜索距离数组末端太远。Use只读了第一句话,但我愿意打赌缓冲区溢出,如果您在那里额外分配了2048字节的未使用内存,那么这恰好是非致命的。首先,请停止使用,改用适当的字符文字,并使用。。然后,对于一个导致未定义行为的大问题,atoi
函数需要一个字符串,而所有的C字符串都需要终止,而您的字符串不是。您对一个非零终止的temp[2]
调用atoi(),但我愿意打赌缓冲区溢出是非致命的,如果你有额外的2048字节未使用的内存分配在那里。首先,请停止使用,使用适当的字符文字代替,并适用于使用。。然后,对于一个导致未定义行为的大问题,atoi
函数需要一个字符串,而所有C字符串都需要终止,而您的字符串不是
不是以零结尾的。fgets
添加NULL
终止符。fgets
始终为NULL终止输出(除非它返回NULL,但OP检查是否为NULL)fgets
添加NULL
终止符。fgets
始终为NULL终止输出(除非它返回NULL,但OP会检查该值)添加0确实解决了这个问题。但是我一直认为任何数组的最后一个单元都包含一个终结符,因此它不能使用。这就引出了最后一个问题,这是否也会发生在C++中?我写了很多的学校作业层程序,我一直认为在n个大小的数组的第n个单元中,有0个。我使用了专门寻找0的代码来停止执行。但是所有这些都是C++的。@ ARN9:是的,C和C++是一样的。除非你专门把它放在那里,否则数组的最后一个单元将不包含零。使用一个函数,比如<代码> StrucP或<代码> STRCAT/CODE>将添加一个,但在这种情况下,你不会这样做。在您的情况下,数组char temp[2]
是一个包含索引0
和1
的两个元素数组。您可以填充这两个元素,但是内存中的下一个字节不是该数组的一部分,因此它可以包含任何内容。我已经弄清楚了发生了什么。显然,std::cin>
在读取输入后添加了一个空终止符。这解释了为什么它总是在ut对我来说是这样的,为什么现在没有。谢谢你的全面回答。@aron9foreverfgets
也添加了一个空终止符。这不是问题。问题是手动生成字符串(temp
,在本例中)没有手动添加空终止符。吹毛求疵:他没有添加空终止符的事实意味着temp
不是字符串,这就是atoi()
失败的原因。每个字符串都是char[]
,但不是每个char[]
都是字符串。-)添加0确实解决了问题。然而,我一直认为任何数组的最后一个单元格都包含终止符,因此它不可用。这就引出了最后一个问题,C++也会发生这种情况吗?我写了很多学校作业层程序,我总是假设在n个大小的数组的第n个单元格上,存在0。我使用过专门寻找0停止执行的代码。但所有这些都是C++的。