Home > Blockchain >  Strange issue reading from a CSV
Strange issue reading from a CSV

Time:12-15

I am trying to write a program that will allow the user to search for any element on the periodic table by searching using name, atomic number, or symbol. Currently the name and atomic number work fine, but when I tried to copy and paste the code for the symbol, it's suddenly not working. Even hard coding in a cout << "Hello World!"; will not display. Any tips?

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

using namespace std;

std::vector<std::string> readAtomicNumber(std::string file_name,std::string search_term);
std::vector<std::string> readName(std::string file_name,std::string search_term);
std::vector<std::string> readSymbol(std::string file_name,std::string search_term);

int main()
{
    
    int searchchoice;
    int AtomicNumber;
    string Name;
    string Symbol;
    string term;
    
    cout << "How will you be searching?\nYou may search using;\n1 = Element Name\n2 = Element Symbol\n3 = Atomic Number\n4 = Show me the entire Periodic Table.\n\n";
    cin  >> searchchoice;
    
    if(searchchoice == 4)
    {
        //something here to cout the entire periodic table
    }
    else if(searchchoice == 3)
    {
        cout << "\n\nWhat is the Atomic Number of the Element you are searching for?\n";
        cin >> term;
    }
    else if(searchchoice == 2)
    {
        cout << "\n\nWhat is the Symbol of the Element you are searching for?\n";            // going to need something to return
        cin >> term;                                                                         // "that is not a name/atomic number etc"
    }                                                                                        // incase of a false input
    else if(searchchoice == 1)   
    {
        cout << "\n\nWhat is the Name of the Element you are searching for?\n";
        cin >> term;
    }
    else
    {
        cout << "\n\nError. Please re-run the program, and input 1, 2, or 3.\n";
        return 0;
    }
    
    if(searchchoice == 3)
    {
        std::vector<std::string> data = readAtomicNumber("PeriodicTableupdated",term);                  //atomic number
    }
    else if(searchchoice == 2)
    {
        std::vector<std::string> data = readSymbol("PeriodicTableupdated",term);                         //symbol
    }                                                                                        
    else if(searchchoice == 1)   
    {
        std::vector<std::string> data = readName("PeriodicTableupdated",term);                           //name
    }

    
return 0;
}

std::vector<std::string> readAtomicNumber(std::string file_name,std::string search_term)            //READ ATOMIC NUMBER
{
    std::vector<std::string> record;
    
    std::ifstream file;
    file.open(file_name);
    
    bool found_record = false;
    
    std::string field_one; //atomic number
    std::string field_two; // name
    std::string field_three; // symbol
    std::string field_four;
    
    while(getline(file,field_one,',') && !found_record)
    {
        getline(file,field_two,',');
        getline(file,field_three,',');
        getline(file,field_four,'\n');
        if(field_one == search_term)
        {
            found_record = true;
            record.push_back(field_one);
            record.push_back(field_two);
            record.push_back(field_three);
            record.push_back(field_four);
        }
    }
    
        std::cout << "\nThat Element is: " << record[1] << "\nAtomic Number:\tName:\t\tSymbol:\t\tAtomic Mass:\n" << record[0] << "\t\t" << record[1] << "\t" << record[2] << "\t\t" << record[3];
    return record;
}

std::vector<std::string> readName(std::string file_name,std::string search_term)            // READ NAME
{
    std::vector<std::string> record;
    
    std::ifstream file;
    file.open(file_name);
    
    bool found_record = false;
    
    std::string field_one; //atomic number
    std::string field_two; // name
    std::string field_three; // symbol
    std::string field_four;
    
    while(getline(file,field_two,',') && !found_record)
    {
        getline(file,field_one,',');
        getline(file,field_three,',');
        getline(file,field_four,'\n');
        if(field_one == search_term)
        {
            found_record = true;
            record.push_back(field_one);
            record.push_back(field_two);
            record.push_back(field_three);
            record.push_back(field_four);
        }
    }
    
        std::cout << "\nThat Element is: " << record[0] << "\nAtomic Number:\t\tName:\t\tSymbol:\t\tAtomic Mass:\n" << record[1] << "\t\t\t" << record[0] << "\t" << record[2] << "\t\t" << record[3];
    return record;
}

