I'm wondering if anybody can help me solving the following problem in C++:
I have a file where some time there is missing data i.e there are two consecutive TABs, then I need to transform the second TAB into "-999999" or "0" for example.
here is how the file looks like
i_1 i_2 i_3 i_4 i_5
j_1 12 14 16
j_2 11 17 25
j_3 44 51 65
I want to compute the mean of the elements on the first row i.e( 12,14 and 16) as:
sum+=tab[i][j];
mean = sum/5; (considering empty spaces =0)
thank you
#include <boost/algorithm/string/split.hpp>
#include <iostream>
#include <fstream>
#include <vector>
#include <list>
bool const compress_tokens = false;
bool const table_width = ...;
std::ifstream inp("filename");
// parsed grid
std::list<std::vector<std::string> > table;
std::string strbuf;
std::vector<std::string> vecbuf;
while(inp.getline(strbuf))
{
vecbuf.clear();
boost::split(vecbuf, strbuf, boost::is_any_of("\t"), compress_tokens);
assert(vecbuf.size() == table_width);
table.push_back(vecbuf);
}
Related
I have written the following code. What I did is this
opened a file "Numbers.dat" and asked input from console
then separated the numbers in separate even and odd files
#include <fstream>
#include <iostream>
int main() {
std::ofstream numWrite("Numbers.dat");
int temp;
while(std::cin>>temp){
numWrite<<temp<<std::endl;
}
numWrite.close();
std::ofstream even("Even.dat"), odd("Odd.dat");
std::ifstream num("Numbers.dat");
while(num){
num>>temp;
if(temp%2==0)
even<<temp<<std::endl;
else
odd<<temp<<std::endl;
}
num.close();
even.close();
odd.close();
return 0;
}
I used newlines after every input, therefore I am having the extra newline in Numbers.dat file and when my program is reading that, it is giving an extra output to the even/odd files.
I can eliminate them by either removing newline from the numbers.dat file, or some check on the other code.
But I am unable to do that, please help!
Or if there is a better way, tell me that too!
Inputs:
1 2 3 4 5 6 7 8 9 10 a
OUTPUTS:
even.dat
2
4
8
10
10
odd.dat
1
3
5
7
9
Problem is this:
while(num){
num>>temp;
This should be done this way:
while(num>>temp){
For details see eof() bad practice?
Fancy way to address this is, by use of iterators and std::partition_copy
#include <fstream>
#include <iostream>
#include <iterator>
#include <algorithm>
int main() {
std::ifstream in("Numbers.dat");
std::ofstream even("Even.dat");
std::ofstream odd("Odd.dat");
std::partition_copy(
std::istream_iterator<int>{in}, {},
std::ostream_iterator<int>{even, " "},
std::ostream_iterator<int>{odd, " "},
[](auto x) { return x % 2 == 0; });
return 0;
}
https://godbolt.org/z/z4qcErPWd
In my program first I read a file into a vector of strings called rosterList:
100
95
0
-1
110
80
90
-1
120
80
75
-1
130
60
55
-1
This step is successful. My goal is to create a vector of Student objects using the data above. Constructor accepts 3 strings as parameters:
Student::Student(string id,string g1,string g2)
To do that, the program loops through this vector of strings line by line, if the line converted to integer is greater or equal to 100, it is an id, then dynamically create a new Student object by passing the id (current line) and the next 2 lines as parameters, and add the object to the vector studentRecords
for (vector<string>::iterator it = rosterList.begin(); it<rosterList.end();it++){
if(stoi(*it)>=100 || it == rosterList.begin()){ // error
studentRecords.push_back(
Student(*it,*(it+1),*(it+2)) // dynamically push
);
}
}
And there is a dynamic error:
libc++abi.dylib: terminating with uncaught exception of type
std::invalid_argument: stoi: no conversion
I looked it up online, the error comes from stoi not be able to convert. Where in the program goes wrong?
Either you have to read your file correctly....or
If you are not confident on file data, do a validation for numeric content.
Below is code sample.
Any junk that you read other than numeric content in your file will cause failure.
Below code compiles and for your idea. You can optimize it.
#include <iostream>
#include <cstring>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
std::vector<string> rosterList;
bool is_numeric(string strin)
{
char const *str = strin.c_str();
return all_of(str, str+strlen(str),
[](unsigned char c) { return ::isdigit(c); });
}
int main(int argc, char *argv[])
{
rosterList.push_back("100");
rosterList.push_back(" ");
rosterList.push_back("140");
rosterList.push_back("180");
for (vector<string>::iterator it = rosterList.begin(); it<rosterList.end();it++){
if(is_numeric(*it) && (stoi(*it)>=100 || it == rosterList.begin())){ // error
std::cout<<stoi(*it)<<std::endl;
}
}
}
One problem I see in your code is that you're accessing it+1 and it+2 also when it is the last 2 positions of the vector. This will try to access a pointer that doesn't exist as this points to after rosterList.end().
You will have to test if it+1 and it+2 are < than rosterList.end() before using them.
I'm looking for some help piping a file (16-bit signed little endian integers raw data) from the command line to my program:
cat rawdata.dat | myprogram
The code works pretty well on Linux, 512 bytes are transformed into 256 ints per loop turn.
If I compile it with MinGW on Windows, only the first 76 values will be transformed correctly. Also the program stops after the first while loop.
Does anybody know what I am doing wrong? I am using Windows 7 64bit + MinGW compiler.
Code:
#include <iostream>
using namespace std;
int main()
{
int BUF_LEN = 512;
char buf[BUF_LEN];
while(!cin.eof())
{
cin.read(buf, BUF_LEN);
int16_t* data = (int16_t*) buf; //to int
for(int i=70;i<85;i++)
{
cout << i << " " << data[i] << endl;
}
}
return 0;
}
Testfile: http://www.filedropper.com/rawdata
Correct values would be:
70 -11584
71 13452
72 -13210
73 -13331
74 13893
75 10870
76 9738
77 6689
78 -253
79 -1009
80 -16036
81 14253
82 -13872
83 10020
84 -5971
TL;DR:
Fix? There isn't one. You have to force cin into binary mode. I think to do that you'd have to close and reopen cin, and I can only see that ending badly.
Real solution is don't do this. Open the file normally with
std::ifstream in("rawdata.dat", std::fstream::binary);
Rest of the story:
Suspected that this would be some sort of gooned binary translation, so I put together a quick bit of code to see what's going on in the file.
#include <iostream>
#include <fstream>
using namespace std;
#define BUF_LEN 512
int main()
{
ifstream in("rawdata.dat");
char buf[BUF_LEN];
int16_t test;
int count = 0;
while(in.read((char *)&test, sizeof(test)))
{
cout << count++ << ":" << in.tellg() << ":" << test << endl;
if (count == 85)
{
break;
}
}
return 0;
}
Important output (int16 number:position in file:number read
0:358:0
First value returned is actually at position 358. Not sure why.
75:508:10870
76:510:9738
77:909:8225
78:911:11948
Wooo-eee! Look at that position jump from 510 to 909. Nasty. 510 would be right around the end of the buffer, but it doesn't look like the buffer is being respected.
My understanding is istream::read should be totally unformatted, just a dumb copy of input stream to provided buffer so I have no idea why this happens. Maybe windows is just weird.
Addendum
Thomas Matthews probably has the right idea, secret Windows control characters, but 510 is a rather innocuous comma. Why go bonkers over a comma?
This one finally solved my problem:
Read binary data from std::cin
Just add the following lines to your code if you are using MinGW:
#include <io.h>
#include <fcntl.h>
#include <fstream>
_setmode(_fileno(stdin), _O_BINARY);
Say I have an input file text.txt that looks like this:
12.4 Mass kg
32 acceleration m/s^2
21 volume m^3
I would like to get the first number in each row and use it as a variable and ignore the rest of the line.
Thanks!
Try the following
#include <limits>
#include <iostream>
#include <fstream>
//...
double d;
while ( file_stream >> d )
{
file_stream.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
}
Basically, I want to make a simple function for a larger project, this will actually end up as a Header file that handles all my inventory. Any who, I just want it to be able to read/pull/input the Data from a .csv file format... Or I can even do a .txt if it is easier to make this function work, As long as I can open it up in MS Excel and edit the items and add new items, when the function is ran it will Open up "Example.csv" and for example, the function will look for the cell in Column 1 - 'sSwordName' and it will pull the data in the row FOLLOWING that cell, excluding that first column completely in all the inputs essentially... It will group it together, or what ever it may have to do in order to ASSIGN it to that Variable. Please see Code.h (Comments) to see my questions about my source code.
Code.h -
#include "stdafx.h"
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <vector>
using namespace std;
char sSwordName[100][25] = {};
int sSwordLvlR[100] = {};
vector<string> split_at_commas(const string & row)
{
vector<string> res;
istringstream buf(row);
string s;
while (getline(buf, s, ','))
res.push_back(s);
return res;
system("pause");
}
/* Question 1: Where & How do I properly add 'ifstream wInv("Example.csv");' in order to Load the CSV file it is reading? */
/* Question 2: Line 38 & 46. */
/* Question 3: Line 39 & 47 */
int main()
{
int i = 1;
string line;
string row;
vector<string> values = split_at_commas(line);
if (values[0] == "sSwordName")
{
for(int i = 1; i < values.size(); ++i);
{
/*int i error: Object must have a pointer-to-object type*/
sSwordName[100][25][i - 1] = /*How do I convert string to char?*/(vector[i]);
}
}
else if (values[1] == "sSwordLvlR")
{
for(int i = 1; i < values.size(); ++i);
{
/*int i error: Object must have a pointer-to-object type*/
sSwordLvlR[i - 1] = /*How do I Convert string to int?*/(vector[i]);
}
}
}
/* Question 4: Is there anything else that is wrong in this? If so, how would I fix it */
Example.csv -
sSwordName,Wooden Shortsword,Bronze Shortsword,Iron Shortsword,Steel Shortsword,Titanium Shortsword
sSwordLvlR,1,3,5,6,10
More Information On The CSV:
sSwordName,Wooden Shortsword,Bronze Shortsword,Iron Shortsword,Steel Shortsword,Titanium Shortsword
sSwordLvlR,1,3,5,6,10
^Is not the ONLY way I can format it, for convenience I can do something like this (Below, E2.csv). If it is easier to make the function, function.;
sSwordName,"Wooden Shortsword","Bronze Shortsword","Iron Shortsword","Steel Shortsword","Titanium Shortsword"
sSwordLvlR,"1,","3,","5,","6,","10,"
I can even format it in this way;
sSwordName,"{"Wooden Shortsword","Bronze Shortsword","Iron Shortsword","Steel Shortsword","Titanium Shortsword"};
sSwordLvlR,"{1,3,5,6,10};"
Once again, I greatly appreciate any help. I thank you in Advanced!
-Leaum