Reputation: 402
I am trying to write a program that has to store an ASCII picture (every line has a different length) in an 2D-Array and then print it out again. Either I have to cut the array at "\n" or I have to create an array with dynamic size. Here is what I have so far. It is printing out in the right way, but every line has 255 chars.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define MAX_LENGTH 255
int main(void) {
FILE *iFile, *oFile;
char elements[MAX_LENGTH][MAX_LENGTH];
memset(elements, 0, MAX_LENGTH);
int zeile = 0, position = 0, size = 0;
char c;
bool fileend = false;
//open files
iFile = fopen("image.txt", "r");
oFile = fopen("imagerotated.txt", "w+");
if ((iFile == NULL) || (oFile == NULL))
{
perror("Error: File does not exist.");
exit(EXIT_FAILURE);
}
//read File to a 2D-Array
while (1) {
if ((c = fgetc(iFile)) != EOF) {
if (c == '\n') {
zeile++;
position = 0;
}
elements[zeile][position] = c;
position++;
}
else {
fileend = true;
}
if (fileend == true) {
break;
}
}
//Write 2D-Array into the output file
fwrite(elements, MAX_LENGTH, MAX_LENGTH, oFile);
fclose(iFile);
fclose(oFile);
return EXIT_SUCCESS;
}
So my question is what is the best solution to print out an array and cut each line at "\n"? (Or create an array with dynamic length/size).
I thought about creating an int countRows and get the number from 'zeile' when fileend becomes true, but how do i get countColoumns?
The main goal is rotate the ASCII image in 90 degree steps, but i'm stuck at the output. So i have to use a 2D-Array so i can swap chars easily. Thanks for your help.
Upvotes: 1
Views: 3939
Reputation: 84551
To write your array data to a binary file with fwrite
, you will need to know the number of characters you are writing. All you care about is the number of used characters (or used lines in your case), not the uninitialized/empty part of your array. You will probably also want to write the number of lines and the size of each array element as the first two values to the file so you will know how many of x-size array to read back. (handling strings, you can also write the null-terminating char to the file if you choose) If you have the number of lines numlines
as an unsigned int
, then something simple like the following for type char
where sizeof (char) = 1
:
unsigned maxl = MAX_LENGTH;
fwrite (&numlines, sizeof numlines, 1, oFile);
fwrite (&maxl, sizeof maxl, 1, oFile);
fwrite (elements, MAX_LENGTH, numlines, oFile);
Then to read it back, you read the first 2 unsigned int values which the number an array (or row) size to read back from the file.
If elements contains something other than char
where sizeof type > 1
, then you would change the fwrite
for maxl
and elements
to (example for int):
unsigned maxl = MAX_LENGTH * sizeof (int);
...
fwrite (&maxl, sizeof maxl, 1, oFile);
fwrite (elements, MAX_LENGTH * sizeof (int), numlines, oFile);
or the last line would normally be seen as just:
fwrite (elements, maxl, numlines, oFile);
The goal is to write the file (or record) in a way that you can easily read it back in. Knowing the number of elements and the size and saving those as the first two numbers written to the file allows you to query the file for the size/type needed to hold the values and then to read them back into your program and validate your read.
With not much additional effort, you can write a jagged array out as well, just include the number of character (or bytes) to be read before each line in your output. That will allow you to write a number of unevenly sized groups of elements to your file saving some file size in the process.
Upvotes: 1
Reputation: 2098
I,
You can try to make a function prototyped like that :
char **myFileToArray(char *contentOfFile);
The purpose of this function is to create an array who will contain each line of your picture. In this function you count the number of lines (= number of '/n'), you create a dynamic array with this size. For each dimension of your array, you dynamically allocate of the length of your line plus one for the '/0'. You copy your line into the dimension and put the '/0' at each end of dimension. after this you can return your array.
For example, if your file is :
1. /\_/\
2. =( °w° )=
3. ) ( //
4. (__ __)//
you will have a array of size 5 composed like that :
array[0] = " /\_/\"
array[1] = "=( °w° )="
array[2] = " ) ( //"
array[3] = " (__ __)//"
array[4] = "/0"
For the printing you can create an other function that write the array an replace each '/0' by a '/n'.
This solution is bit more complex but it's still a solution and a clean one i think.
I hope my explanation was clear sorry for my bad english i try to improve !
Upvotes: 1