std::vector<std::string> readSymbol(std::string file_name,std::string search_term)            // READ SYMBOL
{
    std::vector<std::string> record;
    
    std::ifstream file;
    file.open(file_name);
    
    bool found_record = false;
    
    std::string field_one; //atomic number
    std::string field_two; // name
    std::string field_three; // symbol
    std::string field_four;
    
    while(getline(file,field_three,',') && !found_record)
    {
        getline(file,field_one,',');
        getline(file,field_two,',');
        getline(file,field_four,'\n');
        if(field_three == search_term)
        {
            found_record = true;
            record.push_back(field_one);
            record.push_back(field_two);
            record.push_back(field_three);
            record.push_back(field_four);
        }
    }
    
        std::cout << "\nThat Element is: " << record[2] << "\nAtomic Number:\t\tName:\t\tSymbol:\t\tAtomic Mass:\n" << record[0] << "\t\t\t" << record[1] << "\t" << record[2] << "\t\t" << record[3];
    return record;
}

The Periodic Table csv I'm using has 118 elements, so I will just include the first 10 elements for this purpose.

AtomicNumber,Element,Symbol,AtomicMass
1,Hydrogen,H,1.007
2,Helium,He,4.002
3,Lithium,Li,6.941
4,Beryllium,Be,9.012
5,Boron,B,10.811
6,Carbon,C,12.011
7,Nitrogen,N,14.007
8,Oxygen,O,15.999
9,Fluorine,F,18.998
10,Neon,Ne,20.18

CodePudding user response:

I highly recommend not using parallel arrays, but using vectors of structs that model the data (record). Let's define a record as the data on one text line, less the separator characters.

struct Element
{
    unsigned int atomic_number;
    std::string  name;
    std::string  symbol;
    double       atomic_mass;
    friend std::istream& operator>>(std::istream& input, Element& e);
};

std::istream& operator>>(std::istream& input, Element& e)
{
    std::string text_record;
    std::getline(input, text_record);
    std::istringstream text_stream(text_record);
    text_stream >> e.atomic_number;
    char comma;
    text_stream >> comma;
    std::getline(text_stream, e.name, ',');
    std::getline(text_stream, e.symbol, ',');
    text_stream >> e.atomic_mass;
    return input;
};

The above code models the Element and overloads operator>> to read an Element.

Your data input could look like this:

std::vector<Element> database;
Element e;
//... open file.
while (file >> e)
{
    database.push_back(e);  // Append to database;
}

You can then search the database by brute force.

Edit 1: Index tables
An index table is a table that is sorted by a key member and contains links or offsets to the database. This will allow you to search by keys without having to resort the database.

We're going to need an index table, that compares by name:

std::map<string, unsigned int> index_by_name;

Here's the modification to the input:

unsigned int db_index = 0;
while (file >> e)
{
    database.push_back(e);
    index_by_name[e.name] = db_index;
      db_index;
}

So, to search the database for Sodium, you would do:

unsigned int sodium_index = index_by_name.at("Sodium");
Element sodium_element = database.at(sodium_index);

Without index tables, you would have to either do a linear search, or sort the database then do a binary search (or other search based on a sorted contents).

CodePudding user response:

std::vector<std::string> readSymbol(std::string file_name, std::string search_term)            // READ SYMBOL
{
    std::vector<std::string> record;

    std::ifstream file;
    file.open(file_name);

    bool found_record = false;

    std::string field_one; //atomic number
    std::string field_two; // name
    std::string field_three; // symbol
    std::string field_four;

    while (getline(file, field_three, ',') && !found_record)
    {
        getline(file, field_one, ',');
        getline(file, field_two, ',');
        getline(file, field_four, '\n');
        if (field_three == search_term)
        {
            found_record = true;
            record.push_back(field_one);
            record.push_back(field_two);
            record.push_back(field_three);
            record.push_back(field_four);
        }
    }

    std::cout << "\nThat Element is: " << record[2] << "\nAtomic Number:\t\tName:\t\tSymbol:\t\tAtomic Mass:\n" << record[0] << "\t\t\t" << record[1] << "\t" << record[2] << "\t\t" << record[3];
    return record;
}

in this part you literally assign the first string until , to field_three.

but that first string is actually line number since the structure of your file is:

lineNumber , Name, Symbol, Mass

so comparison of (field_three == search_term) is actually a comparison between lineNumber and Symbol which is not logical.

when you debug you will see variables better.

i will drop a screenshot below.

enter image description here

  • Related