Read complex numbers (a+bi) from text file in C++ - c++

i want to read an array of complex numbers (in a+bi form). There are several suggestions I found on the internet, however those methods only result the real part, while the imaginary part is always 0. And infact the real part of the next number is the imaginary of the previous number.
For example, I have an text file as follow:
2+4i
1+5i
7+6i
And here is a suggestion for reading complex data
int nRow = 3;
std::complex<int> c;
std::ifstream fin("test.txt");
std::string line;
std::vector<std::complex<int> > vec;
vec.reserve(nRow);
while (std::getline(fin, line))
{
std::stringstream stream(line);
while (stream >> c)
{
vec.push_back(c);
}
}
for (int i = 0; i < nRow; i++){
cout << vec[i].real() << "\t" << vec[i].imag() << endl;
}
while (1);
return 0;
And the output result is:
2 0
4 0
1 0
Is there a proper way to read a+bi complex numbers from text file? Or do I have to read the data as a string, and then process the string to extract and convert it back to complex numer?
Thanks !

One option is to read separately the real and imaginary part in 2 ints, and the sign into a char, then emplace_back into the complex vector, like
int re, im;
char sign;
while (stream >> re >> sign >> im)
{
vec.emplace_back(re, (sign == '-') ? -im : im);
}
Here sign is a char variable that "eats" up the sign.

