0

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;
}
Zarari
  • 29
  • 6
  • 1
    "`string namesarray[25];`"? ...Why didn't you use a `std::vector` ?... Also read [why using `eof()` as loop condition is considered wrong](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) – WhiZTiM Mar 12 '17 at 19:05
  • I haven't learned about vectors yet I'm still stuck to using arrays. I've setup a similar while loop to the one above like with: while(getline(inputFile, line, ',')) but I'm still having the same issues. – Zarari Mar 12 '17 at 19:13
  • From what I can see `i` is near-worthless in this code. Regardless, if you really wanted to do this as per-line validation and input an intermediate `std::string` and a `std::istringstream` would probably make the code much easier to understand. And seriously; a vector of struct, each holding a single name and a vector of scores is the right approach here. – WhozCraig Mar 12 '17 at 19:24
  • How would I use istringstream? – Zarari Mar 12 '17 at 19:30

5 Answers5

1

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.

olaralex
  • 57
  • 1
  • 1
  • 9
1

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

Fanarosss
  • 306
  • 3
  • 17
1

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.

xX Eman Xx
  • 111
  • 5
0

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

Timur Kukharskiy
  • 305
  • 3
  • 16
0

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;
}
Remy Lebeau
  • 454,445
  • 28
  • 366
  • 620