Not able to print this 2D array (weird output) in C - arrays

I am trying to read a text file with 100 numbers like 1 2 45 55 100 text file here (all on a single line) and then put them in a 10x10 array (2D array).
736.2 731.6 829.8 875.8 568.3 292.2 231.1 868.9 66.7 811.9 292.0 967.6 419.3 578.1 322.5 471.7 980.0 378.8 784.1 116.8 900.4 355.3 645.7 603.6 409.1 652.1 144.1 590.6 953.1 954.0 502.0 689.3 685.6 331.9 565.1 253.9 624.1 796.2 122.8 690.7 608.0 414.8 658.3 27.3 992.9 980.8 499.0 972.8 359.7 283.1 89.7 260.1 638.4 735.4 863.6 47.5 387.5 7.7 638.1 340.6 961.7 140.1 29.8 647.3 471.9 594.9 901.2 96.0 391.1 24.0 786.7 999.1 438.7 445.0 26.4 431.6 425.9 525.4 404.4 785.6 808.5 494.1 45.7 447.0 229.5 909.3 494.4 617.0 917.0 132.5 957.5 878.8 272.6 987.4 526.1 744.5 582.3 427.3 840.5 973.3
Here is my code:
#include <stdio.h>
#define NR 10
#define NC 10
int main(void) {
int numbers[9][9];
int i = 0;
int count;
int j = 0;
FILE *file;
file = fopen("numbers.txt", "r");
for (count = 1; count < 101; count++) {
fscanf(file, "%d", &numbers[i][j]);
j++;
if ((count != 1) && (count % 10 == 0)) {
i++;
j = 0;
}
}
fclose(file);
int p = 0;
int q = 0;
for (p = 0; p < NR; p++) {
for (q = 0; q < NC; q++) {
printf("%d", numbers[p][q]);
}
printf("\n");
}
return 0;
}

As SparKot noted in a comment, to read a 10x10 matrix, you need to define the matrix with 10x10 elements:
int numbers[10][10];
That has to be one of the weirder ways of reading a 10x10 matrix that I've ever seen. Why not go for a simple approach of nested loops. Since the data contains floating-point numbers, you need to read them as double (or perhaps float) values.
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
double double_val;
if (fscanf(file, "%lf", &double_val) != 1)
{
fprintf(stderr, "failed to read matrix[i][j]\n", i, j);
exit(EXIT_FAILURE);
}
numbers[i][j] = double_val;
}
}
The mess with double_val works around the data containing floating point numbers and your original code trying to read integers. You'll get one valid value; thereafter, fscanf() will return 0 because the . is not a part of a valid integer. This highlights the importance of checking the return value from fscanf() and its relatives.
Frankly, you should be using double numbers[10][10]; for the data from the file. Then you could read directly into the array:
if (fscanf("%lf", &numbers[i][j]) != 1)
But you'd need to check (and probably change) all the rest of the code too.

There are multiple issues in your code:
the matrix is too small, make it numbers[NR][NC].
you do not check for fopen failure: you will have undefined behavior if the file numbers.txt is not in the current directory or cannot be open for reading.
you read the file contents as integers, but the file contains floating point numbers with a . decimal separator: the second and subsequent fscanf() will get stuck on the . and keep returning 0 without modifying the destination number, leaving the matrix mostly uninitialized. Make the matrix double numbers[NR][NC], read the numbers with %lf and test for conversion failure.
the counting method in the reading loop is weird. Just use 2 nested for loops with proper counter and tests.
printing the matrix contents, you should output at least a space between numbers so the output is readable.
Here is a modified version:
#include <errno.h>
#include <stdio.h>
#include <string.h>
#define NR 10
#define NC 10
int main() {
double numbers[NR][NC];
FILE *file;
file = fopen("numbers.txt", "r");
if (file == NULL) {
fprintf(stderr, "cannot open numbers.txt: %s\n", strerror(errno));
return 1;
}
for (int i = 0; i < NR; i++) {
for (int j = 0; j < NC; j++) {
if (fscanf(file, "%lf", &numbers[i][j]) != 1) {
fprintf(stderr, "error reading number at row %d, col %d\n",
i + 1, j + 1);
fclose(file);
return 1;
}
}
}
fclose(file);
for (int p = 0; p < NR; p++) {
for (int q = 0; q < NC; q++) {
printf(" %5g", numbers[p][q]);
}
printf("\n");
}
return 0;
}

