仅当声明了伪字符数组[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对我来说是这样的,为什么现在没有。谢谢你的全面回答。@aron9forever
fgets
也添加了一个空终止符。这不是问题。问题是手动生成字符串(
temp
,在本例中)没有手动添加空终止符。吹毛求疵:他没有添加空终止符的事实意味着
temp
不是字符串,这就是
atoi()
失败的原因。每个字符串都是
char[]
,但不是每个
char[]
都是字符串。-)添加0确实解决了问题。然而,我一直认为任何数组的最后一个单元格都包含终止符,因此它不可用。这就引出了最后一个问题,C++也会发生这种情况吗?我写了很多学校作业层程序,我总是假设在n个大小的数组的第n个单元格上,存在0。我使用过专门寻找0停止执行的代码。但所有这些都是C++的。