将数据从文件放入字符数组不会在最后数据处停止

时间:2016-02-16 02:21:47

标签: c++

我在使用课程时生气,并且正在努力使用它们。我遇到了一个问题,我试图使用一个简单的程序从一个包含简单数字的文件中检索数据(在这种情况下,#34; 1234")。

#include <iostream>
#include <fstream>

class hold
{
public:
    void enter();
    hold();
private:
    char x[50];
}; 

 hold::hold()
{
    x[50] = NULL;
}

void hold::enter()
{
    std::ifstream inFile;
    inFile.open("num.txt");
    int pos = 0;
    while(inFile.good())
    {
        inFile >> x[pos];
        pos++;
    }

    std::cout << "strlen(x) = " << strlen(x) << std::endl;
    for(int i = 0; i < strlen(x); i++)
    {
        std::cout << x[i] << " ";
    }
    std::cout << std::endl;
}

int main()
{
    hold h;
    h.enter();
    system("pause");

    return 0;
}

输出结果为:

strlen(x) = 50;
1 2 3 4 (following a bunch of signs I do not know how to print).

我已经差不多一年了,因为我一直在练习课程,而且我不记得在课堂上使用过字符数组。任何人都可以告诉我,在&#34; 4&#34;之后,我弄乱了这个文件并没有终止。如果&#34; x [pos] ==&#39; \ 0&#39;我已尝试使用if语句打破while循环,但它也没有工作。

2 个答案:

答案 0 :(得分:1)

您没有终止字符串并且您有未定义的行为,因为strlen正在击中从未初始化的数组元素。试试这个:

while( pos < 49 && inFile >> x[pos] )
{
    pos++;
}
x[pos] = '\0';

请注意,循环后的pos现在与strlen(x)返回的内容相同。

如果您不需要以空字符结尾的字符串,那么只需使用pos而不是strlen(x)而不终止,但在这种情况下,您将需要避免使用任何依赖的字符串函数以null结尾的字符串。

您的构造函数中也存在堆栈粉碎问题(未定义的行为):

hold::hold()
{
    x[50] = NULL;
}

这不行。您不能修改超出数组末尾的内存。如果你想把它归零,你可以做到

memset( x, 0, sizeof(x) );

或者在C ++ 11中:

hold::hold()
    : x{ 0 }
{
}

答案 1 :(得分:1)

strlen期望以null结尾的字符串。由于您的x 以空值终止,因此将其传递给strlenundefined behavior

幸运的是,您无需致电strlen,因为您的变量pos会计算x内的有效条目数:

std::cout << "length of my string = " << pos << std::endl;
for(int i = 0; i < pos ; i++) {
    std::cout << x[i] << " ";
}
  

有没有办法解释pos-1以外的额外字符?

是的,更好的方法是仅在您知道字符输入成功时才增加pos

while(inFile >> x[pos]) {
    pos++;
}