从文件中将数据读入结构数组

时间:2015-11-03 03:18:30

标签: c++ arrays parsing file-io

我有一个看起来像这样的输入文件

 1 0 3
 2 11 5
 3 15 1
 4 16 11

和一个看起来像这样的结构

struct numb {
int numb1;
int numb2;
int numb3;
}

我需要创建一个struct数组,以便数组的每个元素都包含所有三个数字。所以

numbArray[0].numb1 == 1
numbArray[0].numb2 == 0
numbArray[0].numb3 == 3
numbArray[1].numb1 == 2
numbArray[1].numb2 == 11

等等。我已经掌握了打开和关闭文件,查找文件中有多少行,以及从文件中读取单行,但我不知道如何从一行存储单个元素。

到目前为止,我的程序看起来像这样:

#include <iostream>
#include <fstream>
#include <string>

int main(int argc, char* argv[])
{
    ifstream inFile(argv[1]);
    int fileLength = 0;
    std::string line;
    while(std::getline(inFile, line))
    {
        ++fileLength;
    }
    struct numb {
    int numb1;
    int numb2;
    int numb3;
    }
    if(inFile.is_open())
    {
        for(unsigned i = 0; i <= fileLength; i++)
        {
            //What to do here?
        }
    }
}

3 个答案:

答案 0 :(得分:0)

当您没有输入的常规结构并且需要处理行之间的变化时,请使用/** * Provides basic right-to-left transitions. Saves and restores view state. * Uses {@link PathContext} to allow customized sub-containers. */ public class SimplePathContainer extends PathContainer { private static final String TAG = "SimplePathContainer"; private final PathContextFactory contextFactory; public SimplePathContainer(int tagKey, PathContextFactory contextFactory) { super(tagKey); this.contextFactory = contextFactory; } @Override protected void performTraversal(final ViewGroup containerView, Flow.Traversal traversal, final PathContainer.TraversalState traversalState, final Flow.Direction direction, final Flow.TraversalCallback callback) { final PathContext oldPathContext; final PathContext newPathContext; if(containerView.getChildCount() > 0) { Log.d(TAG, "Container View Child count was > 0, using view context of path [" + PathContext.get(containerView.getChildAt( 0).getContext()).path + "]"); oldPathContext = PathContext.get(containerView.getChildAt(0).getContext()); } else { Log.d(TAG, "Container View Child Count was == 0, using root context"); oldPathContext = PathContext.root(containerView.getContext()); } Log.d(TAG, "Previous Path [" + oldPathContext.path + "]"); final Path to = traversalState.toPath(); Log.d(TAG, "New Path [" + to + "]"); View newView; newPathContext = PathContext.create(oldPathContext, to, contextFactory); int layout = ((BasePath) to).getLayout(); //removed annotation newView = LayoutInflater.from(newPathContext.getApplicationContext()) //fixed first path error .cloneInContext(newPathContext) .inflate(layout, containerView, false); View fromView = null; if(traversalState.fromPath() != null) { fromView = containerView.getChildAt(0); traversalState.saveViewState(fromView); } traversalState.restoreViewState(newView); if(fromView == null || direction == REPLACE) { containerView.removeAllViews(); containerView.addView(newView); oldPathContext.destroyNotIn(newPathContext, contextFactory); callback.onTraversalCompleted(); } else { final View finalFromView = fromView; if(direction == Flow.Direction.BACKWARD) { containerView.removeView(fromView); containerView.addView(newView); containerView.addView(finalFromView); } else { containerView.addView(newView); } ViewUtils.waitForMeasure(newView, new ViewUtils.OnMeasuredCallback() { @Override public void onMeasured(View view, int width, int height) { runAnimation(containerView, finalFromView, view, direction, new Flow.TraversalCallback() { @Override public void onTraversalCompleted() { containerView.removeView(finalFromView); oldPathContext.destroyNotIn(newPathContext, contextFactory); callback.onTraversalCompleted(); } }, (BasePath) Path.get(oldPathContext), (BasePath) to); } }); } } private void runAnimation(final ViewGroup container, final View from, final View to, Flow.Direction direction, final Flow.TraversalCallback callback, BasePath fromPath, BasePath toPath) { Animator animator = createSegue(from, to, direction); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { container.removeView(from); callback.onTraversalCompleted(); } }); animator.start(); } private Animator createSegue(View from, View to, Flow.Direction direction) { boolean backward = direction == Flow.Direction.BACKWARD; int fromTranslation = backward ? from.getWidth() : -from.getWidth(); int toTranslation = backward ? -to.getWidth() : to.getWidth(); AnimatorSet set = new AnimatorSet(); set.play(ObjectAnimator.ofFloat(from, View.TRANSLATION_X, fromTranslation)); set.play(ObjectAnimator.ofFloat(to, View.TRANSLATION_X, toTranslation, 0)); return set; } } 。当您的输入文件具有常规结构时(在这种情况下,每行总有三个值),那么只需直接使用流提取操作符:

getline

Express your ideas directly in code尽可能多。

注意我已经编写了代码,假设文件格式正确。如果每行的值太多或太少,则上述代码将会混淆。但是,最好对simplest thing that could possibly work进行编码,并在需要时担心复杂性。在您的示例中,您声明输入文件格式正确,因此无需过度复杂化。

答案 1 :(得分:0)

我建议使用std::stringstream

#include <iostream>
#include <sstream>
#include <string>
#include <stdio.h>
#include <vector>

struct numb {
  int numb1;
  int numb2;
  int numb3;
};

void populate(std::vector<numb>& my_numbs, std::string line) {
   std::stringstream ss(line);
   numb my_numb;
   ss >> my_numb.numb1 >> my_numb.numb2 >> my_numb.numb3;
   my_numbs.push_back(my_numb);
}

void output(const numb my_numbs) {
    printf("%d %d %d\n", my_numbs.numb1, my_numbs.numb2, my_numbs.numb3);
}

int main(int argc, char* argv[]) {
  ifstream inFile(argv[1]);
  std::string line;
  std::vector<numb> my_vect;
  while(std::getline(inFile, line)) {
    populate(my_vect, line);
  }

  for(size_t i = 0; i < my_vect.size(); ++i) {
    std::cout << "my_vect[" << i << "]:";
    output(my_vect[i]);
  }

  return 0;
}

std::stringstream允许您解析std::string中的数据类型,您只需要解析3 int s,您可以将其与结构一起使用。然后将结构推入向量中。

这是从stdin获取输入的工作{{3}。

答案 2 :(得分:-1)

您应该能够做到这样的事情:

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
    ifstream inFile(argv[1]);
    int fileLength = 0;
    std::string line;
    struct numb {
        int numb1;
        int numb2;
        int numb3;
    };
    vector<vector<int>> sets;
    int n1, n2, n3;
    while (std::cin >> n1)
    {
        cin >> n2;
        cin >> n3;
        vector<int> vec;
        vec.push_back(n1);
        vec.push_back(n2);
        vec.push_back(n3);
        sets.push_back(vec);
    }

    numb * numbSet = new numb[sets.size()];

    //Since the vectors data is continuous in memory just as the array of structs are
    //you can just copy the data directly
    for (int i = 0; i < sets.size(); i++)
    {
        std::memcpy(&numbSet[i], &sets[i][0], sizeof(numb));
    }
}