read an input file using vectors - c++

I have written a code to read file below but its not working.
Input file:
2 1 16
16 0 0
1 1 1234
16 0 0
1 1 2345
code is:
std::ifstream input_file;
evl_wire wire;
int num_pins,width,cycles,no;
std::vector<int>IP;
while(input_file)
{
input_file >> num_pins;//num_pins=2
if (pins_.size() != num_pins) return false;
for (size_t i = 0; i < pins_.size(); ++i)
{
input_file >> width;//width=1 for 1=0 ,=16 for i=2
if (wire.width != width) return false;
pins_[i]->set_as_output();
}
for (size_t i = 1; i < file_name.size(); i=i+1)
input_file>>cycles;
input_file>>no;
pins_=IP;
}
where std::vector<pin *> pins_; is in gate class and void set_as_output(); is in pin class
2 represent no of pins,1 width of first pin and 16 width of second pin.
here from second line in file 16 is no of cycles pins must remain at 0 0,for next 1 cycle pins must be assigned 1 and 1234 as inputs.

Some parts of your code are almost certainly wrong. Other parts I'm less certain about -- they don't make much sense to me, but maybe I'm just missing something.
while(input_file)
This is almost always a mistake. It won't sense the end of the file until after an attempt at reading from the file has failed. In a typical case, your loop will execute one more iteration than intended. What you probably want is something like:
while (input_file >> num_pins)
This reads the data (or tries to, anyway) from the file, and exits the loop if that fails.
if (pins_.size() != num_pins) return false;
This is less clear. It's not at all clear why we'd read num_pins from the file if we already know what value it needs to be (and the same seems to be true with width vs. wire.width).
for (size_t i = 1; i < file_name.size(); i=i+1)
input_file>>cycles;
This strikes me as the most puzzling part of all. What does the size of the string holding the file name have to do with anything? This has be fairly baffled.

I don't fully understand your code, but I don't see you are opening the input file anywhere. I think it should be:
std::ifstream input_file;
evl_wire wire;
int num_pins,width,cycles,no;
std::vector<int>IP;
input_file.open("name of the file");
if(input_file.is_open())
{
while(input_file >> num_pins) //num_pins=2
{
if (pins_.size() != num_pins) return false;
for (size_t i = 0; i < pins_.size(); ++i)
{
input_file >> width;//width=1 for 1=0 ,=16 for i=2
if (wire.width != width) return false;
pins_[i]->set_as_output();
}
for (size_t i = 1; i < file_name.size(); i=i+1)
input_file>>cycles;
input_file>>no;
pins_=IP;
}
input_file.close();
}

The function I used:
bool input::validate_structural_semantics()
{
evl_wire wire;
std::ifstream input_file;std::string line;
int x[]={1000};
for (int line_no = 1; std::getline(input_file, line); ++line_no)
std::string s; int i=0;
std::istringstream iss;
do
{
std::string sub;
iss >> sub;
x[i]=atoi(sub.c_str());
i++;
}
while (iss);
if (pins_.size()!=x[0]) return false;
for (size_t i = 0; i < pins_.size(); ++i)
{
if (wire.width != x[i+1]) return false;
pins_[i]->set_as_input();
}
for(size_t i=4;i<1000;i++)
{
for(size_t j=0;j<pins_.size();j++)
pins_.assign(x[i-1],x[i+j]);
}
return true;
}
This implementation is using arrays but it didn't work,although there isn't any compling error.

Related

the program should display the last 5 lines of the file, but it does not work with large files

