从文本文件输入到char *数组[9]

时间:2017-02-09 19:24:38

标签: c++ arrays pointers dynamic-arrays c-strings

The error message

我有一个包含9个单词的文件,我必须将每个单词存储到9个指针的char数组中,但我不断收到错误消息。我不能用矢量!

#include <iostream>
#include <fstream>


using namespace std;


int main()
{
   char *words[9];
   ifstream inStream;
   inStream.open("sentence.txt");
   if (inStream.fail())
   {
       cout << "Input file opening failed.\n";
       exit(1);
   }

   for ( int i = 0; i < 10; i++)
   {
       inStream >> words[i];
   }

       inStream.close();

   return 0;
}

3 个答案:

答案 0 :(得分:2)

声明

char *words[9];

声明一个原始指针数组。此数组未初始化,因此指针具有不确定的值。使用它们中的任何一个都是Undefined Behavior。

相反,你想要

vector<string> words;

其中vector来自std::vector标头<vector>,而string来自std::string标头<string>

使用push_back成员函数将字符串添加到向量的末尾。

此外,您需要将close调用移出循环。否则它将在第一次迭代中关闭文件。

这种方法提供了代码(不包括袖口,免责声明......)

#include <fstream>
#include <iostream>
#include <vector>
#include <string>
using namespace std;

int main()
{
   vector<string> words;
   ifstream inStream;
   inStream.open("sentence.txt");

   for ( int i = 0; i < 10; i++)
   {
       string word;
       if( inStream >> word )
          words.push_back( word );
   }
   inStream.close();
}

如果你不能使用std::stringstd::vector那么你需要初始化指针数组,并确保你没有读取更多的缓冲区而不是有空间。

这里的主要问题是>>对于读取由指针给出的原始数组是不安全的。它不知道该数组有多大。它很容易导致缓冲区溢出,带来可怕的后果。

所以这有点复杂,但它看起来像这样:

#include <ctype.h>          // isspace
#include <fstream>
#include <iostream>
#include <locale.h>         // setlocale, LC_ALL
#include <stdlib.h>         // EXIT_FAILURE
using namespace std;

void fail( char const* const message )
{
    cerr << "! " << message << "\n";
    exit( EXIT_FAILURE );
}

void readWordFrom( istream& stream, char* const p_buffer, int const buffer_size )
{
    int charCode;

    // Skip whitespace:
    while( (charCode = stream.get()) != EOF and isspace( charCode ) ) {}

    int n_read = 0;
    char* p = p_buffer;
    while( n_read < buffer_size - 1 and charCode != EOF and not isspace( charCode ) )
    {
        *p = charCode;  ++p;
        ++n_read;
        charCode = stream.get();
    }
    *p = '\0';      // Terminating null-byte.

    if( charCode != EOF )
    {
        stream.putback( charCode );
        if( not isspace( charCode ) )
        {
            assert( n_read == buffer_size - 1 );    // We exceeded buffer size.
            stream.setstate( ios::failbit );
        }
    }
}

int main()
{
    static int const n_words            = 9;
    static int const max_word_length    = 80;
    static int const buffer_size        = max_word_length + 1;  // For end byte.

    char *words[n_words];
    for( auto& p_word : words ) { p_word = new char[buffer_size]; }

    ifstream inStream{ "sentence.txt" };
    if( inStream.fail() ) { fail( "Input file opening failed." ); }

    setlocale( LC_ALL, "" );            // Pedantically necessary for `isspace`.
    for( auto const p_word : words )
    {
        readWordFrom( inStream, p_word, buffer_size );
        if( inStream.fail() ) { fail( "Reading a word failed." ); }
    }

    for( auto const p_word : words ) { cout << p_word << "\n"; }

    for( auto const p_word : words ) { delete[] p_word; }
}

答案 1 :(得分:1)

永远不会为保存在数组中的char*指针分配任何内存。

编写c ++代码的惯用方法是:

#include <iostream>
#include <fstream>
#include <vector>

int main() {
   std::vector<std::string> words(9);
   std::ifstream inStream;
   inStream.open("sentence.txt");

   for ( int i = 0; inStream && i < 9; i++) {
       inStream >> words[i];
   }
}

inStream.close()不是必需的,甚至在循环内部也是错误的。变量超出范围后,std::istream将自动关闭。

答案 2 :(得分:1)

您的代码存在一些问题。

char * words [9]; 这为9个指针分配空间,而不是9个字符串。由于你不知道字符串有多大,你有两个选择。您可以“猜测”您需要多少并相应地限制输入,或者您可以使用动态内存分配(malloc或new)来创建存储字符串所需的空间。动态记忆将是我的选择。

for(int i = 0; i&lt; 10; i ++) 该循环将在单词[0]到单词[9]上执行。但是,没有单词[9](这将是第十个单词)所以你将覆盖你没有分配的内存

inStream&gt;&gt;字[I]; 这会将您的输入流发送到您不“拥有”的内存。在从输入流中捕获它们之前,您需要为要生存的单词分配空间。要正确执行此操作,您需要知道每个单词需要多少空间才能分配它。

你可以尝试这样的事情:

int main()
{
    char *words[9];
    char tempInput[256]; // space to capture the input, up to a maximum size of 256 chars
    ifstream inStream;
    inStream.open("sentence.txt");
    if (inStream.fail())
    {
        cout << "Input file opening failed.\n";
        exit(1);
    }

    for ( int i = 0; i < 9; i++)
    {
        //Clear the input buffer
        memset(tempInput, 0, 256);

        //Capture the next word
        inStream >> tempInput;

        //allocate space to save the word
        words[i] = new char(strlen(tempInput));

        //Copy the word to its final location
        strcpy(words[i], tempInput)
    }

    inStream.close();

    return 0;
}