动态将fscanf放入数组

时间:2018-12-10 17:11:06

标签: c file input scanf

我正在尝试将一些文本放入数组的结构部分中,该数组是一部分文本。

例如,我的结构是:

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.stage.Stage;

public class TableViewDemo2 extends Application
{

    double sceneX, sceneY;

    Circle circle = new Circle(15, Color.RED);
    Circle circle2 = new Circle(15, Color.BLUE);
    Line line = new Line();

    private Line connectLines(Line line, Circle startNode, Circle endNode)
    {
        line.startXProperty().bind(startNode.centerXProperty());
        line.startYProperty().bind(startNode.centerYProperty());
        line.endXProperty().bind(endNode.centerXProperty());
        line.endYProperty().bind(endNode.centerYProperty());

        return line;
    }
    //mouse pressed event
    EventHandler<MouseEvent> mousePressed = new EventHandler<MouseEvent>()
    {
        @Override
        public void handle(MouseEvent e)
        {
            System.out.println("pressed");

            sceneX = e.getSceneX();
            sceneY = e.getSceneY();

            Circle tempCircle = ((Circle) e.getSource());
            tempCircle.toFront();
        }
    };

    //mouse dragged event
    EventHandler<MouseEvent> mouseDragged = new EventHandler<MouseEvent>()
    {
        @Override
        public void handle(MouseEvent e)
        {
            System.out.println(Math.hypot(line.getBoundsInLocal().getWidth(), line.getBoundsInLocal().getHeight()));

            System.out.println("dragged");
            double offSetX = e.getSceneX() - sceneX;
            double offSetY = e.getSceneY() - sceneY;

            Circle tempCircle = ((Circle) (e.getSource()));
            tempCircle.setCenterX(tempCircle.getCenterX() + offSetX);
            tempCircle.setCenterY(tempCircle.getCenterY() + offSetY);

            if (Math.hypot(line.getBoundsInLocal().getWidth(), line.getBoundsInLocal().getHeight()) >= 100) {
                tempCircle.setCenterX(tempCircle.getCenterX() - offSetX);
                tempCircle.setCenterY(tempCircle.getCenterY() - offSetY);
            }

            sceneX = e.getSceneX();
            sceneY = e.getSceneY();
        }
    };


    @Override
    public void start(Stage stage)
    {

        circle.setOnMouseDragged(mouseDragged);
        circle2.setOnMouseDragged(mouseDragged);

        Line returnLine = connectLines(line, circle, circle2);

        StackPane root = new StackPane(new Pane(circle, circle2, returnLine));

        stage.setTitle("TableView (o7planning.org)");

        Scene scene = new Scene(root, 450, 300);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args)
    {
        launch(args);
    }
}

然后我将输入诸如:

struct animal
{
    char animal_Type[11];
    int age;
    int numberOfLegs;
    int walksPerDay;
    char favoriteFood[];
};

我有一个可行的解决方案,可以将每天最多的价值放入结构中,但是我希望能够将食品放入“最喜欢的食品”中。我为此有一个动态数组,但是我不确定如何将剩余的文本读到收藏夹食物数组中。

使用的代码是:

dog,2,4,2,biscuits,wet
cat,5,4,0,biscuits,wet,dry,whiskers
bird,1,2,0,birdseed,biscuits,bread,oats,worms,insects,crackers

我该怎么做?

1 个答案:

答案 0 :(得分:0)

首先,您的struct与您在评论中所说的不符。

char favoriteFood[];

上面是char的数组,因此不可能保存喜欢的食物的列表,除非它是一个字符串。而且由于数组的大小未指定,因此您将无法像以前一样填充它。相反,您真正想要的是

char **favoriteFood;
unsigned int favoriteFoodSize;

这将使您创建一个扩展的字符串列表以适合您需要容纳的任何数据。

对于读入而言,最好的方法是使用fgets读取整行,然后使用strtok之类的东西将分隔符分隔为一行。首先定义一个非常大的字符串以容纳整行,并定义一个char *来容纳每个字段。

char buffer[1024];
char *token;

然后进入主循环将是这样的:

while(fgets(buffer,1024,fp)) {
    token=strtok(buffer,",");
    strcpy(beasts[i].animal_Type,token);

    token=strtok(NULL,",");
    beasts[i].age = atoi(token);

    /* etc... */
}

您需要检查token是否曾经NULL,以应对出现短线的可能性并相应地进行处理。还要确保复制到animal_Type的字符串不超过10个字符...或者将其设置为char *,这样您就可以具有任意大小的字符串。

对于favoriteFood,您需要使用realloc来增加它的大小,以容纳所添加的每种新食物,并不断遍历字符串,直到令牌用完为止。

token=strtok(NULL,",");
if(token) {
    beasts[i].favoriteFood=malloc(sizeof(char *));
    beasts[i].favoriteFood[0]=strdup(token); // Need to index using 0 as favoriteFoodSize won't have a value yet
    beasts[i].favoriteFoodSize=1;

    token=strtok(NULL,",");
    while(token) {
        beasts[i].favoriteFood=realloc(beasts[i].favoriteFood,(beasts[i].favoriteFoodSize+1)*sizeof(char *));
        beasts[i].favoriteFood[beasts[i].favoriteFoodSize]=strdup(token);
        beasts[i].favoriteFoodSize++;

        token=strtok(NULL,",");
    }
}

最后一个食物中将有一个\n,因为fgets会将其保留在读取的缓冲区中,因此您可以用它来告诉您是否已完成所有食物的处理(您还将需要将其从最近的食物中删除)。或者,如果您没有它,您会知道该行较长,您需要阅读更多内容。但是根据您的示例数据,这似乎不太可能。

由于要进行大量的内存分配,因此应确保检查返回的值,以确保没有用完内存。