I wrote a program that should print the last 5 lines of a file, but the teacher created a file with a line of 4 GB, and the program broke. How to rewrite a program so that it can work with very large files
a possible solution is to read the file character by character, but I don’t know how to do it
here is the c ++ program code
#include <iostream>
#include <fstream>
#include <string>
using std::ifstream;
using std::cout;
using std::string;
using std::getline;
int main(int argc, char * argv[], char * env[]) {
setlocale(LC_ALL, "");
int i;
string line;
if (argc == 3) {
string filename = argv[1];
ifstream myfile(filename);
string n = argv[2];
int nn = atoi(n.c_str());
string line, buffer[nn];
const size_t size = sizeof buffer / sizeof * buffer;
size_t i = 0;
while (getline(myfile, line)) {
buffer[i] = line;
if (++i >= size) {
i = 0;
}
}
for (size_t j = 0; j < size; ++j) {
cout << buffer[i] << "\n";
if (++i >= size) {
i = 0;
}
}
//return 0;
}
}
The problem must be with big lines in that 4GB file. Your solution buffers (and later drops) every line and at least one of the lines is probably too long to be buffered in the machine you're running, making your program crash.
You should read the file starting from the end counting the number of newlines and stop and output the rest of if when you reach the count of nn + 1. Buffering the last nn lines is not a good option when you need to handle big lines.
Here a snippet of a solution that could help you:
array<char, 64 * 1024> buffer; // 64kb of buffer
size_t nn = atoi(n.c_str());
myfile.seekg(0, ios_base::end);
unsigned int nlcount = 0;
size_t length = myfile.tellg();
size_t oldpos = length;
while (myfile.tellg() > 0) {
size_t newpos = oldpos - min(oldpos, buffer.size());
myfile.seekg(newpos);
size_t rdsize = oldpos - newpos;
myfile.read(buffer.data(), rdsize);
if (!myfile) {
cerr << "failed while looking for newlines\n";
return 1;
}
auto rit = buffer.rbegin() + (buffer.size() - rdsize);
while (rit != buffer.rend() && nlcount <= nn) {
if (*rit == '\n') {
++nlcount;
}
++rit;
}
if (nlcount > nn) {
myfile.seekg(newpos + (buffer.rend() - rit) + 1);
break;
}
oldpos = newpos;
}
This will point the input stream to the exact position where you just need to output the rest of it if nlcount is equal to nn + 1. I recommend you to output it not using buffered lines, but using a fixed sized buffer:
while (myfile.peek() != EOF) {
myfile.read(buffer.data(), buffer.size());
cout.write(buffer.data(), myfile.gcount());
}
Don't use getline() or you will still end up buffering lines and crash when handling long ones.
To remove buffer dependency one way is to read the file from the end backward to reach the number of lines you want. 5 is hard-coded here but you can pass it as a parameter.
std::ifstream fileReader("test.txt", std::ios_base::ate );
std::string currentLine;
long length;
int lines;
char c = '\0';
if( fileReader )
{
length = fileReader.tellg();
for(long i = length-2; i > 0; i-- )
{
fileReader.seekg(i);
c = fileReader.get();
if( c == '\r' || c == '\n' )
{
lines++;
if (lines == 5)
break;
}
}
while(fileReader)
{
std::getline(fileReader, currentLine);
std::cout << currentLine << std::endl;
}
}

extraction of letters at even positions in strings?

string extract(string scrambeledword){
unsigned int index;
string output;
string input= " ";
for (index=0; index <= scrambeledword.length() ; index++);
{
if (index%2==0)
{
output+=input ;
cout << output;
}
}
return output;}
I want to extract the even numbered indexed letters from the 40 letter long word inputted by users. does this make sense? i have not taken arrays yet and do not want to include them.
Problems:
1. You have a ; after your for loop, the loop body is never run.
2. <= is wrong here since scrambeledword.length() is out of range. Use != or < instead.
3. You need to either assign something to input before adding it to output or get rid of it altogether.
4. As #Aconcagua pointed out, it is worth noting that I removed your declaration of index from the function scope and added it only to the for loop scope. If you also considered doing so, compiler would throw an error (since it'd be undeclared outside of the scope of for) and you'd be noted about the ; problem.
Fixed version:
string extract(const string &scrambeledword){ // copying strings is expensive
// unsigned int index; // obsolete
string output;
// string input= " "; // obsolete
for (size_t index = 0; index != scrambeledword.length(); ++index) // `<=` would be wrong since scrambeledword.length() is out of range
{
if (index % 2 == 0)
{
output += scrambeledword[index];
// cout << output; // obsolete. If you just want the characters, print scrambeledword[index]
cout << scrambeledword[index];
}
}
cout << endl; // break the line for better readability
return output;
}
Your code won't run the block under the for because there is a ; at the end of the line. That means the for runs without block. Basically it will count to the length of the given word.
In the for index <= scrambeledword.length() can cause an out of bound exception because you can index out of the string-array. Use index < scrambeledword.length() instead.
This can be a good solution for the problem:
string extract(const string& scrambeledword)
{
string output;
for (unsigned int index = 0; index < scrambeledword.length(); index++)
{
if (index % 2 == 0)
{
output += scrambeledword[index];
}
}
return output;
}
auto str = "HelloWorld"s;
int i = 0;
for_each(str.cbegin(), str.cend(), [&i](char const & c) { if (i++ % 2 == 0) cout << c; });
output: Hlool
You could go with something like this:
for(int i = 0; i < scrambleword.length(); i+=2){
output += scrambleword.at(i);
}

