My code requires me to open up a file.
the first line of the file contains 2 integers between 1 and 1000.
I must read these 2 numbers, use them to create a 2D array corresponding to those numbers
(e.g. 50,200 is - array[50][200]).
After i have created this array, i have to read the rest of the file and store the data (which is set up in a grid of the dimensions of the 2 numbers).
What is the best way to go about this. I thought about doing a getline and then doing a for loop to append the chars to row then column and then converting to int, but my compiler kept coming up with errors.
Is the file binary or text? If binary, use fread, it will let you read the raw bytes easily. if its text use fscanf
Assuming the input is always of this form (a little unclear):
2,4
aaaa
b b
... then an approach would be to read in the dimensions of your matrix (number of rows, number of columns) and then follow that up by reading each element of the matrix one character at a time. It would be something along the lines of this:
int rows = getchar();
// Skip ','.
getchar();
int cols = getchar();
int arr[ rows ][ cols ];
int r = 0;
int c = 0;
for ( int byte = getchar(); byte != EOF; byte = getchar(), c++ ) {
if ( c == cols ) {
c = 0;
r++;
}
arr[ r ][ c ] = byte;
}
... and you would need to pipe the input file to your program as follows:
./program.out < input.txt
Remark: This is tailored to your specific problem-set, it would not work if: the input is not guaranteed to populate the entire array, the input is a bad size, overflow of dimensions, etc. (many issues) - so be sure to account for those.
Related
I need to store values coming from various data types in a binary file (in python) and then decode this binary file in c and reconstruct the values. For more clarification, lets assume we have three variables as below
a = [1, 2, 3], dtype = int
b = ['sky', 'chair', 'book', 'desk']
c = [3.56, 4.69, 55.0, 1.698], dtype = float32
step1: export all data values to a binary file (data)
step2: import the binary file in c and then reconstruct corresponding values.
//load binary file ?
...
// declaration
int a[3];
char *b[4];
double c[4];
// decode the binary file to have the same values in c ?
...
a = [1, 2, 3];
b = {'sky', 'chair', 'book', 'desk'};
c = [3.56, 4.69, 55.0, 1.698];
Thanks in advance for your helps,
I'm trying to have something that dynamically exports the data in a binary file and also dynamically retrieve in C; a data structure like this:
[number of integers, all integers values, number of floats, all float values, number of strings, all strings]
For example: [3, 1, 2, 3, 4, 0.2, 0.65, 0.56, 0.33, 2,'sky','desk']
In summary, I also need to pass the number of elements for each data type for decoder in C; If I know that values are stored in such an order (ints, floats, strs)
step 1: Read first number (3), now we know that there are 3 int values.
step 2: Read the next tree numbers as ints.
step 3: Read the number of float values (4).
step 4: read four float numbers.
step 5: read the number of strings (2),
step 6: read the two strings.
I know that I can use struct package to create binary packs and then write them, but I don't know what Generic strategy should I follow with respect to the unpacking process which is being implemented in C (!!!).
a data structure like this: [number of integers, all integers values, number of floats, all float values, number of strings, all strings]
In preparation for writing the strings to the file, I'd convert them to bytes, e. g.:
bb = [s.encode() for s in b]
The store part in Python amounts to providing the numbers and values along with an appropriate format string.
integers: The straightforward format string 'I%di'%len(a) covers the number of integers I and all integers values %di, where %d is replaced by the number of items in a.
floats: The straightforward format string 'I%df'%len(c) covers the number of floats I and all float values %df, where %d is replaced by the number of items in c.
strings: The format string is a little less straightforward because struct.pack doesn't allow a repeat count for strings, but requires the string length. ''.join(['%ds'%(len(s)+1) for s in bb]) constructs the format for all string values %ds, where %d is replaced by the number of bytes in each string plus one for the terminating NUL. (Failing detailed specification, I chose to store the strings in C form.)
This gives:
data = struct.pack('I%di'%len(a)+'I%df'%len(c)+'I'+''.join(['%ds'%(len(s)+1) for s in bb]),
len(a), *a, len(c), *c, len(bb), *bb)
open('data', 'wb').write(data)
The decode part in C is not very complicated, following the steps you outlined, e. g.:
#include <stdio.h>
#include <stdlib.h>
int geti(FILE *stream)
{ // helper function to read an integer
int i;
if (!fread(&i, sizeof i, 1, stream)) exit(EXIT_FAILURE);
return i;
}
…
// step 1: Read first number of int values.
int ni = geti(stdin);
int a[ni];
// step 2: Read the next 'ni' numbers as ints.
for (int i = 0; i < ni; ) a[i++] = geti(stdin);
// step 3: Read the number of float values.
int nf = geti(stdin);
double c[nf];
// step 4: read 'nf' float numbers.
for (int i = 0; i < nf; )
{ float f; fread(&f, sizeof f, 1, stdin); c[i++] = f; }
// step 5: read the number of strings,
int ns = geti(stdin);
char *b[ns];
// step 6: read the 'ns' strings.
for (int i = 0, j, c; i < ns; ++i)
{
b[i] = NULL, j = 0;
do
{
b[i] = realloc(b[i], j+1);
c = getc(stdin);
if (c == EOF) exit(EXIT_FAILURE);
} while (b[i][j++] = c);
}
Note that in this example
of course you could use a stream other than stdin,
not all errors (read failure or out of memory) are checked,
no provisions are made for the case that the number representations in source and destination are different; for this, you could utilize struct.pack's byte order and size indication and/or ntohl() in C.
This question already has answers here:
How to write an array to file in C
(3 answers)
Closed 3 years ago.
I would like to write an array of integers into a file using C. However, I get some gibberish in the file.
The code is about a function that converts a decimal number into binary then stores it into a file.
int * decToBinary(int n) //function to transform the decimal numbers to binary
{
static int binaryNum[16]; // array to store binary number
int i = 0; // counter for binary array
while (n > 0) {
binaryNum[i] = n % 2; // storing remainder in binary array
n = n / 2;
i++;
}
return binaryNum;
}
int main()
{
FILE *infile;
int i;
int *p;
int decimal= 2000;
int written = 0;
infile = fopen("myfile.txt","w");
p = decToBinary(decimal);
written = fwrite(p,sizeof(int),sizeof(p),infile) ;
if (written == 0) {
printf("Error during writing to file !");
}
fclose(infile);
return 0;
}
This is what I get in my file:
This is what I get when I write a text as a test, it does not have any problem with the text, but it has with the array.
char str[] = "test text --------- \n";
infile = fopen("myfile.txt","wb");
p=decToBinary(decimal);
fwrite(str , 1 , sizeof(str) , infile);
written = fwrite(p,sizeof(int),sizeof(p),infile) ;
And this is what I get when I make this change:
written = fwrite(&p,sizeof(int),sizeof(p),infile) ;
First, be aware that there are two interpretations for 'binary':
int n = 1012;
fwrite(&n, sizeof(n), 1, file);
This writes out the data just as is; as it is represented in form of bits, output is considered "binary" (a binary file).
Your question and the code you provided, though, rather imply that you actually want to have a file containing the numbers in binary text format, i. e. 7 being represented by string "111".
Then first, be aware that 0 and 1 do not represent the characters '0' and '1' in most, if not all, encodings. Assuming ASCII or compatible, '0' is represented by value 48, '1' by value 49. As C standard requires digits [0..9] being consecutive characters (this does not apply for any other characters!), you can safely do:
binaryNum[i] = '0' + n % 2;
Be aware that, as you want strings, you chose the bad data type, you need a character array:
static char binaryNum[X];
X??? We need to talk about required size!
If we create strings, we need to null-terminate them. So we need place for the terminating 0-character (really value 0, not 48 for character '0'), so we need at least one character more.
Currently, due to the comparison n > 0, you consider negative values as equal to 0. Do you really intend this? If so, you might consider unsigned int as data type, otherwise, leave some comment, then I'll cover handling negative values later on.
With restriction to positive values, 16 + 1 as size is fine, assuming int has 32 bit on your system! However, C standard allows int to be smaller or larger as well. If you want to be portable, use CHAR_BIT * sizeof(int) / 2 (CHAR_BIT is defined in <limits.h>; drop division by 2 if you switch to unsigned int).
There is one special case not covered: integer value 0 won't enter the loop at all, thus you'd end up with an empty string, so catch this case separately:
if(n == 0)
{
binaryNum[i++] = '0';
}
else
{
while (n > 0) { /.../ }
}
// now the important part:
// terminate the string!
binaryNum[i] = 0;
Now you can simply do (assuming you changed p to char*):
written = fprintf(file, "%s\n", p);
// ^^ only if you want to have each number on separate line
// you can replace with space or drop it entirely, if desired
Be aware that the algorithm, as is, prints out least significant bits first! You might want to have it inverse, then you'd either yet have to revert the string or (which I would prefer) start with writing the terminating 0 to the end and then fill up the digits one by one towards front - returning a pointer to the last digit (the most significant one) written instead of always the start of the buffer.
One word about your original version:
written = fwrite(p, sizeof(int), sizeof(p), infile);
sizeof(p) gives you the size of a pointer; this one is system dependent, but will always be the same on the same system, most likely 8 on yours (if modern 64-bit hardware), possibly 4 (on typical 32-bit CPU), other values on less common systems are possible as well. You'd need to return the number of characters printed separately (and no, sizeof(binaryNum) won't be suitable as it always returns 17, assuming 32-bit int and all changes shown above applied).
You probably want this:
...
int main()
{
int decimal = 2000;
int *p = decToBinary(decimal);
for (int i = 0; i< 16; i++)
{
printf("%d", p[i]);
}
return 0;
}
The output goes to the terminal instead into a file.
For writing into a file use fopen as in your code, and use fprintf instead of printf.
Concerning the decToBinary there is still room for improvement, especially you could transform the number directly into an array of char containing only chars 0 and 1 using the << and & operators.
so I am trying to make a matrix reader that will take a text file that contains only data for a NxN matrix such as:
10 9 8 7
6 5 4 3
2 1 0 1
Read the test file into a dynamic multidimensional array. The program will not have headers, so it will need to read the entire file in order to obtain # of rows/cols.
Once I have all the data in my array I then will be able to manipulate how I want (i.e. swapping columns/rows, reversing order, etc).
At this point I am just trying to get my program to simply output the array as it appears in the test file once the entire matrix has been read in.
Here is what I have written so far:
#include <stdio.h>
#include <stdlib.h>
int main() {
int n;
int i=0;
int j=0;
scanf("%d", &n);
int **array;
array = malloc(n * sizeof(int *));
if(array == NULL) {
printf("Out of memory\n");
exit(1);
}
for(i = 0; i < n; i++) {
array[i] = malloc(n * sizeof(int));
if(array[i] == NULL) {
printf("Out of memory\n");
exit(1);
}
}
for(i = 0; i < n; i++) {
for(j = 0; j < n; j++) {
int k;
scanf("%d", &k);
array[i][j] = k;
printf("%d ", array[i][j]);
}
}
}
And running this gives me output:
9 8 7 6 5 4 3 2 1 0 1 1 1 1 1 1 1 1 1 1 1 1... repeating 1's...
I am not sure what is wrong with my code I have been staring at it for a solid hour and have made 0 progress.
Because my output prints out about 100 different ints I feel that my problem lies in my printing loops, and I feel like it has something to do with int n, but I am not sure how to deal with this.
Any help with be greatly appreciated! Thanks.
The issue is as follows: The first number that is obtained from your file is 10 and that is being stored inside the int n close towards the beginning. That value defines the width and height of your multi-dimensional array, your matrix. You then ask for further values from that file, exactly 10 * 10 many times.
The file, however, only has 4 * 3 - 1 = 11 numbers left in it. It provides them all, right into the int k. Those values get stored inside your matrix, printed. After the 11th (or 12th if you count the first 10) the scanf starts failing. As it fails, it returns the value EOF == -1 but you do not recognize that.
Failure leaves the k as it is, although I am not sure whether it is guaranteed to remain what it previously was, since as far as I know, k could very well have another memory location allocated for itself with each cycle, since (again) as far as I know it gets cleared at the end of each loop. In your case, it does keep its value, luckily I would say, and that gets stored/printed.
In the end, you should have exactly 100 numbers printed, because of that 10 at the very beginning.
Even if you had an additional 4 at the very beginning, you'd end up with a matrix that has a wild last line with all 1s.
If you want to have a 3 by 4 matrix in your hands, consider making your file as the following example:
3 4
10 9 8 7
6 5 4 3
2 1 0 1
Then read the first value into an int n and then second one into an int m. Make first memory allocation with malloc( n * sizeof * array );, then the secondary allocations with malloc( m * sizeof ** array );.
You could also alternatively omit reading anything, deduce how many rows and columns your matrix should have by reading the amount of new-line '\n' occurrences in your file (plus one), as well as amount of numbers there are on a single line.
Edit:
Okay, let's show this you could also part: This is just an example, I'll be using a pair of scanfs for counting both the amount of lines that have at least one number inside and amount of numbers on a single line.
...
int n = 0;
int m = 0;
int discardable;
while ( scanf( "%d", &discardable ) == 1 ) {
// as long as a number has been successfully read
n++;
if ( scanf( "%*[^\n]" ) != 0 )
// discard everything until a '\n'
// and if you fail to encounter a '\n' anywhere until the file ends...
break;
}
// rewind back to the beginning of the file
rewind ( stdin );
while ( scanf( "%d", &discardable ) == 1 ) {
// as long as a number has been successfully read
m++;
if ( scanf( "%*[ \t]" ) != 0 || stdin->_ptr[0] == '\n' )
// discard every ' ' or '\t'
// if you rather get carried until the end of file, break
// else, if the upcoming character is '\n', again, break
break;
}
rewind ( stdin );
...
There you have it, n and m here should be storing the height and width of the matrix you should have, respectively.
This is just a way to do it, I can see why many could potentially just hate this, because I have made use of the FILE structure, and referred to _ptr, but whatever. I personally would prefer this any day over carrying a temporary character array and read from it.
I am working on a C program for an introductory course and am currently stuck.
The program computes the approximate value of cos(x) via Taylor series expansion.
The catch is that it reads input from a dat. file which consists of a certain number of rows of three numbers each, containing information that is meant to be processed.
For instance, the dat. file might be:
5
1 -1 6
2 1 .0001
2 1.5 2
...
The first number of each row determines which method to compute cos(x), the second number determines the value of x, etc.
I process this file as a multidimensional array:
int array[64][64], m;
FILE *ifp
ifp = fopen("cos_input.dat", "r");
i = 0;
fscanf(ifp, %d\n", &m); //takes the first value into int m
while (fscanf(ifp, "%d %d %d\n", &array[i][0], &array[i][1], &array[i][2]) == 3) {
i++;
}
^This code (I think) puts the input data file into a m x 3 array.
Now I need to manipulate the elements of the array and then write them to another output dat. file, which takes the form, for example:
x = 1
x = 2
x = 3
x = 4
...
My notion to accomplish this is to first, implement my other functions with the values stored in the multi-dimensional array, which I believe I can do, just declaring each value of my array and throwing them into the computational blender that is my other functions. (e.g., power(array[3][2], array[1][2]);) Then I have to print them to a dat. file, which I have no clue how to do.
This is because I am very sketchy on my knowledge of pointers and the fprintf/fscanf functions.
When I am writing my final data it will consist of some loop which will spit out one value per line. What is the code to use in order to print this to cos_output.dat? Must I create a new pointer expression 'ofp' similar to how I created 'ifp' in order to open the input file and implement it with scanf?
This is my first and only step I can come up with so far.
FILE *ofp; //output file pointer
ofp = fopen("cos_output.dat", "w"); //the final output data file
//.... how to print? T_T
Thanks, your help is very much appreciated!
(http://ece15.ucsd.edu/Labs/lab3.pdf) <- Link to the assignment (Problem 1) only if my explanations are unclear.
You can print to a file by doing something like
FILE *ofp; //output file pointer
ofp = fopen("cos_output.dat", "w"); //the final output data file
for (i = 0; i < 5; i++) {
fprintf(ofp, "x = %d\n", i);
}
This will generate a cos_output.dat file contains
x = 0
x = 1
x = 2
x = 3
x = 4
You can modify this fprintf() statement to output whatever you want. See fprintf(3) for further details.
I am trying to read pixel data from a PPM file. I have a function to read the header so I know it's pointing to the beginning of the pixel data. I tried using fgetc(file) but if the value is more than one digit it will not work. I also tried using an array and converting the array to an int or char but I have no way of knowing how many digits each value is. I'm also not sure if the values are separated by whitespace or not. Basically I need a way to extract the pixel data. (I'm using C.)
My code right now is:
char read_byte(FILE *ipt) {
int c, i=0, sum=0;
while (i<16) {
c=fgetc(ipt);
if((i%2)!=0 {
if(c&1) {
sum+=pow(2,i/2);
}
}
i++;
}
return (char)sum;
}
EDIT:
At first I thought the file was stored as the ASCII values, then I realized it's stored as binary. Right now I think I'm making it act like hex. I'm not sure if that's correct. I'm really stuck.
EDIT: changed my code a bit
char read_byte(FILE *ipt) {
int c, i=0, sum=0;
while(i<8) {
c = fgetc(ipt);
c=c&1;
sum+=c*pow(2,i);
i++;
}
return sum;
}
I print the sum as %c
Must you write this for an assignment, or is it for pleasure, or could you use someone else's code?
There is an Open Source solution.
"Netpbm is a package of graphics programs and a programming library. " which includes programs to read PPM at http://netpbm.sourceforge.net/doc/
Edit:
Have you got, or read the definition of the file format, e.g. http://netpbm.sourceforge.net/doc/ppm.html?
It looks like the data is either sequences of one byte RGB triples, or sequences of two byte RGB triples.
The program can detect which format is used from item 7 "The maximum color value (Maxval)". It says "If the Maxval is less than 256, it is 1 byte. Otherwise, it is 2 bytes."
So you code a function which reads one byte/component RGB data, then code another to read two byte/component RGB data.
The program can choose which to call once it has read the value of Maxval.
Edit {
According to the document at that link, the image data in a 'P6' ppm is binary.
So if MaxValue is <256, and hence the data for each colour component is one byte, then reading three bytes, with three calls of fgetc(fp) would return the binary value of one RGB pixel.
If the program has read the header, it has the values of width and height for the image data. So it could allocate an array for every row (width wide of RGB pixels), and an array of pointers to each allocated pixel row array. Then read the binary data into each row, and the program has something straightforward to operate on; a 2d array.
} end edit
My reading of your question suggests you already know how to read one byte data using fgetc.
Edit - it seems like this is irrelevant:
You can read two byte data by calling fgetc twice, and shifting and bit or-ing the data, e.g. (partly ignoring error checking):
int a = fgetc(fp);
int b = fgetc(fp);
if (a >= 0 && b >= 0) { // then all is okay
unsigned int twobyte = (a<<8) | b; // or (b<<8) | a; depending on byte order
// ...