Taking input and output to file using pointer array - arrays

Here, the array pointer name[i] is not not working and I can't figure out how to change the pointer or the array to make it work. There was no compiler error/warning but the console terminal showed a negative return value and printf() was not working.
Also, the output file was created but it was empty: nothing was written into it.
I guess there's some problem with the fscanf() action of taking string input from file.
#include<stdio.h>
#include<math.h>
int main()
{
FILE *fr, *fw;
fr = fopen("data.txt", "r");
float wt[10], ht[10], bmi[10];
char *name[5];
for(int i = 0; i < 5; i++)
{
fscanf(fr, "%s\t%f\t%f", &name[i], &wt[i], &ht[i]);
bmi[i] = wt[i] / pow(ht[i], 2);
}
printf("%s", name[2]);
fw = fopen("bmi.txt", "w");
for(int j = 0; j < 5; j++)
{
fprintf(fw, "%s\t%f\n", name[j], bmi[j]);
}
fclose(fr);
fclose(fw);
return 0;
}

You should not assume that the file size is 5. You should dynamically allocate memory to the name variable like so:
int length;
fseek(filename, 0, SEEK_END);
length = ftell(filename);
name = malloc(length);
fread(name, 1, length, filename);

Related

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

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.

Trying to print an array out of a file

I'm new here and new to C.
I want to print an array out of a file with fopen but it does not seem to work.
My empty array is char matrix[25][25], and now I am trying to open a text file and print it into the array. The txt file is named Matrix1.txt and consists out of 625 characters that are either '*' or ' '.
What I am trying to do now is:
//openfile(), LÄNGE=Lenght=25, BREITE=Height=25, datei=file, matrix=array
int dateiöffnen(char matrix[][LÄNGE], char* datei){
FILE *fp;
char cell;
fp = fopen(datei, "r");
if (fp == NULL){
printf("Fehler!\n"); //Fehler=Error
}
else{
for (int y = 0; y < BREITE; y++){
for (int x = 0; x > LÄNGE; x++){
fscanf(fp, "%c", &cell);
matrix[x][y] = cell;
}
}
fclose(fp);
}
}
So later I try to print the array and play the Game of life with that printed array (it's in a switch):
case 1:
dateiöffnen(matrix, "Matrix1.txt");
play(matrix);
print(matrix);
but for some reason it prints a blank array and if I try to run the openfile() in the main function like this
int main(int argc, char *argv[]) {
char matrix[BREITE][LÄNGE];
int x, y;
//srand(time(NULL));
dateiöffnen(matrix, "Matrix1.txt");
}
it prints an array like this:
So I am very confused and would be glad and thankful if someone could give me a hint what's going on.
There is probably a typo in the inner for loop:
for (int x = 0; x > LÄNGE; x++){
should be:
for (int x = 0; x < LÄNGE; x++){

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 taking string data from file, outputting some unexpected results

So I have a makefile type file where I'm first trying to take each line of said file and store it into a an array of strings, each index of the array is a separate line. I have found that this part of the code works alright, but then I take that array of strings and I try to take each individual file that is independent and dependent from the makefile, I output the string array and it outputs as follows:
util.hmain.c stk.o util.o▒-▒
util.cmain.c stk.o util.o▒-▒
stk.hcmain.c stk.o util.o▒-▒
stk.ccmain.c stk.o util.o▒-▒
main.cmain.c stk.o util.o▒-▒
f▒c▒H▒▒ [Ð▒▒▒▒▒▒▒▒▒▒▒▒▒▒H▒▒8L▒D$PH▒T$HI▒▒L▒L$XeH▒
I'm really confused on why it's outputting such weird characters, is it a memory leak or something? I don't know how to fix it at all.
This is the following code which produces such an output..
char c;
int newline_count = 0;
while ( (c=fgetc(makeFile)) != EOF ) {
if ( c == '\n' )
newline_count++;
}
//Inputting file string data into a array of char arrays for simplicity.
char *fileString[newline_count];
rewind(makeFile);
int i;
int i2 = 0;
int i3 = 0;
for(i = 0; i < string_size; i++){
char temp[500];
temp[i3] = fgetc(makeFile);
if(temp[i3] == '\n'){
temp[i3] = '\0';
fileString[i2] = strdup(temp);
i2++;
i3 = 0;
}else{
i3++;
}
}
//Getting each individual file
char *files[newline_count];
for(i = 0; i < newline_count; i++){
char temp[500];
if(strstr(fileString[i], ":") != NULL){
}else{
i2 = 0;
do{
temp[i2] = fileString[i][i2];
i2++;
}while(!isspace(fileString[i][i2]));
files[i] = strdup(temp);
}
}
for(i = 0; i < newline_count; i++){
printf("%s %c", files[i], '\n');
}
Any sort of insight would be helpful, I'm just stuck.
Here:
do{
temp[i2] = fileString[i][i2];
i2++;
}while(!isspace(fileString[i][i2]));
you copy characters from fileString to temp without checking for string end. You should replace the condition with:
}while(!isspace(fileString[i][i2]) && fileString[i][i2]!='\0');
But this is not enough, as it stops when it reaches '\0' and does not copy it. So, after that, you should add:
temp[i2] = '\0';
Also note that strdup function allocates memory that you need to free, otherwise you have some memory leaks.

fread fails to read an unsigned int? [C]

I have a Person Struct as the following:
typedef struct Person {
char name[NUM_CHARS];
unsigned int age;
} Person;
where #define NUM_CHARS 20.
I want to write this structure to a binary file, so I wrote two function to handle that:
int writePerson(Person* person, FILE* _fp) {
int i = 0;
int count = 0;
int len = strlen(person->name);
// Write name
for(i = 0; i < len+1; i++) {
count += fwrite(&(person->name[i]), sizeof(char), 1, _fp);
// fseek(_fp, 1, SEEK_CUR);
}
// Continue
// Write age
count += fwrite(&(person->age), sizeof(unsigned int), 1, _fp);
return count;
}
int readPerson(Person* person, FILE* _fp) {
int i = 0;
int count = 0;
// Write name
for(i = 0;person->name[i] != NULL;i++) {
count += fread(&(person->name[i]), sizeof(char), 1, _fp);
}
// Continue
// Write age
count += fread(&(person->age), sizeof(unsigned int), 1, _fp);
return count;
}
So I wrote a Person to a blank file Px.bin that I've created well in advance:
int main() {
FILE* fp = fopen("Px.bin", "r+b");
Person person = {"Billie", 40};
// Person y ;
int x = writePerson(&person, fp);
printf("%d", x);
// printPerson(&y);
getchar();
fcloseall();
return 0;
}
Seems to work well, prints 8.
but when I try to read this file:
int main() {
FILE* fp = fopen("Px.bin", "r+b");
// Person person = {"Billie", 40};
Person y ;
int x = readPerson(&y, fp);
printf("%d\n", x);
printPerson(&y);
getchar();
fcloseall();
return 0;
}
I'm getting this result:
11
Billie
-858993460
Where printPerson is:
void printPerson(Person* p) {
printf("%s\n%d\n", p->name, p->age);
}
What is the problem?
This bit
for(i = 0;person->name[i] != NULL;i++) {
count += fread(&(person->name[i]), sizeof(char), 1, _fp);
}
is going to use uninitialized (IOW, containing garbage) person->name[] as the condition for reading. And it may so happen that the wrong number of bytes will get read here.
After that the following
count += fread(&(person->age), sizeof(unsigned int), 1, _fp);
can read the integer from an incorrect location within the file, not where said integer has been stored.
The fix would be to first read a character and then see if it's '\0' or not. If it is, the string's been fully read. If it's not, keep reading characters.
Your code that reads name does check for likely non-initialized (or zeroed out) person->name[i] elements. As result the loop end at some non-predictable time (i.e. if it is zeroed out loop will not fread even single character).
for(i = 0;person->name[i] != NULL;i++) {
count += fread(&(person->name[i]), sizeof(char), 1, _fp);
}
You want to change it to do/while loop or instead of reading till 0 prefix data in the file string with length and read that many characters.

Resources