在C ++的csv文件中搜索名称

时间:2019-07-06 18:03:04

标签: c++

我是一位年轻的程序员,正在尝试学习c ++。我有一个工作的csv.file。但是我想搜索分配给该名称的特定号码,然后显示我要查找的名称。我在这里有文件:

1,Bulbasaur,grass
2,Ivysaur, grass
3,Venusaur, grass
4,Charmander, fire
5,Charmeleon, fire
6,Charizard, fire
7,Squirtle, water
8,Wartortle, water
9,Blastoise, water

代码

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

int main()
{
    ifstream ip("pokedex.csv");

    string pokedexnum[9];
    string pokemonName[9];
    string pokemonType[9];
    cout<<"please enter a pokemon number:"<<" ";
    cin>>pokemonType[0];

    while (ip.good()){

        getline( ip, pokedexnum[0]);
        getline( ip, pokemonName[0]);
        getline( ip, pokemonType[0]);
    }

    cout<<"the pokemon that is:"<< " "<<pokedexnum[0]<< "is the pokemon called:"<< pokemonName[0];
    ifstream close("pokedex.csv");
    return 0;
}

运行时

please enter a pokemon number: 1
the pokemon that is: is the pokemon called:8,Wartortle, water

您能指出我做错了吗?

2 个答案:

答案 0 :(得分:1)

此代码中的问题:

  • 您未正确使用std::getline处理逗号分隔的数据。结果是每遍都消耗了输入文件中的三行 ;每行中没有三个值。
  • 您同时也没有正确使用ip.good()
  • 您将测试值保留在数组中,该值将在第一次迭代过程中被覆盖,因此将丢失。
  • 您忽略每次std::getline调用时潜在的IO故障。
  • 每次循环迭代都将覆盖阵列中的slot-0。
  • 未成年人,ifstream close("pokedex.csv");显然没有按照您的想法去做。这样只会在给定的文件名上创建另一个名为fstream的{​​{1}}对象。

稍后可能是暂时的,但在不久的将来很明显。

实际上,您不需要任何数组。您要做的只是读取行,似乎想针对CSV数据第一列的输入数测试输入数字,报告找到的行,然后结束该行。

这样做:

  1. 读取输入值进行搜索。
  2. 打开文件进行扫描。
  3. 一次枚举文件。
  4. 对于(3)中的每一行,请使用字符串流将其分成逗号分隔的值。
  5. 根据(1)的输入测试id值。如果相同,则报告结果并中断循环。完成了。

结果是这样的:

close

未经测试,但可以正常工作。

这时您是否要完全将项目存储在数组中,但这完全不必解决您似乎正在尝试的抽象问题,即找到匹配的行并从中报告名称-相同。如果您 still 想要将它们存储在数组中,建议您制作一个结构来做到这一点,例如:

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <cstdlib>

int main()
{
    std::cout<<"please enter a pokemon number: ";

    long num;
    if (std::cin >> num && num > 0)
    {
        std::ifstream ip("pokedex.csv");
        std::string line;
        while (std::getline(ip, line))
        {
            std::istringstream iss(line);
            std::string id, name, skill;

            if (std::getline(iss, id, ',') &&
                std::getline(iss, name, ',') &&
                std::getline(iss, skill))
            {
                char *endp = nullptr;
                long n = std::strtol(id.c_str(), &endp, 10);
                if (id.c_str() != endp && n == num)
                {
                    std::cout << "The pokemon that is: " << num << " is called: " << name << '\n';
                    break;
                }
            }
        }
    }
}

并且只有一个数组,而不是必须保持同步的三个任意数组。

答案 1 :(得分:0)

四个问题冲向我:

  1. 您将用户的输入存储到pokemonType中,然后还使用pokemonType从CSV文件中读取数据。文件输入将覆盖用户输入。

  2. 您的文件输入循环始终引用索引0。数据文件中的所有行都将进入元素0。这是即使用户输入1,输出也是从数据文件的最后一行输出的主要原因。

  3. 您的文件读取循环的结构类似于您希望将每条数据行的一部分放入不同的数组中,但是您编写的内容实际上在每次迭代中读取三行,并将这些行存储在三个不同的数组中

  4. 这不会影响您的输出,但是编写代码ifstream close("pokedex.csv");就像您要关闭打开的文件流一样,但是我确实相信这行实际上是在创建 ifstream称为close,然后打开附加到其的pokedex.csv。换句话说,它与您的另一行ifstream ip("pokedex.csv");就像,但变量名是close而不是ip


您将要研究称为“字符串标记化”的内容。从一些网络搜索开始,将您所学的内容应用于代码,当然,如果遇到其他问题,请在此处向Stack Overflow发布一个新问题,以显示(就像您在此处所做的那样)您尝试过的内容以及采用的方式”工作。


关于#3的详细说明,这是如何读取您的数据文件:

在文件读取循环的第一次迭代结束时,...

pokedexnum[0]   is  "1,Bulbasaur,grass"
pokemonName[0]  is  "2,Ivysaur, grass"
pokemonType[0]  is  "3,Venusaur, grass"

在文件读取循环的第二次迭代结束时,...

pokedexnum[0]   is  "4,Charmander, fire"
pokemonName[0]  is  "5,Charmeleon, fire"
pokemonType[0]  is  "6,Charizard, fire"

在文件读取循环的第三次迭代结束时,...

pokedexnum[0]   is  "7,Squirtle, water"
pokemonName[0]  is  "8,Wartortle, water"
pokemonType[0]  is  "9,Blastoise, water"

这就是为什么

<< "is the pokemon called:"<< pokemonName[0];

输出

is the pokemon called:8,Wartortle, water