【问题标题】:reading file and split the line in c++读取文件并在c ++中拆分行
【发布时间】:2012-10-17 10:45:58
【问题描述】:

我有以下代码从 txt 文件中读取输入,如下所示

Paris,Juli,5,3,6 
Paris,John,24,2 
Canberra,John,4,3 
London,Mary,29,4,1,2

我的代码是将数据加载到地图中,然后我想打印地图内容以确保它已正确插入,我检查了 m 的值,因为它在分割线时使用。但是,在执行过程中,我将其视为 continue 0s,这意味着它永远不会进入 while 循环。我以前使用过这部分代码,它可以工作。我找不到错误的地方。

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

struct info {
       string Name;
       int places;// i will use the binary value to identfy the visited places example 29 is 100101 
             // this means he visited three places (London,LA,Rome)   
       vector<int> times; // will represent the visiting time,e.g. 1,2,5 means london 1 time, LA 
                   // twice and Rome five times 


       };
map<string,vector<info> > log;
map<string,vector<info> >::iterator i;
fstream out;
int main() {
    out.open("log.txt", std::ios::in | std::ios::out | std::ios::app);
            string line;
            char* pt;
            string temp[19];

    // for each line in the file 
    while (!out.eof())
    {
         getline(out,line);//read line from the file
         pt=strtok(&line[0],"," );//split the line
         int m=0;
         while (pt != NULL)
         {
         temp[m++] = pt; // save the line info to the array
         cout<<m<<"  ";
         pt = strtok (NULL, ",");
         }
         cout<<m<<"  "; // during the execution I get this as continues 0s which means it is never enter the while loop
         info tmp;
         // read the other data
         tmp.Name=temp[1];
         tmp.places=atoi(temp[2].c_str());
         for ( int i=3;i<=m;i++)
         { 
         tmp.times.push_back(atoi(temp[i].c_str()));
         }         
         // create a new object 
         log[temp[0]].push_back(tmp); 
         }

 vector<int>::iterator j; 
    for(i=log.begin();i!=log.end();i++) {
    cout<< "From "<< i->first<<" city people who travels: "<<endl; 
    for (size_t tt = 0; tt < (i->second).size(); tt++) {
    cout<< (i->second[tt]).Name<< " went to distnations "<< (i->second)[tt].places<<" \nwith the folloing number of visiting time "; 
    for (j=((i->second[tt]).times).begin();j!= ((i->second[tt]).times).end();j++) 
    cout<<*j<<" ";
     } 
    }  


          system("PAUSE");
          return 0;
          }

【问题讨论】:

  • 另见 this question 在 C++ 中拆分字符串。
  • strtok 采用 char* 但它采用“字符串”类型吗?我其实不知道。 cstring 包含在您的代码中吗? strtok 应该在那里。
  • 也许您的输入 txt 文件命名为 log.txt
  • @Md.TaufiqueHussain 相同的代码块与其他文件一起工作,我现在确切地知道该行中有多少元素。在这里,每行都有不同数量的元素,所以我无法确定每行中的元素。最小元素数为 3
  • 看这个question用c++20实现读取文件和分割字符串。

标签: c++ map split readfile


【解决方案1】:

这是一个错误

// for each line in the file 
while (!out.eof())
{
     getline(out,line);//read line from the file

应该是

// for each line in the file 
while (getline(out,line))
{

坦率地说,我发现这个错误重复的频率令人难以置信。 eof 不会做你认为它做的事。它测试 last 读取是否因为文件结束而失败。您正在使用它来尝试预测下一次读取是否会失败。它根本不是那样工作的。

这一行是错误的

pt=strtok(&line[0],"," );//split the line

strtok 适用于 C 字符串,不能保证它适用于 std::string

但这些都不是你真正的错误。我建议只用ios::in 打开文件。毕竟你只想从中读取。

【讨论】:

  • actullay 我想从文件中读取数据,然后将新数据附加到它。我以前在那种程序中使用过strtok,它可以工作。
  • 如果我按照你写的那样设置while条件,程序不会读取任何数据。
  • @user1749118 当然可以。但是你很幸运。不能保证它会一直有效。您使用的下一个编译器或您编写的下一个程序可能无法正常工作。你应该像 Nickolay 说的那样去做。
  • @user1749118 好的,删除 ios::app ,然后当您要追加时,查找文件末尾,甚至关闭文件并重新打开它。
【解决方案2】:

您的 fstream 不应在应用模式下打开。这将寻找文件到文件末尾。从中删除std::ios::app

【讨论】:

    【解决方案3】:

    您不能使用strtok 标记std::string。请改用getline

    std::string str("some,comma,separated,data");
    std::string token;
    while (getline(str, token, ',')) {
        cout << "Token: " << token << end;
    }
    

    在每次迭代中,token 包含来自 str 的下一个已解析标记。

    【讨论】:

      【解决方案4】:

      这是错误的temp[m++] = pt; // save the line info to the array

      切换到类似的东西,而不是“temp”

      std::vector<std::string> vTemp; 
      
      pt=strtok(&line[0],"," );//split the line       
      while (pt != NULL)
      {
      vTemp.push_back(pt); // save the line info to the array      
      pt = strtok (NULL, ",");
      }
      

      还可以考虑使用类似的方法进行拆分。

      std::vector<std::string> SplitString(const std::string &strInput, char cDelimiter)
      {
          std::vector<std::string> vRetValue;
      
          std::stringstream ss(strInput); 
          string strItem;
          while(std::getline(ss, strItem, cDelimiter))    
          {   
              // Skip Empty
              if(strItem.size()==0)       
                  continue;
      
              vRetValue.push_back(strItem);
          }
      
          return vRetValue;
      }
      

      【讨论】:

        【解决方案5】:

        @halfelf 非常适合我的简单错误,它可以工作,但现在问题是当我打印我得到的数据时

        From Paris  city people who travels:
        Juli went to distnations 5
        with the folloing number of visiting time 3 6 0 
        John went to distnations 24
        with the folloing number of visiting time 2 6 
        From Canberra  city people who travels:
        Johnwent to distnations 4
        with the folloing number of visiting time 3  6
        From London city people who travels:
        Mary went to distnations 29
        with the folloing number of visiting time 4 1 2 0
        

        这是不正确的,因为 6 被添加到来自堪培拉和巴黎的 John,而 0 被添加到 Juli 和 Mary。 关于我在哪里弄错的任何想法,它关于时间向量,似乎我需要重置每一行的值或在插入后清除内容。额外的 0 呢?

        【讨论】:

        • 解决它,只需从 for 循环中删除 = 符号 for ( int i=3;i&lt;=m;i++) .. 谢谢大家的帮助
        猜你喜欢
        • 1970-01-01
        • 2020-12-18
        • 2013-09-08
        • 2014-01-17
        • 1970-01-01
        • 2019-05-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多