FILE *fp;
char line[80];
int a, b;
if ((fp = fopen("filename", "r") != NULL)
while (fgets(line, 80, fp) != NULL) {
if (sscanf(line, "%d + %di", &a, &b) == 2)
/* do something with a and b */
else
fprintf(stderr, "Not in a+bi form");
}

Your requirement (the format of input you seek) does not correspond to the method you are using to read it. The default streaming of a complex is the real and the imaginary part separated by spaces and in brackets - the sign between is not mandatory, and the trailing i is not required.
The obvious way to parse for input you seek is to read the real part, read a character, check if the character is a signed (+ or -) and ignore spaces, then read the imaginary part. That is trivial with istreams.

int real[10] = { 0 };
int imaginary[10] = { 0 };
FILE *lpFile = fopen("filename" "rt"); // Open the file
for (int i = 0; i < 10; i++) {
fscanf(lpFile, "%d+%di", &real[i], &imaginary[i]); // Read data 10 times
}
fclose(lpFile); // Close the file
This example code will read 10 complex numbers from a file.

Related

How to read binary data from file after read sucessfully the ascii header in the file

I am trying read the Netpbm image format, following the specification explained here. The ascii types for the format (which have P1, P2 and P3 as magic number), I can read without problems. But I have issues reading the binary data in these files (whose with P4, P5 and P6 as magic number) - the header for the file (which is ascii) I am able to read without problem.
In the link, it is stated that:
In the binary formats, PBM uses 1 bit per pixel, PGM uses 8 or 16 bits
per pixel, and PPM uses 24 bits per pixel: 8 for red, 8 for green, 8
for blue. Some readers and writers may support 48 bits per pixel (16
each for R,G,B), but this is still rare.
with this, I try use this answer to read the data, bit by bit, and got this code:
if(*this->magicNumber == "P4") {
this->pixels = new Matrix<int>(this->width, this->height);
vector<int> p;
while(getline(file, line_pixels)) {
if(line_pixels.size() > 0 && line_pixels.at(0) != '#') {
string byte;
stringstream ss(line_pixels);
while(getline(ss, byte)) {
unsigned char c = (unsigned char)byte.at(0);
for(int x=0; x != 8; x++) p.push_back( (c & (1 << x)) != 0 );
}
}
}
int count = 0;
for(int i=0; i<height; i++) {
for(int j=0; j<width; j++) {
this->pixels->set(i, j, p[count++]);
}
}
}
but when I try read the image named as sample_640×426.pbm in this link, I should get this result:
but I am getting this result instead:
For the binary format for PGM and PPM images, when I try open the image, I got a segmentation fault error when I try increment count at some point in the execution of the loop. I think somehow the size of vector<int> p is ending bigger than the expected product width x height.
the code for the PGM format:
if(*this->magicNumber == "P5") {
this->pixels = new Matrix<int>(this->width, this->height);
vector<int> p;
while(getline(file, line_pixels)) {
if(line_pixels.size() > 0 && line_pixels.at(0) != '#') {
string number;
stringstream ss(line_pixels);
while(getline(ss, number)) {
unsigned char data = (unsigned char)number.at(0);
p.push_back((int)data);
}
}
}
int count = 0;
for(int i=0; i<height; i++) {
for(int j=0; j<width; j++) {
this->pixels->set(i, j, p[count++]);
}
}
}
the code for the PPM format:
if(*this->magicNumber == "P6") {
this->pixels = new Matrix<struct Pixel>(this->width, this->height);
vector<int> p;
while(getline(file, line_pixels)) {
if(line_pixels.size() > 0 && line_pixels.at(0) != '#') {
string byte;
stringstream ss(line_pixels);
while(getline(ss, byte)) {
unsigned char data = (unsigned char)byte.at(0);
p.push_back((int)data);
}
}
}
int count = 0;
for(int i=0; i<height; i++) {
for(int j=0; j<width; j++) {
struct Pixel pixel;
pixel.r = p[count++];
pixel.g = p[count++];
pixel.b = p[count++];
this->pixels->set(i, j, pixel);
}
}
}
Anyone can give a hint of what I am doing wrong here?
while(getline(file, line_pixels)) {
std::getline reads from the input stream until a newline character is read.
A file is a file. It contains bytes. Whether you believe the file contains text, or binary, is purely a matter of interpretation.
Text lines are terminated by a newline character. That's what std::getline does: it reads bytes from a file until it reads a newline character. Whatever gets read, goes into the std::string parameter.
This would be very confusing if your intent is to read some binary data, like an image. A byte containing the same value as a newline character can occur naturally in a binary file like an image file, representing the appropriate pixel values. Using std::getline to read non-textual data always ends in tears.
This would only make sense in one situation: if you already know, in advance, the the binary data you intend to read here ends with a byte that just happens to be the newline character, and that newline character appears nowhere else.
But, of course, in an image file, you have no such guarantees, whatsoever.
When reading image data you are typically expected to read a specific amount of bytes from the file.
Here, you know, in advance, the size of your image and its format. Based on that you can calculate using a simple mathematical formula how many bytes you expect to read.
And that happens to be what std::istream's read() method does: read the specific number of bytes from a file. This link provides more information.
You need to replace all shown code that improperly uses getline with one that uses read().

File Handling in C reading multiple chars

abort action islemi durdur(MS)
abort sequence durdurma dizisi(IBM)
I have a file.txt like above. I want to read this from the file.txt separately. Besides the file.txt I got 2 more turkce.txt and ingilizce.txt
Here is what I want to do :
I want to read from file.txt and separate the words English and Turkish. After that ingilizce.txt become like this
abort action
abort sequence
and turkce.txt like this
islemi durdur(MS)
durdurma dizisi(IBM)
Also, I have multiple columns and 5127 rows. Column numbers can changes each and every row.
Here is a pic of some part of my file.txt
http://i59.tinypic.com/33m0iu8.png
Thank you for your answers.
Update : I solved the problem. The difference between left column's starting of first letter and right column's starting of firs letter are same and it equals 37.
So I use
FILE* fp = fopen("file.txt","r");
char s[256];
fgets(s, 37 , "fp);
You don't say it explicitly, but your file has two fixed-width columns, which you want to separate.
A substring of a string str from a fixed index i to the end can be expressed with pointer arithmetic: str + i or &str[i]. Strings that are not zero-terminated (like your first column) can be printed by specifying a length with printfs precision field, e.g. printf("%.*s", len, str).
A quick and dirty way to print your two columns is:
char line[80];
int col = 36;
while (fgets(line, sizeof(line), in)) {
fprintf(en, "%.*s\n", col, line);
fprintf(tr, "%s", line + col);
printf("\n");
}
This method has some drawbacks: It will print garbage if the string is shorter than your separation width, i.e. if the right column is empty. It also prints the column padding spaces for the left column, which looks untidy. So let's write a function that splits the strings nicely, which we can call like so:
while (fgets(line, sizeof(line), in)) {
char *stren, *strtr;
split_at(line, &stren, &strtr, 36);
fprintf(en, "%s\n", stren);
fprintf(tr, "%s\n", strtr);
}
The function looks like this:
void split_at(char *line, char **left, char **right, int col)
{
char *trim = line;
char *p = line;
*left = line;
*right = line + col;
while (p < *right) {
if (*p == '\0') {
*right = p;
break;
}
if (!isspace(*p)) trim = p + 1;
p++;
}
*trim = '\0';
trim = p;
while (*p) {
if (!isspace(*p)) trim = p + 1;
p++;
}
if (trim) *trim = '\0';
}
This should work for your example data. It will also work for empty left or right columns. It will not work if there is no space between the left and right columns, i.e. when the left and right art are pasted together.
This method will also work only if the code points of the strings have the same length. You haven't said which encoding you use for your data. If you use ISO-8859-9, you will be okay. If you use UTF-8, all non ASCII-codepoints, i.e. the Turkish special characters, will be represented by more than one byte. What looks like a fixed-width column doesn't have a fixed width in its memory representation.
That said, you should be safe as long as your English text is in the left column. English text is made up of only ASCII characters unless you have fancy formatting with typographic quotation marks or some such.
There could be better solutions but here is simple one.
#include <iostream>
#include <fstream>
int main()
{
std::ifstream inFile("file.txt");
std::ofstream outFileT("turkce.txt", std::ios::app);
std::ofstream outFileE("ingilizce.txt", std::ios::app);
std::string a;
std::string b;
for (int i = 0; i < 2; i++) {
inFile >> a >> b;
outFileE << a + " " + b + "\n";
inFile >> a >> b;
outFileT << a + " " + b + "\n";
}
}
I assumed you have two lines but you can determine lines count in the file first.

Read first n letters from file to a string?

I'm quite new with programming, and now I'm doing an exercise where I should use a cycle to read 25 first symbols from the file, which contains a string of 25 letters (+spaces if the name is shorter than 25) and two numbers. Example:
Whirlpool machine 324 789.99
as I imagine it should look something like this:
ifstream info("Information.txt");
string str;
int a;
double b;
for(int i = 0; i < 25; i++)
{ // some kind of code to get first 25 symbols into a string.
}
info >> a >> b;
And I just can't seem to find the right code to get 25 characters straight to string. Any suggestions?
An easy way is to use read() to read given number of characters:
int length = 25; // num of chars you want to read
str.resize(length, ' '); // reserve spaces
char* begin = &*str.begin();
info.read(begin, length); // <- read it here
You can use the std::copy_n() algorithm with stream buffer iterators:
std::string str;
std::copy_n(std::istreambuf_iterator<char>(info.rdbuf()),
25, std::back_inserter(str));
An approach that you might be more comfortable with is using get() with a for() loop:
for (char c; str.size() != 25 && info.get(c); )
str += c;
Given the context, I'd read the entire line into a string, using
std::getline, and then extract the substring. Something like:
std::string line;
while ( std::getline( info, line ) ) {
std::string header = line.substr( 0, 25 );
// and later...
std::istringstream rest( line.substr( 25 ) );
int a;
double b;
rest >> a >> b;
// ...
}
In general, when reading line oriented input, read the line,
then use a std::istringstream to parse it. Or, if there are
parts you can use "as is" (as is the case here), use them as is.

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;
}