为什么char [1]从我的输入文件中读取整个单词?

时间:2014-05-15 21:27:39

标签: c++ arrays file

这是我到目前为止所做的:我想从C ++中读取文件中的单词,并且我只允许使用cstring库。这是我的一段代码

#include <cstring>
#include <fstream>
#include <stdio.h>

using namespace std;

int main(){

    ifstream file;
    char word[1];


    file.open("p.txt");



    while (!file.eof()){

        file >> word;
        cout << word << endl;

    }
    system("pause");
    return 0;
}

工作正常,一次只读一个字。但我不明白这是如何工作的。 任何大小的char数组怎么可能是char字[1]或char字[50]一次只读一个字而忽略空格。

此外,我想将这些单词存储在动态数组中。我怎样才能做到这一点?任何指导都会受到赞赏吗?

7 个答案:

答案 0 :(得分:7)

您的代码有未定义的行为。 operator >>只是覆盖数组之外的内存。

考虑到您所包含的标题<stdio.h>未在程序中使用。另一方面,您需要包含声明函数<cstdlib>的标头system

至于你的第二个问题,你应该使用例如标准容器std::vector<std::string>

例如

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstdlib>

int main()
{
    std::ifstream file("p.txt");
    std::string s;
    std::vector<std::string> v;
    v.reserve( 100 );



    while ( file >> s ) v.push_back( s );

    std::system( "pause" );

    return 0;
}

或者您可以简单地将矢量定义为

std::vector<std::string> v( ( std::istream_iterator<std::string>( file ) ),
                            std::istream_iterator<std::string>() );

如果您要包含标题<iterator>

例如

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <iterator>
#include <cstdlib>

int main()
{
    std::ifstream file("p.txt");
    std::vector<std::string> v( ( std::istream_iterator<std::string>( file ) ),
                                std::istream_iterator<std::string>() );

    for ( const std::string &s : v ) std::cout << s << std::endl;

    std::system( "pause" );

    return 0;
}

答案 1 :(得分:4)

您的代码正在调用未定义的行为。它没有崩溃就是掷骰子,但它的执行并不是确定性的,因为这是 undefined 的本质。

加载具有空格分隔的单词文件的最简单方法(我发现)是:

std::ifstream inp("p.txt");
std::istream_iterator<std::string> inp_it(inp), inp_eof;
std::vector<std::string> strs(inp_it, inp_eof);

strs将每个以空格分隔的char序列包含为std::string的线性向量。使用std::string获取动态字符串内容,并且不要觉得在你给我们所有人之前的那些艰苦工作中利用地狱的一点点内疚:The Standard Library

答案 2 :(得分:1)

你正在使用C ++,所以你可以避免使用C语言。

std::string word;
std::vector<std::string> words;
std::fstream stream("wordlist");

// this assumes one word (or phrase, with spaces, etc) per line...
while (std::getline(stream, word))    
    words.push_back(word);

或每行以逗号分隔的多个单词(或短语,带空格等):

while (std::getline(stream, word, ','))    
    words.push_back(word);

或每行以空格分隔的多个单词:

while(stream >> word)
    words.push_back(word);

无需担心缓冲区大小或内存分配或类似内容。

答案 3 :(得分:1)

这很有效,因为你很幸运,而且你不会覆盖一些关键的记忆。您需要为char word数组分配足够的字节,比如char word[64]。并使用while(file>>word)作为EOF的测试。如果允许您使用push_back STL,则可以在循环中std::vector<string>将该字C++改为#include <algorithm> #include <iterator> #include <vector> #include <string> #include <fstream> #include <iostream> using namespace std; int main() { ifstream fin("./in.txt"); // input file vector<string> words; // store the words in a vector copy(istream_iterator<string>(fin),{}, back_inserter(words)); // insert the words for(auto &elem: words) cout << elem << endl; // display them }

如果您想要一个简单的类似C ++ 11 STL的解决方案,请使用此

vector<string> words(istream_iterator<string>(fin),{});

或者更紧凑地,直接从流迭代器构造容器,如

copy

并删除vector<string>语句。

如果您使用multiset<string>#include <set>)而改为<{p}} {/ 1}}

copy(istream_iterator<string>(fin),{}, back_inserter(words)); // insert the words

copy(istream_iterator<string>(fin),{}, inserter(words, words.begin())); // insert the words

你得到了命令。因此,在我看来,使用STL是最干净的方法。

答案 4 :(得分:1)

由于char *的{​​{1}}超载,您的代码失败了。

operator>>数组,无论大小,都会分解为类型char,其中值是数组开头的地址。

为了与C语言兼容,已经实现了重载char *以读取一个或多个字符,直到到达终止空白字符,或者流有错误。

如果您声明一个包含1个字符的数组并从包含&#34; California&#34;的文件中读取,则该函数将放置&#39; C&#39;进入数组的第一个位置继续将剩余的字符写入内存中的下一个位置(无论它们是什么数据类型)。这称为缓冲区溢出

更安全的方法是阅读operator>>(char *)或如果您只想要一个字符,请使用std::string变量。查看您最喜欢的char方法的C ++参考。在达到给定分隔符之前,读取过载。

答案 5 :(得分:1)

您只需要进行一些更改:

#include <cstring>
#include <fstream>
#include <stdio.h>
#include <string>
int main(){

    ifstream file;
    string word;    

    file.open("p.txt");    

    while (file >> word){
        cout << word << endl;    
    }

    system("pause");
    return 0;
}

答案 6 :(得分:0)

file>>char *

可以使用任何字符*并且您正在使用

file >> word;

它只是将工作变量视为char *但是你在某处遇到了一个segemntation错误,如果你的代码增长,你会看到一些东西在没有任何逻辑原因的情况下无效。 GDB调试器将向您显示seg错误