I'm quite new to C++, so sorry if this is a dumb question!
For a project we are given a file with a couple of thousand lines of values, each line having 9 different numbers.
I want to create a for/while loop that, for each loop, stores the 8th and 9th integer of a line as a variable so that I can do some calculations with them. The loop would then move onto the next line, store the 8th and 9th numbers of that line as the same variable, so that I can do the same calculation to it, ending when I've run out of lines.
My problem is less to do with reading the file, I'm just confused how I'd tell it to take only the 8th and 9th value from each line.
Thanks for any help, it is greatly appreciated!
Designed for readability rather than speed. It also performs no checking that the input file is the correct format.
template<class T> ConvertFromString(const std::string& s)
{
std::istringstream ss(s);
T x;
ss >> x;
return x;
}
std::vector<int> values8;
std::vector<int> values9;
std::ifstream file("myfile.txt");
std::string line;
while (std::getline(file, line))
{
std::istringstream ss(line);
for (int i = 0; i < 9; i++)
{
std::string token;
ss >> token;
switch (i)
{
case 8:
{
values8.push_back(ConvertFromString<int>(token));
}
break;
case 9:
{
values9.push_back(ConvertFromString<int>(token));
}
break;
}
}
}
First, split the string, then convert those to numbers using atoi. You then will take the 8th and 9th values from the array or vector with the numbers.
//Split string
std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, delim)) {
elems.push_back(item);
}
return elems;
}
std::vector<std::string> split(const std::string &s, char delim) {
std::vector<std::string> elems;
split(s, delim, elems);
return elems;
}
//new code goes here
std::string line;
std::vector<std::string> lineSplit = split(line, ' ');
std::vector<int> numbers;
for (int i = 0; i < lineSplit.size(); i++)
numbers.push_back(atoi(lineSplit[i]);//or stoi
int numb1 = numbers[7];//8th
int numb2 = numbers[8];//9th
Related
I want to be able to parse a string such as:
inputStr = "abc 12 aa 4 34 2 3 40 3 4 2 cda t 4 car 3"
Into separate vectors (a string vector and integer vector) such that:
strVec = {"abc", "aa", "cda", "t", "car"};
intVec = {12, 4, 34, 2, 3, 40, 3, 4, 2, 4, 3};
What is a good method to do this? I'm somewhat familiar with stringstream and was wondering whether it's possible to do something like this:
std::string str;
int integer;
std::vector<int> intVec;
std::vector<std::string> strVec;
std::istringstream iss(inputStr);
while (!iss.eof()) {
if (iss >> integer) {
intVec.push_back(integer);
} else if (iss >> str) {
strVec.push_back(str);
}
}
I have attempted something to that effect, but the program seems to enter a halt of sorts (?). Any advice is much appreciated!
When iss >> integer fails, the stream is broken, and iss >> str will keep failing. A solution is to use iss.clear() when iss >> integer fails:
if (iss >> integer) {
intVec.push_back(integer);
} else {
iss.clear();
if (iss >> str) strVec.push_back(str);
}
I think this answer is the best here.
#include <string>
#include <sstream>
#include <vector>
#include <iterator>
template<typename Out>
void split(const std::string &s, char delim, Out result) {
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, delim)) {
*(result++) = item;
}
}
std::vector<std::string> split(const std::string &s, char delim) {
std::vector<std::string> elems;
split(s, delim, std::back_inserter(elems));
return elems;
}
Originally answered here, You can then try to distinguish between strings and numbers.
To expand on the title, I am reading a file line-by-line that appears as so:
FirstName,LastName,mm/dd/yyyy,SSN,Role,Salary,Zip,Phone
I have this code I just wrote but am having some trouble placing it into my struct as I'm using std::string as opposed to char[]. I want to continue using std::string for purposes down the road. Also, excuse any syntax errors as I haven't written in c/c++ in a while. I have also read the most elegant way to iterate to words of a string but I am still confused on how to do that with the slashes involved in the date format. SSN and Salary are private members of a struct that will be pushed into a vector for later use. How can I do this using c++ libraries? To be honest, the istringstream confuses me as they include some type of parser inside their struct directly. Is this honestly the best way to accomplish what I'm trying to do?
char stringData[150]; //line to be read in
while(fgets(stringData, 150, infile) != NULL) {
if( currentLine == 1) {
fgets(stringData, 150, infile); //get column names | trash
}
else {
lineSize = sscanf(stringData, "%[^,],%[^,],%d/%d/%d,%d,%[^,],%lf,%[^,],%s", temp.firstName,temp.lastName,
&temp.birthMonth,&temp.birthDay,&temp.birthYear,
&tempSSN, temp.role, &tempSalary, temp.zip,
temp.phoneNum);
if(lineSize != 10) { //error message due to a row being incorrect
cerr << "/* ERROR: WRONG FORMAT OF INPUT(TOO FEW OR TOO MANY ARGUMENTS) ON LINE: */" << currentLine << '\n';
exit(1);
}
temp.setSSN(tempSSN);
temp.setSalary(tempSalary);
vector.push_back(temp);//push Employee temp into the vector and repeat loop
}
currentLine++
}
TL;DR: What is the easiest way to do this using c++ libraries?
As Sam Varshavchik already mentioned, the easiest way would be separating input with , then separate on of them with / again.
Thanks to this famous question I'm using following approach to split string :
template<typename Out>
void split(const std::string &s, char delim, Out result)
{
std::stringstream ss(s);
std::string item;
while(std::getline(ss, item, delim))
{
*(result++) = item;
}
}
std::vector<std::string> split(const std::string &s, char delim)
{
std::vector<std::string> elems;
split(s, delim, std::back_inserter(elems));
return elems;
}
assuming that this is your structure :
struct info
{
std::string firstName;
std::string lastName;
std::string birthMonth;
std::string birthDay;
std::string birthYear;
std::string tempSSN;
std::string role;
std::string tempSalary;
std::string zip;
std::string phoneNum;
};
I would implement your needed function like this :
void parser(std::string fileName, std::vector<info> &inf)
{
std::string line;
std::ifstream infile(fileName);
int index = inf.size();
while(std::getline(infile, line))
{
inf.push_back({});
std::vector<std::string> comma_seprated_vec = split(line, ',');
inf.at(index).firstName = comma_seprated_vec.at(0);
inf.at(index).lastName = comma_seprated_vec.at(1);
inf.at(index).tempSSN = comma_seprated_vec.at(3);
inf.at(index).role = comma_seprated_vec.at(4);
inf.at(index).tempSalary = comma_seprated_vec.at(5);
inf.at(index).zip = comma_seprated_vec.at(6);
inf.at(index).phoneNum = comma_seprated_vec.at(7);
std::vector<std::string> slash_seprated_vec = split(comma_seprated_vec.at(2), '/');
inf.at(index).birthMonth = slash_seprated_vec.at(0);
inf.at(index).birthDay = slash_seprated_vec.at(1);
inf.at(index).birthYear = slash_seprated_vec.at(2);
++index;
}
}
Then you can use it like this :
int main()
{
std::vector<info> information;
parser("some file", information);
return 0;
}
There you go, your information are presented in information variable.
I have a text file that has the following data for a simple entry/exit system:
where each line has {time_stamp} {name} {door_entry} {status}
time_stamp - number of seconds since some arbitrary start time
name - The workers username
door_entry - door number entered/exited
status - whether they entered or exited the door
The text file is large and has about 10,000 entries similar to this
Question: I'm wondering how I can decompose each line and split each piece of information into a variable. So for example I have the Worker class here:
class Worker
{
std::string staffToken;
int doorEntry;
std::string status;
public:
Employee();
};
I want to solve this problem with an array as well. I know I could use a Vector or a Map but I want to solve this with an array.
I've created an array of pointer objects for the Worker class.
typedef Worker * WorkPtr;
WorkPtr * workers = new WorkPtr[MAX]; //where max is some large constant
for (int i = 0; i < MAX; ++i)
{
workers[i] = new Worker();
}
The goal of this problem I've created is that I simply want to check for any unusual activity in this text file where a Worker has entered or exited multiple times in a row:
you can use this template to split a string with a certain delimiter
template<typename Out>
void split(const std::string &s, char delim, Out result) {
std::stringstream ss;
ss.str(s);
std::string item;
while (std::getline(ss, item, delim)) {
*(result++) = item;
}
}
std::vector<std::string> split(const std::string &s, char delim) {
std::vector<std::string> elems;
split(s, delim, std::back_inserter(elems));
return elems;
}
for example:
ifstream fin("your_file");
while(getline(fin,str))
{
vector<string> res;
res = split(str, ' ');
//your process with res
}
I'm looking to take a somewhat lengthy text file 50 rows by 2 columns, have a user input the file name and read it into a two demensional array. The text file is a combination of organized names (including commas) and numbers.
I can get the console to display the text file itself, but I'm stuck when it comes to orgazing the data into the array. I'm trying to devise a loop code involving getline and find in order for program through sort through the .txt, stop at a comma and record every character before that comma into a location (i.e [0] [0]) of the array. I'm aware that using vectors would be easier, but I'd like to solve this with an array.
Also, there is the issue of reading names (strings) into the array (int).
Please test this code:
#include <vector>
#include <fstream>
#include <string>
#include <sstream>
#include <iterator>
template<typename Out>
void split(const std::string &s, char delim, Out result) {
std::stringstream ss;
ss.str(s);
std::string item;
while (std::getline(ss, item, delim)) {
*(result++) = item;
}
}
std::vector<std::string> split(const std::string &s, char delim) {
std::vector<std::string> elems;
split(s, delim, std::back_inserter(elems));
return elems;
}
int main()
{
std::ifstream file("test.txt", std::ios::binary);
std::string a, b;
int c;
std::vector<std::vector<std::string>> arr;
if (file)
{
while (file >> a )
{
std::vector<std::string> v = split(a, ',');
arr.push_back(v);
}
}
return 0;
}
my test.txt:
m,2
n,4
o,6
p,8
q,10
I want to pass dimension parameters of a matrix class as a char array, I can get the number of dimensions by counting the number of commas written in the parameters but I cant seem to read the numbers in a char as integers.
When I try to convert from char to int I get huge unrelated numbers. How can I read the numbers in a char array as integers?
template <class T>
matrix <T>::matrix (char * dimensions)
{
int nod = 0;
for(int i=0;dimensions[i];i++)
{
if (dimensions[i] == ',') nod++;
}
Number_of_dimensions = nod+1;
//...
}
You can use the following idea, illustrated with a rough pseudo-code snipper:
std::string s = "1234,4556";
//While you still have a string to parse
while (s.length()) {
//Use a comma to delimit a token
std::string delimiter = ",";
//Find the position of the comma or the end of the string
unsigned int comma_pos = s.find(delimiter);
//Find the sub-string before the comma
std::string token = s.substr(0, comma_pos); // token is "1234"
//Find your int
int i = std::stoi(token);
//"Eat" the token, continue
s.erase(0, comma_pos+1);
}
This is a particularly rough example, but the core idea is there: use std::string::substr() to find your sub-string with a comma delimiter, then convert the token to an int.
You also might want to consider looking for several delimiters, such as '\n'.
Split() function splits string by delimiter. In our case delimiter is comma. The number of elements is dimension. Than we convert each element to number using std::stringstream (C++98, or std::stoi in C++11).
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
std::vector<std::string> Split(const std::string &s, char delim)
{
std::vector<std::string> elems;
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, delim))
elems.push_back(item);
return elems;
}
std::vector<int> GetDim(char *dimensions)
{
std::vector<std::string> dim_str = Split(dimensions, ',');
std::vector<int> elems(dim_str.size());
for (size_t i = 0; i < dim_str.size(); ++i) {
std::stringstream ss(dim_str[i]);
ss >> elems.at(i);
}
return elems;
}
int main() {
std::string s = "1234,4556";
std::vector<int> d = GetDim(&*s.begin());
std::cout << "Dimensions: " << d.size() << std::endl;
std::cout << "Values: ";
for (size_t i = 0; i < d.size(); ++i) {
std::cout << d[i] << " ";
}
std::cout << std::endl;
return 0;
}
I suggest you not to use pointer as arguments. Use std::string or std::vector instead. Do not forget const qualifier. So GetDim() can be:
std::vector<int> GetDim(const std::string& dimensions)
{
std::vector<std::string> dim_str = Split(dimensions, ',');
std::vector<int> elems(dim_str.size());
for (size_t i = 0; i < dim_str.size(); ++i) {
std::stringstream ss(dim_str[i]);
ss >> elems.at(i);
}
return elems;
}