loading values of a text file into an array

The text file I generate from an graph generator is similar to:
:0 0|- 1|82 2|72
:1 0|87 1|- 2|74
:2 0|86 1|53 2|-
These are supposed to represent node and the distance to them.
line 1 is :1 1|- 2|82 3|72
it is saying the distance from node 0 to node 0 (0|-) is - (infinity)
and from node 0 to node 1 (1|82) is 82
and from node 0 to node 2 (2|72) is 72
But I want to load the values into a 2d array.
the array above should be
Graph[0][0] = -
Graph[0][1] = 82
Graph[0][2] = 72
etc...
I'm just not sure how when I read in the txt file to catch the :0 & :1 & :2 then separate 1|5.
any help would be great!
Thanks!
One problem is those - characters. If you replace them with 0, then you can use something like the following code:
// Open the file like this:
// std::ifstream fin ("whatever.txt");
char dummy;
for (int i = 0; i < n; ++i)
{
int x, d;
fin >> dummy >> x; // read ":1", etc.
assert (dummy == '=');
assert (x == i + 1);
for (int j = 0; j < n; ++j)
{
fin >> x >> dummy >> d; // read "2|42", etc.
assert (dummy == '|');
assert (x == j + 1);
Graph[i][j] = d;
}
}
All those asserts are there to make sure the redundant data in the file are as they are supposed to be. And don't forget to replace all '-'s with '0's.
You can see what I'm doing there. I'm reading the integers normally, and reading a character when the ':' and '|' symbols are.
A plain C approach which you may re-write as C++ or just use as-is. After all, this doesn't look like C++ critical code.
Note the use of a maximum length for fgets (granted, a C++ string could work better here) and a #define for "infinity", since you cannot store this value in a sensible way. It assumes all of your distances are positive, and that your data is as you have shown (i.e., no surprises such as huge numbers > MAX_INT, or inconsistent spacing).
The usual C++ approach of cin does not work well here, and neither does fscanf, since in both cases you need to read one character, determine if it is an - and if it is not re-read itself and any digits following it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_DATA_LENGTH 120
#define DIST_INFINITY 0xFFFFFFFF
unsigned int Graph[10][3];
int main (void)
{
FILE *fp;
char input_string[MAX_DATA_LENGTH], *token_ptr;
int graph_counter = 0, i;
fp = fopen ("graph.txt", "rt");
if (!fp)
{
printf ("data not found\n");
return -1;
}
do
{
if (fgets (input_string, MAX_DATA_LENGTH, fp) == NULL)
break;
token_ptr = input_string;
for (i=0; i<3; i++)
{
token_ptr = strchr (token_ptr, '|');
if (!token_ptr || !token_ptr[1])
break;
token_ptr++;
if (*token_ptr == '-')
Graph[graph_counter][i] = DIST_INFINITY;
else
Graph[graph_counter][i] = strtoul (token_ptr, NULL, 10);
token_ptr++;
}
if (i < 3)
break;
graph_counter++;
} while (1);
for (i=0; i<graph_counter; i++)
printf ("Graph[%d] = %u %u %u\n", i, Graph[i][0], Graph[i][1], Graph[i][2]);
return 0;
}

C++ Benford's Law program.

