【问题标题】:File input containing string and integer包含字符串和整数的文件输入
【发布时间】:2014-12-24 08:03:13
【问题描述】:

我有一个文件,其内容如下所示:

Aadam
50
Aadam
0
Aad
0123
Waleed
12345

现在,我需要将第一行存储在字符串数组中,将第二行存储到整数数组中。 这是我写的源代码......

ifstream infile ("File.txt");
string name [20];
int score [20};
for (int i = 0; !infile.eof(); i++)
            {
                getline(infile, name[i]);
                infile >> scores[i];
            }

好吧,程序成功读取了第一行,但之后它什么也不做。 我首先尝试了另一种方法,首先将整数存储为临时字符串,然后使用“stoi”将该字符串转换为整数,这就像一个魅力。像这样:

for (int i = 0; !infile.eof(); i++)
            {
                getline(infile, name[i]);
                string temp;
                getline(infile, temp);
                scores[i] = stoi(temp);
            }

但问题是我不能使用 stoi。它在我的计算机上运行良好,但我必须将源代码提供给可能没有支持 C++11 的编译器的老师。这对我来说可能是个问题。 所以我需要另一种方式来从文件中输入数据。 所以,如果你知道如何做到这一点,请告诉我方法。

【问题讨论】:

标签: c++ arrays file file-io


【解决方案1】:

用“atoi”代替“stoi”:

scores[i] = atoi(temp.c_str());

http://en.cppreference.com/w/cpp/string/byte/atoi

它早在 C++11 之前就已经存在了。

【讨论】:

  • 那应该如何帮助解决问题?
【解决方案2】:

如果你不能使用 stoi,你可以使用字符串流来代替。

std::ifstream infile ("File.txt");
std::string name[20];
int score[20];
for (int i = 0; !infile.eof(); i++){
    getline(infile,name[i]);
    std::string temp;
    getline(infile,temp);

    std::stringstream s; 
    s << temp; 
    int integertemp; 
    s >> integertemp; // This will convert string to integer, just like how it is with iostreams.
    score[i] = integertemp;
}

【讨论】:

    【解决方案3】:

    问题的要点是,如果输入包含:

    Aadam\n
    50\n
    

    你做到了:

      getline(infile, name[i]);    // name[i] contains "Hello", \n consumed
      infile >> scores[i];         // scores[i] contains 50
    

    那么输入仍然包含:

    \n
    

    那是在50 之后。带有int&gt;&gt; 运算符不使用任何尾随换行符或它提取的数字之后的其他字符。

    然后在下一次循环中,输入流包含:

    \n
    Aadam\n
    0\n
    

    你做到了:

      getline(infile, name[i]);    // name[i] contains "", \n consumed
      infile >> scores[i];         // input failure
    

    由于Aadam(第二个)无法解析为int&gt;&gt; 运算符将infile 置于失败状态。您的代码永远不会清除失败状态,也不会对其进行检查,因此所有后续操作都会失败并且您的代码会进入无限循环。

    其他问题是using eof() is a bad idea,并且(如果读数已修复)如果您的文件中有超过 20 对项目,则会出现缓冲区溢出。


    要解决 I/O 问题,你可以这样写:

    for (int i = 0; i < 20; ++i)
    {
        getline(infile , name[i]);
        infile >> scores[i];
        infile.ignore(SIZE_MAX, '\n');
    
        if ( !infile )
            break;
    }
    

    这里的ignore行表示读完数字后,会消耗该行的剩余部分。

    当循环结束时,i 将包含成功读取的对数。如果输入失败,break 的条件很重要。

    【讨论】:

      【解决方案4】:

      问题出在getline使用&gt;&gt;之后。

      要解决它,您可以添加此方法:

      istream& eatwhites(istream& stream)
      {
          // to define white spaces manually:
          //const string skip=" \t\r\n";
          //while(string::npos != skip.find(stream.peek())){
          //   stream.ignore();
          //}
      
          //or just use isspace:
          while(isspace(stream.peek())){
              stream.ignore();
          }
      
          return stream;
      }
      

      并像这样写每个getline

      string name;
      getline( eatwhites(infile), name); 
      

      还有cin:

      string name;
      getline( eatwhites(cin), name); 
      

      【讨论】:

      • 他也想要分数,而不仅仅是名字。
      • 问题出在getline使用&gt;&gt;后。这解决了问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-20
      • 1970-01-01
      • 1970-01-01
      • 2018-05-01
      • 2018-02-20
      相关资源
      最近更新 更多