A complex number is a number that can be expressed in the form a + bi
, where a
and b
are real numbers and i
is the imaginary unit, satisfying the equation i*i=−1
. In this expression, a
is the real part and b
is the imaginary part of the complex number.
From wikipedia
The following code, will open a file where each line contains one complex number, read the number and store it into the appropriate variables.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
const char *filename = argv[1];
FILE *fin = fopen(filename, "r");
// Making sure we managed to open the file
if (fin != NULL) {
//Initially this pointer will hold the whole line, eventually the data for the second Component will be removed
char *first_value = NULL;
size_t length_of_buffer = 0;
ssize_t bytes_read;
// Read Line by line until end of file:
// If *line is set to NULL and *length_of_buffer is set 0 before the call, then getline() will allocate a buffer for storing the line.
// This buffer should be freed by the user program even if getline() failed.
while ((bytes_read = getline(&first_value, &length_of_buffer, fin)) != -1) {
printf("Data = '%s' : Length = %zu\n", first_value, bytes_read);
// Create char string to store the second Component
char *second_value;
// We are a bit wasteful here but it makes the code simpler
second_value = (char *) malloc(bytes_read * sizeof(char));
// Create Imaginary flag to distinguish real values from imaginary values - One for each Component
char imaginary_flag[2] = {0, 0};
// Initialize Iterators
// i: for pointing to characters of current line
// j: for pointing to characters in first Component
// k: for pointing to characters in second Component
int i, j = 0, k = 0;
// Flag to indicate that first character if the first Component was found - This helps distinguish between first and second Component
char met_a_number = 0;
// Flag to indicate first Component ends and we should process the second Component
char copy_to_second_value = 0;
// To store the previous character value, we use it to check that when a sign is found, it does not belong to an exponential
char previous_character = '\0';
for (i = 0; i < bytes_read; i++) {
// Initialize current character being processed/evaluated from the line
const char current_character = first_value[i];
// Find the 'j' character that shows that this number is imaginary, then drop the character
if (current_character == 'j') {
if (copy_to_second_value == 0) {
// First Component is the imaginary part
imaginary_flag[0] = 1;
} else {
// Second Component is the imaginary part
imaginary_flag[1] = 1;
}
continue;
}
//We check that the current character is useful to us
if (!(current_character == ' ' || current_character == '(' || current_character == ')')) {
// If current character still part of first Component [based on flag]
if (copy_to_second_value == 0) {
// Check when second Component begins
// When we find one of the sign characters and it is not part of an exponential, then we switch to the second Component
// Exclude if previous character was "e" because after "e" a sign is followed
if (current_character == '-' || current_character == '+') {
if (met_a_number == 1 && previous_character != 'e') {
// Update Flag to indicate that second Component/Value begins
copy_to_second_value = 1;
// Terminate first Component/Value of current Line
first_value[i] = '\0';
second_value[k++] = current_character;
} else {
// Update First Component with the current character value
first_value[j++] = current_character;
}
}
// If current character still part of the first Component
else {
// Update First Component with the current character value
first_value[j++] = current_character;
// A valid character of a number was found, so we are processing a number.
// If this is the first time it happens, we are processing the first Component
met_a_number = 1;
}
}
// If current character part of second Component [based on flag]
else {
second_value[k++] = current_character;
}
}
// If current character belongs in one of the garbage characters
else {
// If current character is garbage number and we already met a number
// then we start copying to the second Component
if (met_a_number == 1) {
copy_to_second_value = 1;
first_value[i] = '\0';
}
}
// Store current_character before reading the next
previous_character = current_character;
}
// Properly terminate first Component
if (first_value[j - 1] == '\n') {
first_value[j - 1] = '\0';
} else {
first_value[j] = '\0';
}
// Properly terminate second Component
second_value[k - 1] = '\0';
// To store the first and second Components in float format
double numbers[2];
// Convert to float and Print first Component
sscanf(first_value, "%lf", &(numbers[0]));
printf("%.f = '%s' is imaginary = %s\n", numbers[0], first_value, imaginary_flag[0] == 0 ? "FALSE" : "TRUE");
// Convert to float and Print second Component if it exists
if (copy_to_second_value == 1) {
sscanf(second_value, "%lf", &(numbers[1]));
printf("%.f = '%s' is imaginary = %s\n", numbers[1], second_value, imaginary_flag[1] == 0 ? "FALSE" : "TRUE");
}
free(second_value);
double real = 0, imaginary = 0;
if (copy_to_second_value == 1) {
if (imaginary_flag[0] == imaginary_flag[1]) {
fprintf(stderr, "Invalid input line.\n");
if (imaginary_flag[0] == 0) {
fprintf(stderr, "None of the components is imaginary\n");
} else {
fprintf(stderr, "Both components are imaginary.\n");
}
continue;
}
if (imaginary_flag[0] == 0) {
real = numbers[0];
imaginary = numbers[1];
} else {
real = numbers[1];
imaginary = numbers[0];
}
} else {
if (imaginary_flag[0] == 0) {
real = numbers[0];
} else {
imaginary = numbers[0];
}
}
printf("Real part: '%f'\tImaginary part: '%f'\n", real, imaginary);
printf("\n");
}
free(first_value);
fclose(fin);
} else {
fprintf(stderr, "Failed to open file '%s'\n", filename);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
This application will only perform some basic checks on the input, a lot of invalid data can pass as valid..
What this application expects though is the following:
- On each line, there can be either one or two numbers.
- The numbers can be encapsulated in parenthesis ()
- The first number can have a sign or not
- There might be space between the characters or not
- There might be space between the sign characters and the numbers
- The imaginary part of the number will have the character
j
either before the number or after, attached to the number