Reading in a CSV file for integers - c++

I have a test file set up here trying to read in a CSV file
ifstream file;
file.open("New Microsoft Excel Worksheet.csv");
string temp;
string arr[15];
int size = 0;
int index = 0;
while (getline(file, temp, ','))
{
if (!temp.empty())
{
arr[index] = temp;
std::cout << arr[index];
size++;
index++;
}
}
Output
34568
29774
18421
it successfully captures each index, and even lines them out in a row (I'm guessing its also capturing a \n?)
however I need them to be integers, I would do this in the same loop with a stoi() function, but I need the size of the array to be dynamic (I don't want to use vectors here because this is fitting into another part of code that needs an array)
Here is how I turn them into integers and put them in a new array
int *intArr = new int[size];
for (index = 0; index < size; index++)
{
intArr[index] = stoi(arr[index]);
std::cout << intArr[index];
}
and here is the output for this
3456897748421
It seems to miss each number after it switches to the next row in the csv
If I structure it properly, heres whats going on
34568
9774
8421
I'm guessing this has something to do with CSV files giving a \n at the end of a row in an excel file.
How do I fix this? I need all the values to be integers, thanks!

I figured it out, you need two while loops like this:
while (getline(file, temp))
{
istringstream ss(temp);
while (getline(ss, data, ','))
{
arr[index] = data;
std::cout << arr[index];
size++;
index++;
}
}
I'm not exactly sure why you need two, because this seems kind of redundant, but getting the line THEN putting it in a string stream seems to get rid of that new line
Thanks to #brc-dd for the help!

Related

2d array displaying unwanted characters

I have a problem with displaying the contents of a 2d array, I have searched on here for solutions but as I'm not entirely sure what my problem is, I'm not sure I'm asking the right question.
I am writing a program that lets the user open a .txt file which will always contain 30 by 30 characters all separated by a comma and the first line and row will be 0,1,2,3,,,9,0,1,2,3,,,9 and the end of each line will be a new line. The programme should display the contents of the .txt file on the screen without the commas then go on to allow the user to search the location of characters in the file.
I thought the best way to do this would be to use the getline function with a delimiter to populate a 2d array, this seems to have worked except when I display the content of the array, the last character is repeated and I'm not sure if it's due to the way I am populating the array or the way in which I am displaying the array.
while(!inputFile.eof())
{
for (int i = 0; i < SIZE; ++i) // SIZE is defined 30
{
for (int j = 0; j < SIZE; ++j)
{
getline(inputFile, line,',');
aArray[i][j] = line; // aArray and line are declared as strings
std::cout << aArray[i][j];
}
}
cout << endl;
}
This is my input:
0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9
1,*,!,8,0,;,*,a,b,0,8,0,.,y,Z,c,4,4,8,8,8,8,y,y,y,4,–,6,8,!
2,0,0,0,0,0,0,0,0,0,0,1,1,1,2,2,0,0,0,5,5,J,J,J,J,J,J,J,J,j
3,9,8,7,0,8,0,8,0,A,c,4,4,*,F,F,6,F,K,J,H,G,5,s,H,U,P,2,2,0
4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
6,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,Y,Y,Y,0,0,0,0,0,0,0
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
9,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,Y,Y,Y,0,0,0,0,0,0,0
0,0,1,1,2,2,D,D,5,5,$,£,!,a,A,a,A,a,A,a,A,a,A,a,A,a,A,a,A,8
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
2,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
3,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,Y,Y,Y,0,0,0,0,0,0,0
4,0,1,1,2,2,D,D,5,5,$,£,!,a,A,a,A,a,A,a,A,a,A,a,A,a,A,a,A,8
5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
6,0,8,0,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
7,P,0,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,Y,Y,Y,0,0,0,0,0,0,0
8,0,1,1,2,2,D,D,5,5,$,£,!,a,A,a,A,a,A,a,A,a,A,a,A,a,A,a,A,8
9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
1,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,Y,Y,Y,0,0,0,0,0,0,0
2,0,1,1,2,2,D,D,5,5,$,£,!,a,A,a,A,a,A,a,A,a,A,a,A,a,A,a,A,8
3,0,1,1,2,2,D,D,5,5,$,£,!,a,A,a,A,a,A,a,A,a,A,a,A,a,A,a,A,8
4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
6,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,Y,Y,Y,0,0,0,0,0,0,0
7,0,1,1,2,2,D,D,5,5,$,£,!,a,A,a,A,a,A,a,A,a,A,a,A,a,A,a,0,8
8,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,Y,Y,Y,0,0,0,0,0,8,0
9,0,1,1,2,2,D,D,5,5,$,£,!,a,A,a,A,a,A,a,A,a,A,a,A,a,A,a,0,8
This is my output:
012345678901234567890123456789
1*!80;*ab080.yZc448888yyy4–68!
200000000001112200055JJJJJJJJj
398708080Ac44*FF6FKJHG5sHUP220
400000000000000000000000000000
588888888888888888888888888888
6PPPPPPPPPPPPPPPPPPPYYY0000000
700000000000000000000000000000
888888888888888888888888888888
9PPPPPPPPPPPPPPPPPPPYYY0000000
001122DD55$£!aAaAaAaAaAaAaAaA8
100000000000000000000000000000
288888888888888888888888888888
3PPPPPPPPPPPPPPPPPPPYYY0000000
401122DD55$£!aAaAaAaAaAaAaAaA8
500000000000000000000000000000
608088888888888888888888888888
7P0PPPPPPPPPPPPPPPPPYYY0000000
801122DD55$£!aAaAaAaAaAaAaAaA8
900000000000000000000000000000
088888888888888888888888888888
1PPPPPPPPPPPPPPPPPPPYYY0000000
201122DD55$£!aAaAaAaAaAaAaAaA8
301122DD55$£!aAaAaAaAaAaAaAaA8
400000000000000000000000000000
588888888888888888888888888888
6PPPPPPPPPPPPPPPPPPPYYY0000000
701122DD55$£!aAaAaAaAaAaAaAa08
8PPPPPPPPPPPPPPPPPPPYYY0000080
901122DD55$£!aAaAaAaAaAaAaAa0888888888888888888888888888888
As you can see the last character is repeated which is not what I want. I am new to C++ so I'm not sure if I'm even using the best method, I spent nearly 2 days trying to solve a problem I created by mistakingly putting cout << endl; within my for loop so I am reaching out to the fine members if stack overflow for some much needed guidance.
To expand on the comment by #WhozCraig, you shouldn't use iostream::eof inside the loop condition, since it won't return true until after the end of the file is read. Instead, something like this should suffice (note there are many ways to do this):
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#define SIZE 30
int main() {
std::string line;
std::string aArray[SIZE][SIZE];
std::ifstream inputFile("file2.txt");
for (int i = 0; getline(inputFile, line) && i < SIZE; ++i) {
std::istringstream lineStream(line);
std::string token;
for (int j = 0; getline(lineStream, token, ',') && j < SIZE; ++j) {
aArray[i][j] = token;
std::cout << aArray[i][j];
}
std::cout << std::endl;
}
}
Which will provide the desired output:
012345678901234567890123456789
1*!80;*ab080.yZc448888yyy4–68!
200000000001112200055JJJJJJJJj
398708080Ac44*FF6FKJHG5sHUP220
400000000000000000000000000000
588888888888888888888888888888
6PPPPPPPPPPPPPPPPPPPYYY0000000
700000000000000000000000000000
888888888888888888888888888888
9PPPPPPPPPPPPPPPPPPPYYY0000000
001122DD55$£!aAaAaAaAaAaAaAaA8
100000000000000000000000000000
288888888888888888888888888888
3PPPPPPPPPPPPPPPPPPPYYY0000000
401122DD55$£!aAaAaAaAaAaAaAaA8
500000000000000000000000000000
608088888888888888888888888888
7P0PPPPPPPPPPPPPPPPPYYY0000000
801122DD55$£!aAaAaAaAaAaAaAaA8
900000000000000000000000000000
088888888888888888888888888888
1PPPPPPPPPPPPPPPPPPPYYY0000000
201122DD55$£!aAaAaAaAaAaAaAaA8
301122DD55$£!aAaAaAaAaAaAaAaA8
400000000000000000000000000000
588888888888888888888888888888
6PPPPPPPPPPPPPPPPPPPYYY0000000
701122DD55$£!aAaAaAaAaAaAaAa08
8PPPPPPPPPPPPPPPPPPPYYY0000080
901122DD55$£!aAaAaAaAaAaAaAa08

Read Strings from a text file and place in 2D Array

I've spent the past two hours search this and other forums for pointers & guidance on how I can read a txt file, line by line, and store them in a 2D array that I can manipulate with other functions and then later save the array back to the text file; with little luck. Hopefully some bright spark can point me in the right direction.
Currently my text file contains data, separated by spaces, that looks like this:
Number1 Number2 Number3
Colour1 Colour2 Colour3
Letter1 Letter2 Letter3
...
The "getting and setting" of the 2D Array needs to be done in a separate function, and I think the array's need to be global because they will later be manipulated by other functions (i.e. add a new row, delete a row, etc.)
I know the start to the function will need to look something like this:
void getAndSetData()
{
fstream file1;
file1.open("1.txt", ios::in);
}
And will contain a nested for loop that will in turn, set the elements in the 2D array 1 by one. However, I'm really at a loss as how to go about this.
Thank you in-advance.
Hello here is example code how I did it
ifstream in("test.txt"); // input file
string my_array[3][200];
void read_into_array()
{
if(in.is_open())
{
for(int i = 0; i < 200; ++i) // number of rows
{
for(int j = 0; j < 3; ++j) // number of columns
{
in >> my_array[i][j];
cout<<my_array[i][j]<<"\t";
}
cout<<endl;
}
}
}

Access/modify specific row/column of text file

I'm doing some practice in understanding how fstream works, and I've hit a brick wall.
I've initialised a 3x3 text file with each element being 'temp'
I want to be able to access a specific "element", delete it, and then replace it with a string (could be larger or smaller than the current size) but enclosed by the tab characters.
i.e. simulating an edit of a text file
I've been doing some research online, like here: http://www.cplusplus.com/doc/tutorial/files/ but I struggle a lot with implementing it myself.
So the text file, "example.txt" contains:
temp temp temp
temp temp temp
temp temp temp
I'd like to open it for writing, seek the position of say, row 2, column 2 (i.e. corresponding to \n and \t characters), replace it with another string, for example "thisisareplacement"
temp temp temp
temp thisisareplacement temp
temp temp temp
From my understanding, this may not be possible as I'm inputting a much larger size of characters. However I believe somehow defining these \n and \t characters to enclose my strings could give me an opportunity.
Here's my code:
#include <iostream>
#include <fstream>
using namespace std;
int main () {
int numRows = 3;
ofstream myfile ("example.txt");
if (myfile.is_open())
{
for (int i = 0; i < numRows; i++) {
for (int j = 0; j < numRows; j++) {
myfile << "temp\t";
}
myfile << "\n";
}
myfile.close();
}
else { cout << "Unable to open file"; }
// now i want to try and edit a specific row (\n) and column (\t)
return 0;
}

Data parsing from text file

i have encountered an issue regarding parsing values from a text file. What i am trying to do is i need to add up all the values for each specific events for all days and find the average of it. Example will be (290+370+346+325+325)/5 and (5+5+5+12)/4 based on the data in the text file.
A sample is listed below
For each line --> First event:Second event:Third event...:Total number of event:
Every new line is considered a new day.
3:290:61:148:2:5:
2:370:50:173:4:5:
5:346:87:131:4:
3:325:60:145:5:5:
3:325:60:145:5:12:13:7:
I have tried to do it myself but i have only managed to store each column in a string array only. Sample code below. Will appreciate if you guys can help, thanks!
void IDS::parseBase() {
string temp = "";
int counting = 0;
int maxEvent = 0;
int noOfLines = 0;
vector<string> baseVector;
ifstream readBaseFile("Base-Data.txt");
ifstream readBaseFileAgain("Base-Data.txt");
while (getline(readBaseFile, temp)) {
baseVector.push_back(temp);
}
readBaseFile.close();
//Fine the no. of lines
noOfLines = baseVector.size();
//Find the no. of events
for (int i=0; i<baseVector.size(); i++)
{
counting = count(baseVector[i].begin(), baseVector[i].end(), ':') - 1;
if (maxEvent < counting)
{
maxEvent = counting;
}
}
//Store individual events into array
string a[maxEvent];
while (getline(readBaseFileAgain, temp)) {
stringstream streamTemp(temp);
for (int i=0; i<maxEvent; i++)
{
getline(streamTemp, temp, ':');
a[i] += temp + "\n";
}
}
}
I suggest:
int a[maxEvent];
char c; // to hold the colon
while(streamTemp >> a[i++] >> c);

How to find out unknown number of rows and cols in a input file?

Okay so the input file looks like this:
00000000100000001010
00000000010000001001
11100000010100000010
10100100101010101010
00101010010010101000
This is an example grid which is 5x20 and the catch is that the rows and cols can be arbitrary. Which means that I need to figure out how many rows and cols the input file has before I can start computing my two dimensional array.
So I am a little confused because right now I am just trying to read in the array then output it to the console without knowing the rows and cols initially. Please help me with this it's annoying and I can't find a way to do it.
P.S. I can not use the string library
The traditional way to do this is to loop through each character in a char array and keeping track of the number of characters until you hit a newline, depending on the format of the data.
#include <iostream>
using namespace std;
int main()
{
char arr[] = "00000000100000001010\n00000000010000001001\n11100000010100000010\n10100100101010101010 \n00101010010010101000";
int cols = 0;
int rows = 0;
for(int i = 0; arr[i] != '\0';i++)
{
if(rows == 0)
cols++;
if(arr[i] == '\n')
rows++;
}
std::cout<<cols<<" Colums"<<std::endl<<rows+1<<" Rows"<<std::endl;
return 0;
}
This is assuming that the columns are uniform and you have your data in an array.
It's much easier/cleaner/better to read in character by character from a stream, but this is the old way.
There are many ways to proceed, depending on what the motivation was behind your teacher's prohibition on using string. One of the two options below will probably be acceptable. Note that I've played a little fast and loose and skipped a fair amount of error checking, but you shouldn't when you flesh it out. In all cases, I'm assuming the file does not end in a line terminator (as you've shown) and is rectangular (same number of characters on every line).
Use an automatically resizing container
You can still get the essential benefit (for this case) of free memory management without using a string. For example, push the characters one-by-one into a vector:
std::ifstream inF("input.txt");
std::vector<char> contents;
char c;
while(inF.get(c).good())
{
contents.push_back(c);
}
int rows = 1 + std::count(contents.begin(), contents.end(), '\n');
int columns = std::find(contents.begin(), contents.end(), '\n') - contents.begin();
Read out the length of the file from the stream
It's a pretty simple matter to figure out how big the file is and pre-allocate a buffer large enough to hold it:
std::ifstream inF("input.txt");
// option 1
inF.seekg(0, std::ios_base::end);
int charCount = inF.tellg();
// option 2
//int charCount = 0;
//while(inF.get() != std::char_traits<char>::eof())
//{
// charCount++;
//}
//inF.clear();
char* contents = new char[charCount + 1];
inF.seekg(0);
inF.read(contents, charCount);
contents[charCount] = '\0';
int rows = 1 + std::count(contents, contents + charCount, '\n');
int columns = std::find(contents, contents + charCount, '\n') - contents;
delete[] contents;