Clear all a common condition that causes programs to crash; they are often associated with a file named core.
code is showing segmentation fault.

Related

How to fix error of fscanf(), checking if an element in matrix is an integer or not in C

I am tasked with reading a matrix from a text file and find out if it is a magic square, I also have to make sure that all the entries of the matrix are integers and if not I have to write to the standard output an ERROR message while also describing the position where this error occurred.
Now, I succeeded in reading all the elements of matrix but I have a problem with the verification if it is an integer or not.
I used fscanf() because I know that on success it returns the number of elements it succeeded reading correctly and returns EOF or 0 otherwise.
Here is the matrix:
3
12 3 87
78 a 9
45 0 23
first element is the number of rows and columns.
and here is my code ( the part I need help with at least )
while(!feof(file))
{
while ( fgets(buffer, sizeof(buffer), file) )
{
for ( int j = 0; j < n; j++ )
{
if ( i == n )
{
break;
}
m = fscanf(file, "%d", &a[i][j]);
printf("\n%d", m);
if ( m == 0 || m == EOF )
{
printf("\nERROR, %d, %d, %d \n", i, j, a[i][j]);
}
}
i++;
}
}
and here is my output ( right now I'm just trying to figure out this problem so this is not how it will look later on ):
1
1
1
1
0
ERROR, 1, 1, 0
0
ERROR, 1, 2, 48
1
1
1
12 3 87
78 0 48
45 0 23
When I replace 'a' with a number of type (float) for example it will display the ERROR message just for a[1][1] BUT it will replace 9 with 48.
When I have a character ( like in this case ) it will display an ERROR message both for a[1][1] ('a') and a[1][2] ('9') and replace it too.
And my question is why does this happen and what the hell happens between a[1][1] and a[1][2] and how to fix it.
EDIT:I know I could simply exit the program when I find 1 case but I'm really curious on why does this error happen.
fscanf(file, "%d", &n );//I read the first integer, which is also the maximum capacity of my 2d array
int a[n][n];
First points:
while(!feof(file))
{
You will want to look at Why is while ( !feof (file) ) always wrong?. Further, the entire outer loop is superfluous to your code and can simply be removed.
With any of the scanf family of functions, when input does not match the conversion specifier used in the format string, a matching failure occurs, character extraction from the input stream stops at the point of failure, the offending characters causing the failure are left in the input stream (unread) just waiting to bite you on your next attempted read. Attempting to read 'a' as type int with scanf produces a matching failure.
How To Handle A Matching Failure?
Since you always validate all user input, as you note, you detect an input failure with scanf when the return is less than the number of conversions specified (or EOF). Reading an integer at a time with fscanf within your loops tells you exactly where the input failure happened from a row/col standpoint when reading a square matrix worth of data. Knowing where the failure occurred you can output the row/col where the invalid data was encountered.
To capture the invalid data for reporting purposes, you can simply scan forward with fgetc reading a character at a time and filling a buffer with the offending characters until the next valid digit or +/- (explicit sign for a digit) is encountered (you can use ungetc at that point to put the valid digit (or sign) back in the input stream if your wanted to continue reading additional values)
A Short Example
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define MAXC 1024
int main (int argc, char **argv) {
int **m = NULL;
unsigned dim = 0;
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
if (fscanf (fp, "%u", &dim) != 1) { /* read square mtrx dim */
fputs ("error: invalid format, no dimension.\n", stderr);
return 1;
}
if (!(m = malloc (dim * sizeof *m))) { /* allocate/validate dim ptrs */
perror ("malloc-m");
return 1;
}
for (unsigned i = 0; i < dim; i++) /* allocate dim rows of dim int */
if (!(m[i] = calloc (dim, sizeof *m[i]))) { /* zero mem w/calloc */
perror ("calloc-m[i]");
return 1;
}
for (unsigned i = 0; i < dim; i++) /* for each row */
for (unsigned j = 0; j < dim; j++) { /* for each col */
if (fscanf (fp, "%d", &m[i][j]) != 1) { /* read/validate int */
char buf[MAXC], *p = buf; /* buf and ptr to buf */
int c; /* int for char */
/* read while !EOF, not digit and not -/+ */
while ((c = fgetc(fp)) != EOF && (c < '0' || '9' < c) &&
c != '-' && c != '+')
if (!isspace(c)) /* if not a space */
*p++ = c; /* store offending char(s) */
*p = 0; /* nul-terminate buf */
if (c != EOF) /* if c a char - put it back */
ungetc(c, fp);
/* output location of invalid input */
printf ("error: m[%d][%d] - invalid entry '%s'.\n",
i, j, buf);
return 1; /* and bail - or continue -- your choice */
}
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
for (unsigned i = 0; i < dim; i++) { /* for each row */
for (unsigned j = 0; j < dim; j++) /* for each col */
printf (" %3d", m[i][j]); /* output value */
putchar ('\n'); /* output newline */
free (m[i]); /* free ints in row */
}
free (m); /* free pointers */
return 0;
}
(note: you didn't say how you allocated storage, so a simple pointer to pointer to int was used to allocate dim pointers and a block of dim integers was allocated and the starting address for each allocation assigned to each of the pointer to allow indexing as a 2D array)
Example Input Files
Using your example input with invalid int at [1][1]:
$ cat ~/tmpd/mtrx.txt
3
12 3 87
78 a 9
45 0 23
An example with good values:
$ cat ~/tmpd/mtrxgood.txt
3
12 3 87
78 8 9
45 0 23
Example Use/Output
With invalid int at [1][1]:
The program correctly reports the location and the offending character:
$ ./bin/readsquaremtrx ~/tmpd/mtrx.txt
error: m[1][1] - invalid entry 'a'.
With good values, all values are read and the matrix printed to the screen before all allocated memory is freed:
$ ./bin/readsquaremtrx ~/tmpd/mtrxgood.txt
12 3 87
78 8 9
45 0 23
The code is commented to help you follow along. If you have any questions, just let me know.
Key Issue of your Code: Your FILE pointer doesn't move ahead when fscanf encounters an error. You need to move it ahead using fseek.
Some of the issues you need to look at:
How to allocate an array of sufficient size to read all inputs correctly
File based error handling and how to move the FILE pointer ahead if it hits an error while reading using fscanf. My below code considers
only the specific case of a single incorrect character being present,
you will have to handle it appropriately if more than one character is
present.
There is no need for you to do both fgets and fscanf. Only one is sufficient.
Relook, if you really want to use fscanf. The same logic can be achieved using other read methods related to FILE.
Treat the below code strictly as a pseudo code, just giving some indications. This doesn't handle all conditions at all. You need to work on lot of aspects of your code and handle additional error conditions etc. I have just given a pointer on how you can solve it.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *f = fopen("./check.txt", "r");
int a[3][3] = {0};
int n, res, i;
res = fscanf(f, "%d", &n);
i = 0;
while(i<n)
{
for(int j = 0; j < n; j++)
{
int val = 0;
res = fscanf(f, "%d", &val);
if ((res == 0) || (res == EOF))
{
printf("Error: res = %d for i = %d, j = %d, val = %d\n", res, i, j, val);
fseek(f, 1, SEEK_CUR);
}
else
a[i][j] = val;
}
i++;
}
printf("The Matrix\n");
for(int i = 0; i<n; i++)
{
for (int j=0; j<n; j++)
printf("%d ", a[i][j]);
printf("\n");
}
}
Output:
Error: res = 0 for i = 1, j = 1, val = 0
The Matrix
12 3 87
78 0 9
45 0 23
Another example using a flat memory region instead of a somwhat inefficient "array" of pointers to pointers:
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
int is_magic_square(int *square, size_t dimension)
{
if(dimension < 3) {
return 0;
}
int prev_row_sum;
int prev_col_sum;
int d1_sum = 0;
int d2_sum = 0;
for (size_t y = 0; y < dimension; ++y) {
int curr_row_sum = 0;
int curr_col_sum = 0;
for (size_t x = 0; x < dimension; ++x) {
curr_row_sum += square[y * dimension + x];
curr_col_sum += square[x * dimension + y];
if (x == y) {
d1_sum += square[y * dimension + x];
d2_sum += square[y * dimension + dimension - 1 - x];
}
}
if (y && (curr_row_sum != prev_row_sum || curr_col_sum != prev_col_sum)) {
return 0;
}
prev_row_sum = curr_row_sum;
prev_col_sum = curr_col_sum;
}
return prev_row_sum == d1_sum && prev_row_sum == d2_sum ? prev_row_sum : 0;
}
int main(void)
{
char const *filename = "test.txt";
FILE *input = fopen(filename, "r");
if (!input) {
fprintf(stderr, "Couldn't open \"%s\" for reading :(\n\n", filename);
return EXIT_FAILURE;
}
size_t dimension;
if (fscanf(input, " %zu", &dimension) != 1) {
fprintf(stderr, "Faild to read squares dimensions from \"%s\" :(\n\n", filename);
fclose(input);
return EXIT_FAILURE;
}
int result = EXIT_FAILURE;
printf("Reading a %zu x %zu square from \"%s\" ...\n\n", dimension, dimension, filename);
int *square = calloc(dimension * dimension, sizeof(*square));
if (!square) {
fputs("Not enough memory :(\n\n", stderr);
goto cleanup;
}
for (size_t y = 0; y < dimension; ++y, putchar('\n')) {
for (size_t x = 0; x < dimension; ++x) {
int value;
if (fscanf(input, " %d", &value) != 1 || value < 1) {
fprintf(stderr, "\n\nFailed to read value at (%zu, %zu) from \"%s\" :(\n\n",
x + 1, y + 1, filename);
goto cleanup;
}
for (size_t pos = 0; pos < y * dimension + x; ++pos) {
if (square[pos] == value) {
fprintf(stderr, "\n\nDuplicate value %d found at (%zu, %zu) in \"%s\" :(\n\n",
value, x + 1, y + 1, filename);
goto cleanup;
}
}
if(value > dimension * dimension) {
fprintf(stderr, "\n\nValue %d at (%zu, %zu) in \"%s\" is out of range 1, 2, ..., %zu^2 :(\n",
value, x + 1, y + 1, filename, dimension);
goto cleanup;
}
printf("%4d ", value);
square[y * dimension + x] = value;
}
}
int sum = is_magic_square(square, dimension);
printf("\nThis %s a perfect square!\n", sum ? "is" : "is not");
if (sum) {
printf("It's sum is %d.\n", sum);
}
putchar('\n');
result = EXIT_SUCCESS;
cleanup:
free(square);
fclose(input);
return result;
}
Sample Input:
4
10 3 13 8
5 16 2 11
4 9 7 14
15 6 12 1
Sample Output:
Reading a 4 x 4 square from "test.txt" ...
10 3 13 8
5 16 2 11
4 9 7 14
15 6 12 1
This is a perfect square!
It's sum is 34.

How to use 'fwrite' in C?

I'm trying to use 'fwrite' and make snd files.
I want to make IIR Filter. I made a FIR Filter and i use the codes to IIR Filter.
(of course, change coeffs)
But I think 'fwrite' doesn't work. Because the result of IIR filter is only zero.
I think I did some mistakes in my code.
Can you give me a hint? i'm totally in panic now.
When I check output[], it looks fine. It has group of integer, as i respect.
I don't know how to write it.
I know the code is so long and looks difficult.
But I have no idea so if you give me a hand, it would be pleasured.
Thanks for reading.
#include <stdio.h>
#include <stdint.h>
#include <memory.h>
// Filter Code Definitions
#define MAX_INPUT_LEN 80
#define MAX_FLT_LEN 14
#define BUFFER_LEN (MAX_FLT_LEN - 1 + MAX_INPUT_LEN)
double insamp[BUFFER_LEN];
// IIR inititialization
void IirFloatInit(void)
{
memset(insamp, 0, sizeof(insamp));
}
// the IIR filter function
void IirFloat(double *coeffs, double *input, double *output, int length, int
filterLength)
{
double acc;
double *coeffp;
double *inputp;
int n;
int k;
// put the new samples at the high end of the buffer
memcpy(&insamp[filterLength - 1], input, length * sizeof(double));
for (n = 0; n < length; n++) {
coeffp = coeffs;
inputp = &insamp[filterLength - 1 + n];
acc = 0;
for (k = 0; k < filterLength; k++) {
acc += (*coeffp++) * (*inputp--);
}
output[n] = acc;
}
memmove(&insamp[0], &insamp[length], (filterLength - 1) * sizeof(double));
}
double coeffs[MAX_FLT_LEN];
void intToFloat(int16_t *input, double *output, int length)
{
int i;
for (i = 0; i < length; i++) {
output[i] = (double)input[i];
}
}
void floatToInt(double *input, int16_t *output, int length)
{
int i;
for (i = 0; i < length; i++)
{
input[i] += 0.5;
if (input[i] > 32767.0)
{
input[i] = 32767.0;
}
else if (input[i] < -32768.0)
{
input[i] = -32768.0;
}
output[i] = (int16_t)input[i];
}
}
// number of samples to read per loop
int main(void)
{
int size;
int16_t input[MAX_INPUT_LEN];
int16_t output[MAX_INPUT_LEN];
double floatInput[MAX_INPUT_LEN];
double floatOutput[MAX_INPUT_LEN];
double coeffs[MAX_FLT_LEN];
FILE *in_fid;
FILE *out_fid;
FILE *filter;
// open the input waveform file
in_fid = fopen("input.snd", "rb");
if (in_fid == 0) {
printf("couldn't open input.snd");
return;
}
// open the output waveform file
out_fid = fopen("outputFloatIIR.snd", "wb");
if (out_fid == 0) {
printf("couldn't open outputFloat.snd");
return;
}
filter = fopen("coeffs_iir.txt", "r");
if (filter == NULL) {
puts("couldn't open coeffs_iir.txt");
return;
}
for (int i = 0; i < MAX_FLT_LEN; i++) {
fscanf(filter, "%le", &coeffs[i]);
printf("%le \n", coeffs[i]);
}
IirFloatInit();
do {
size = fread(input, sizeof(int16_t), MAX_INPUT_LEN, in_fid);
intToFloat(input, floatInput, size);
IirFloat(coeffs, floatInput, floatOutput, size, MAX_FLT_LEN);
floatToInt(floatOutput, output, size);
fwrite(output, sizeof(int16_t), size, out_fid);
} while (size != 0);
fclose(in_fid);
fclose(out_fid);
fclose(filter);
getchar();
return 0;
}
Into the manual (man printf) I can read this:
eE The double argument is rounded and converted in the style [-]d.ddde+-dd where there is one digit before the decimal-point
character and the number of digits after it is equal to the precision;
if the
precision is missing, it is taken as 6; if the precision is zero, no decimal-point character appears. An E conversion uses the
letter E' (rather thane') to introduce the exponent. The exponent
always contains at least two digits; if the value is zero, the exponent is 00.
Into your file where coefficients are stored, are into that format? If you use a debugger, what happen with the value read into fscanf?
I mean, probably the format is not the expected and because of that you get 0. Maybe you want to use fscanf(filter, "%lf", &coeffs[i]); ?
What is the value returned by fscanf? Into the manual (man fscanf) can be read this:
RETURN VALUES
These functions return the number of input items assigned. This can be fewer than provided for, or even zero, in the event of a
matching failure. Zero indicates that, although there was input
available, no
conversions were assigned; typically this is due to an invalid input character, such as an alphabetic character for a `%d'
conversion. The value EOF is returned if an input failure occurs
before any conver-
sion such as an end-of-file occurs. If an error or end-of-file occurs after conversion has begun, the number of conversions which
were successfully completed is returned.

Input in specific format (matrix)

I have an issue with input in my homework. On stdin, I will get a specifically formatted input.
In first line, there will be 2 integers, that determine the size of a matrix (rows and cols). All the lines after represent rows of the matrix.
I essentially want to do something like getline(), but I don't want to use getline(). In fact I can't, its forbidden in the homework. Therefore I have to scan int by int (or char by char I guess). The issue here is I need it to be bulletproof (almost). Dummy-proof at least.
I'm imagining a big while loop that keeps going until EOF and inside that another loop (perhaps?) which always reads a line, saves it to my allocated matrix and carries on to the next. I'm aware that I'm supposed to be checking for '\n', but I kind of lack the ability to think of a solution today.
Here's what I'm working with: My matrices are a structure.
struct Matrix{
int nrows;
int ncols;
int** matrix;
};
I then have multiple functions.
A function to dynamically allocate space for the matrix of specific size:
struct Matrix init_matrix(int r, int c)
{
struct Matrix mat;
mat.nrows = r;
mat.ncols = c;
mat.matrix = calloc(r, sizeof(int *));
for(int i = 0; i < r; ++i)
{
*(mat.matrix+i) = calloc(c, sizeof(int));
}
return mat;
}
A function to free the previously allocated space:
void free_matrix(struct Matrix mat)
{
int top = mat.nrows;
for(int i = 0; i < top; ++i)
{
free(mat.matrix[i]);
}
free(mat.matrix);
}
Those 2 functions work perfectly fine.
Now I'm trying to make a function create_matrix(void) (at least I think it shouldn't take any args), that will read the input I'm supposed to receive, for example:
3 3
1 2 3
4 5 6
7 8 9
when the function reads the input, it could tell if the input is incorrect or is in incorrect format and exit the program with corresponding exit value (like 100 f.e.) If the input is correct and in correct format, it calls init_matrix() and then saves input to the matrix.
For your deeper understanding: the whole input I'm supposed to receive is:
matrix A (like above, size in first line, values in lines after)
an operation (+,-,*)
matrix B
Then execute the operation (A*B, A+B etc.). I'm trying to make most things into functions, so the main would be very simple, f.e.
int main(int argc, char *argv[])
{
struct Matrix mat1 = create_matrix();
char operation = get_operation();
struct Matrix mat2 = create_matrix();
struct Matrix result = compute(mat1,mat2, operation);
return 0;
}
Something in those lines, if you get me. The thing is I want to make the program complex enough so that I could later edit it to handle a bigger sequence (up to 100) of matrices than just two. Right now I could do it the dirty way, make it work for two matrices with one operation, but that's not what I really want.
Well, here's how I solved it. It works. It's not anywhere close to perfect, but it works, upload system took it and gave it full amount of points, so I'm satisfied.
struct Matrix read_matrix(FILE *fp)
{
struct Matrix mat;
//FIRST LINE
int ch;
int i = 0;
int n = 20;
char* line = calloc(n,sizeof(char));
while((ch = fgetc(fp)) != EOF && ch != '\n')
{
*(line + i++) = ch;
}
*(line + n-1) = '\0';
int r,c;
int k = sscanf(line,"%d %d", &r, &c);
if(k != 2)
{
fprintf(stderr, "Error: Chybny vstup!\n");
exit(100);
}
free(line);
//MATRIX
line = calloc(c, sizeof(int));
mat = init_matrix(r, c);
i = 0;
r = 0;
while(r < mat.nrows && (ch = fgetc(fp)))
{
if(ch == '\n' || ch == EOF)
{
*(line + i) = '\0';
int offset;
char *data = line;
for(int j = 0; j < mat.ncols; ++j)
{
int d = sscanf(data, " %d%n", &mat.matrix[r][j], &offset);
if(d != 1){
fprintf(stderr, "Error: Chybny vstup!\n");
exit(100);
}
data += offset;
}
i = 0;
++r;
if(ch == EOF){
break;
}
} else
{
*(line + i++) = ch;
}
}
free(line);
return mat;
}

How to store a number string in a file as a seperate integer in an array in C

I have 32 bits as a text file in Sender.txt like
00100100101110001111111100000001
I want to store each individual number as an integer in the array. I have tried the following code but not working.
#include <stdio.h>
#include<stdlib.h>
void main()
{
FILE *myfile;
myfile = fopen("Sender.txt" , "r");
char data[32];
int i,con, data1[32];
for(i=0;i<32;i++)
{
fscanf(myfile, "%1s", &data[i]);
}
for(i=0;i<32;i++)
{
con = atoi(data[i]);
data1[i]=con;
}
for(i=0;i<32;i++)
{
printf("%d \n", &data1[i]);
}
}
Still without fully understanding the purpose of your endeavor, I suggest to rewrite the first two loops:
for(i = 0; i < 32; i++)
{
int next = fgetc(myfile);
data1[i] = (next == '0') : 0 ? 1;
}
This code assumes that the file has 32 1's or 0's, all on the same line, and nothing else.
This could be further compressed, possibly at the expense of clarity:
for(i = 0; i < 32; i++)
{
data1[i] = fgetc(myfile) - '0';
}
Why don't you use fgetc ? This function reads only one Charakter and returns it.
Your code should then look like this:This one got errors see EDIT
FILE *file;
char c[32];
for(int i = 0; i < 32; i++){
if((c[i] = fgetc(file)) == NULL)
//then Error
}
fclose(file);
EDIT: As rightly pointed out by "alk" (what a name mate xD) The if clause makes no sense at all. It was to early in the morning i apologize. The right code should of course look like this:
FILE *file;
int data[32]; //The Question was to store the Data in an int not char like i did...
for(int i = 0; i < 32; i++)
data[i] = fgetc(file) - '0';
fclose(file);
Best regards

C - Nested for loops not printing multiple elements

My nested loops only print one char, 'c', which is the correct first char to print, but I cannot figure out why my loop won't keep looping through the alphabet. Any assistance in determining my loop error would be great.
#include <stdio.h>
#include <stdlib.h>
void problem_1_function();
int main(){
problem_1_function();
return (0);
}
void problem_1_function(){
FILE *the_cipher_file;
the_cipher_file = fopen("cipher.txt", "r");
FILE *the_message_file;
the_message_file = fopen("message.txt", "r");
FILE * the_decode_file;
the_decode_file = fopen("decode.txt", "w");
int the_letter_counter = 0;
int the_alphabet_array[100];
int size_of_alphabet = 0;
int size_of_message = 0;
int the_message_counter = 0;
int the_message_array[100];
char the_decode_array [15];
char the_letter_char[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','w','x','y','z'};
if(the_decode_file == NULL){
printf("Error opening file!\n");
}
if(!the_cipher_file){
printf("Error: Filename \"cipher.txt\" not found!\n");
}
while(fscanf(the_cipher_file, " %d%*[,] ", &size_of_alphabet) > 0 && the_letter_counter < 100){
the_alphabet_array[the_letter_counter] = size_of_alphabet;
//printf("%d ", size_of_alphabet);
the_letter_counter++;
}
if(!the_message_file){
printf("Error: Filename \"cipher.txt\" not found!\n");
}
while(fscanf(the_message_file, " %d%*[,] ", &size_of_message) > 0 && the_message_counter < 100){
the_message_array[the_message_counter] = size_of_message;
//printf("%d ", size_of_message);
the_message_counter++;
}
int message_equals_cipher = 0;
int message_equals_cipher2 = 0;
for(message_equals_cipher; message_equals_cipher < sizeof(the_message_array); message_equals_cipher++){ //these nested loops go through the alphabet to print letters corresponding to arrays...
for(message_equals_cipher2; message_equals_cipher2 < 26; message_equals_cipher2++){
if(the_message_array[message_equals_cipher] == the_alphabet_array[message_equals_cipher2]){
the_decode_array[message_equals_cipher] = the_letter_char[message_equals_cipher2];
fprintf(the_decode_file, "%c", the_decode_array[message_equals_cipher]);
}
}
}
fclose(the_cipher_file);
fclose(the_message_file);
fclose(the_decode_file);
}
int message_equals_cipher = 0;
int message_equals_cipher2 = 0;
for(message_equals_cipher; ...
for(message_equals_cipher2; ...
You're setting these to 0 outside the loops .. the initialization expressions of your for statements don't do anything -- if you set your warning level high enough, your compiler should tell you that. Because you don't reset message_equals_cipher2, your inner loop will only run once total. You want
for(message_equals_cipher = 0; ...
for(message_equals_cipher2 = 0; ...
If you are compiling C99 or higher, you can do
for(int message_equals_cipher = 0; ...
for(int message_equals_cipher2 = 0; ...
and get rid of the previous definitions of those variables.
Yes, the problem in your nested for loop is that you are not initializing your message_equals_cipher2 variable to 0 in your second for loop.
The nested code should be like :
for(message_equals_cipher; message_equals_cipher < sizeof(the_message_array); message_equals_cipher++)
{
for(message_equals_cipher2=0; message_equals_cipher2 < 26; message_equals_cipher2++)
{
// Your stuff
}
}
I will agree with jim, instead of initializing your variables message_equals_cipher and message_equals_cipher2 before nested for loops. You can do it as jim specified.

Resources