Zarari
Zarari

Reputation: 29

Read a text file and store into two different arrays: a string array and float array

I'm having trouble storing my code into two different arrays. The following text file contains a format like this: name,1,2,3,4,5anothername,6,7,8,9,10...

For example it could be something like this, I'll name it test.txt:

Drake,1,2,3,4,5
Kanye West,6,7,8,9,10
Ka,11,12,13,14,15,16
Young Thug,17,18,19,20
Kendrick Lamar,21,22,23,24,25

Here is my code so far:

#include <iostream>
#include <fstream>
#include <stdlib.h>
using namespace std;

int main(){
    ifstream inputFile;
    inputFile.open("test.txt");

    if (inputFile.fail()){
        cout << "File open error!" << endl;
        return -1;
    }

    string namesarray[25];    //array used to store names
    float numbersarray[25];    //array used to store numbers
    string line;    //string used to read text file
    int i = 0;    //counter for entire text input
    int j = 0;    //counter for namesarray
    int k = 0;    //counter for numbersarray

    while(getline(inputFile, line, ',')){
        if (line[i] >= 'A' && line[i] <= 'Z'){
            namesarray[j] = line;
            j++;
        }
        else{
            numbersarray[k] = stof(line);
            k++;     
        }
        i++;
    }
    inputFile.close();
}

My problem is that I can't store all the names into the string array, but the numbers are stored into the float array just fine. My code only stores in the first name and then a random number. For example if I create a loop to check if the names or the numbers are stored in correctly

for (int a = 0; a < 25; a++){
    cout << numbersarray[a] << endl;
}

The numbers are stored in fine but checking for the names it doesn't store all the names in there. If I'm checking for the first letter of the line shouldn't it store the name in there if it contains a letter? I don't want to use isalpha() because it still outputs the same problem.

for (int a = 0; a < 25; a++){
    cout << namesarray[a] << endl;
}

Upvotes: 0

Views: 2820

Answers (5)

xX Eman Xx
xX Eman Xx

Reputation: 111

the getLine function's delimiter is a comma, so when it gets to the last number for each name, it reads the number and the name in one string. To fix it, consider something like:

bool letter = true;
bool letterNum = false;
int index = 0;
if((line[0] >= '9' && line[0] >= '0') || line[0] == '.') {
    letter = false;
}
for(int l = 0; l < line.length()) {
    if((letter && ((line[l] >= '9' && line[l] >= '0') || line[l] == '.')) || (!letter && !((line[l] >= '9' && line[l] >= '0') || line[l] == '.'))) {
        index = l;
        l = line.length();
    }
}

if(letter && index == 0) {
    namesarray[j] = line;
    j++;
    i++;
}

if(!letter && index == 0) {
    numbersarray[k] = atoi(line);
    k++;
    i++;
}

if(letter && index != 0) {
    namesarray[j] = line.substr(0, index);
    numbersarray[k] = stof(line.substr(index, line.length() - index));
    j++;
    k++;
    i += 2;
}

if(!letter && index != 0) {
    numbersarray[k] = stof(line.substr(0, index));
    namesarray[j] = line.substr(index, line.length() - index);
    j++;
    k++;
    i += 2;
}

Instead of:

if (line[i] >= 'A' && line[i] <= 'Z'){
    namesarray[j] = line;
    j++;
}
else{
    numbersarray[k] = stof(line);
    k++;     
}
i++;

Inside the while loop. You could also use ifstream >> string, because that reads one line at a time, and you could just parse each substring in between the commas. That may look something like:

#include <iostream>
#include <fstream>
#include <stdlib.h>
using namespace std;

int main(){
    ifstream inputFile;
    inputFile.open("test.txt");

    if (inputFile.fail()){
        cout << "File open error!" << endl;
        return -1;
    }

    string namesarray[25];    //array used to store names
    float numbersarray[25];    //array used to store numbers
    string line;    //string used to read text file
    int i = 0;    //counter for entire text input
    int j = 0;    //counter for namesarray
    int k = 0;    //counter for numbersarray

    while(!inputFile.eof()){
        string data;
        inputFile >> data;
        int lastIndex = 0;
        for(int l = 0; l < data.length(); l++) {
            if(data[l] == ',' || l == data.length() - 1) {
                line = data.substr(lastIndex, l - lastIndex);
                lastIndex = l + 1;
                if (((line[l] >= '9' && line[l] >= '0') || line[l] == '.')){
                    numbersarray[k] = stof(line);
                    k++;    
                }
                else{
                    namesarray[j] = line;
                    j++;
                }
                i++;
            }
        }
    }
    inputFile.close();
}

However, this only works when each name and it's numbers are separated by a \n. If they are, this is the better option. But if they aren't, use the first method.

Upvotes: 1

Remy Lebeau
Remy Lebeau

Reputation: 597051

This is better handled using std::getline() to read an entire line, and then std::istringstream to parse each line, eg:

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

using namespace std;

int main()
{
    ifstream inputFile;
    inputFile.open("test.txt");
    if (!inputFile)
    {
        cout << "File open error!" << endl;
        return -1;
    }

    string namesarray[25]; //array used to store names
    float numbersarray[25*5]; //array used to store numbers
    string s; //string used to read text file
    int i = 0; //counter for entire text input
    int j = 0; //counter for namesarray
    int k = 0; //counter for numbersarray

    while (getline(inputFile, s))
    {
        istringstream iss(s);
        getline(iss, namesarray[j], ',');
        ++j;

        while (getline(iss, s, ','))
        {
            numbersarray[k] = stof(s);
            ++k;
        }

        ++i;
    }

    inputFile.close();
    return 0;
}

Upvotes: 0

Fanarosss
Fanarosss

Reputation: 306

I can not find the use of the i++;. You always have to look for line[0].

I suggest using isdigit(line[0]) to check either it is a number or a character

The problem with your code is that you are checking only for upper case letters. Upper case letters exist only in the first character of the string with the name. So when i++; goes to i>0, line[i] stops to be an upper case, and becomes a lower case.

Also I want you to know that stof works only in c++11

Upvotes: 1

olaralex
olaralex

Reputation: 57

With getline() the third parameter does not eliminates commas. It specifies the delimeter until which the function fills your string. So according to your input file, it is going to get the names.

Upvotes: 1

Timur Kukharskiy
Timur Kukharskiy

Reputation: 303

Why in else statement is i++? You must check the i variable first element of array be but not the addition of it.

Upvotes: 0

Related Questions