So I have to write a program to
=> analyze three different data files, and try to confirm Benford’s law. You will create a console application that opens each file, counts the number of values that start with ‘1’, ‘2’, ‘3’, etc., and then outputs the percentages of each digit.
I think I have it down but I keep getting an error in Dev C++.
int analyzeData(string fname) {
ifstream infile(string fname);
int tmp,count = 0;
float percents[9];
int nums[9] = { 0 };
if(!infile.good())
return 1;
while(!infile.eof())
{
infile >> tmp;
tmp = first(tmp);
if(tmp > 0)
{
nums[tmp - 1] ++;
count++;
}
}
It's saying that 'good', 'eof', and 'infile' are non-class type?
I don't know what that means!
Help would be much appreciated! thanks!
Firstly
ifstream infile(string fname);
should be
ifstream infile(fname);
Your version was a function prototype not a declaration of a variable.
Secondly this is the wrong way to loop to the end of a file
while (!infile.eof())
{
infile >> tmp;
...
}
this is the right way
while (infile >> tmp)
{
...
}
This must be the single most common error we see here. eof does not do what you think it does, and anyone who told you to write while (!infile.eof()) is just wrong.
Finally first(tmp) is not the correct way to get the first digit from an integer. You'll have to work a little harder than that.
Rather than read the input as integers, read the lines as strings, the grab the first digit from the string. Or you could read as an integer and then divide tmp by 10 until the result is < 10.
Make you life a little easier, and use the digit as an index into the array. You need to be able to index values 1 - 9, so you would need to declare your array a little bigger. ditto for percents.
int nums[9] = { 0 }; // works, but do less work
float percents[9];
int nums[10] = { 0 }; // do this, then you can us the digit to index nums[]
float percents[10];
You don't need the guard for tmp > 0, because you have room for all 10 digis,
//if( tmp > 0 )
//{
...
//}
You don't need to subtract one from tmp,
int analyzeData(string fname)
{
ifstream infile(fname);
int tmp,count = 0;
float percents[10];
int nums[10] = { 0 };
if(!infile.good())
return 1;
while(infile >> tmp)
{
tmp = first(tmp);
{
nums[tmp] ++;
count++;
}
}
if(count<1) count=1; //avoid division by zero
for( tmp=1; tmp<10; ++tmp )
cout<<tmp<<":"<<nums[tmp]<<",pct:"<<(nums[tmp]*1.0)/count<<eol;
}

how to read characters and integers from a file?

So I have a data file that looks something like this:
x + y + z
30 45 50
10 20 30
The only characters I needed was the operators, so '+' '+' I was able to use file.get() to successfully get those characters and put them in an array. Problem is I need to get the next line of numbers, and assign them to the values x , y z . I know I cant use .get() , I would have to use getline. Will i have to eliminate the file.get() and use getline instead for first part also?
I looked at some of the questions posted on here but none of them were quite like mines. Note I'm actually going to be using these values for another part of my program, just used cout to see if my values were being read correctly
Here's my previous code:
main(int argc, char *argv[])
{
int a=0;
int n;
fstream datafile;
char ch;
pid_t pid;
int a, b, c, result;
string line;
datafile.open("data1.txt");
if(datafile)
{
for(int i=0; i <9; i++)
{
datafile.get(ch);
if (ch == '*'||ch == '/'||ch == '+'||ch == '-')
{
operations[a] = ch;
cout<<operations[a];
a++;
}
}
}
else
cout<<"Error reading file";
}
So this is how I was getting the first line of the file in the beginning. It worked like I wanted it to, may have not been the nicest coding but it worked. Nevertheless I tried to get the rest of the file, this time using getline, but instead of getting the numbers I was getting a bunch of random gibberish/numbers. I know if I use getline, the first line cannot be in my loop. I know this is how I would get the numbers.
while(getline(datafile, line))
{
istringstream ss(line);
ss >> x >> y >> z;
cout<<x<<""<<y<<""<<z;
}
Would the following make sense for the first line, or am I missing something:
string input;
std::getline(datafile, input)
for (int i = 0; i < input.size(); i++)
if (input[i] == '+' || ...)
{
operations[a] = input[i];
a++;
}
If you don't want to use getline, you could simply read the entire file stream (note that the bool is a rather naive way to handle the problem, I'd recommend something more elegant in your actual code):
bool first = true;
string nums;
int lines = 0;
vector<vector<int>> numlines;
vector<int> topush;
while (!datafile.eof())
{
char ch = datafile.get()
if (ch == 12 && first) //I don't know if '\n' is valid, I'd assume it is but here's the sure bet
first = false;
else if (first && (ch == '+' || ...))
{
operator[a] = ch;
a++;
}
else if (!first && (ch >= '0' && ch <= '9'))
{
if (!(datafile.peek() >= '0' && datafile.peek() <= '0'))
{
numlines[lines].push_back(atoi(nums.c_str());
nums.clear();
if (datafile.peek() == 12)
{
numlines.push_back(topush);
lines++;
}
}
else
nums = nums + ch;
}
Honestly, I can't be sure the above will work exactly right, I'd recommend you just modify your code to use getline exclusively. You'll need to add #include to get atoi.
Add this to your code:
while(!datafile.eof()){
string s;
getline(datafile, s);
istringstream in(s);
string tmp;
while(in >> tmp){
int i = stoi(tmp)
//Do something with i....
}
}