Reputation: 29
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
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
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
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
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
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