cant read values from a file with new lines - c

code doesnt accept values from file since when i print some garbage pops up
the file is a textfile with a letter representing a status, and theres a number. there are 5 sets of these , each on new line the letter and the number is seperated with a space, i need to get the numbers in one array
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char status;
int number;
} information;
int main() {
int array[5] = {0};
int i;
FILE *pointer = fopen("transaction22.txt", "r");
information information1;
for (i = 0; i < 5; i++) {
fread(&information1, sizeof(information1), 1, pointer);
array[i] = information1.number;
printf("%d", information1.number);
}
return 0;
}

You can use fscanf instead of fread as:
fscanf(pointer, "%s %d", info1.status, &info1.number);
where status will be defined as char status[2]; inside struct information.
fread is used for reading raw bytes (blocks of data) from a file.
Now, you are using a text file and trying to read sizeof(info) amount of data which is 5 bytes of data (assuming 32-bit int), therefore what you get after first fread is:
info1.status (1 byte) info1.number (4 bytes)
Byte 1 SPACE + number + NEWLINE + [One more byte]
read by fread (next four bytes read by fread)
Thus info1.number is storing a garbage value.
Also the successive fread call starts reading after the data read by previous fread.

Better to use a character array like c[5]. and replace this is with struct. variable in fread ..like in for loop
fread(c,sizeof(c),1,pointer)
than use
print("%s\n",c);

Related

How to avoid garbage values while writing to a file

i am trying to create a record keeping random access file in C. As you know, in random access file, all the records are given a fixed standard byte length. so that they can be accessed randomly when needed using fseek() and fread() functions. Here i have kept that length as size of whole structure, which is 90 bytes. i have multiple character arrays in structure. when i get input from user in those arrays of characters using structure object, and pass that object to the fwrite function and i give size as size of structure, the character array data is written to the file. but because the text from user is mostly is less than 30 chracters mostly( max size of array), the fwrite function writes the string from user in file but also writes garbage values in file for those indexes which were not used in array. if i use fseek and fread() functions, the program reads data fine. but i want my file to be garbage values free and human readable. How can i do that?
`#include <stdio.h>
#define size 30
struct Record{
char account[size];
char name[size];
char address[size];
};
int main()
{
FILE *ptr = NULL;
ptr = fopen("testfile.txt", "w");
if (ptr == NULL)
{
printf("Could not open file.");
}
else
{
struct Record client;
char account[30];
char name[30];
char address[30];
printf("Enter account number: ");
gets(client.account);
printf("Enter name: ");
gets(client.name);
printf("Enter address: ");
gets(client.address);
fwrite(&client, sizeof(struct Record),1,ptr);
fclose(ptr);
ptr = fopen("testfile.txt", "r");
char buffer[size];
fseek(ptr,0,SEEK_SET);
fread(buffer,30,1,ptr);
puts(buffer);
fclose(ptr);
}
puts("Done!");
return 0;
}`
The data in file i am getting is of follwing form (input: 1 jack new york):
1 ((± 0(± /Œ¬¨þa òpv ± jack ‚Ž ((± 0(± 0(± ¤þnew york lþa à# €# 4(±
I think the problem above is due to the larger size given than length of strings. i also tried giving size as length of string. In that case, the garbage values were not printed. but in that case i will lose my principle of keeping each record of same length to have random access property in file. So how can i write my string data to file without writing garbage values and yet keep the length of each record same as standard lentgh we have decided.
I just recently found the solution to my problem. It was to place space characters ' ' after terminating character in the array. for example, if I have an array of size 30 and I have given it a string of only 10 characters, with the terminating character at the 11th position, I can store space in the remaining ones. so that when I write a whole string with size 30 in the file, the space characters are written and we do not get garbage values appearing in our file. instead, we will have our strings readable in the file.
I used this function for this purpose:
void spaces(char array[],int size)
{
int length = strlen(array);
for (int i = length + 1; i < size; i++)
{
array[i] = ' ';
}
}

Using information from an external file, How can I fill my array up correctly using fread?

I need to be able to make sure my array is correctly receiving values from the file card.raw through fread.
I am not confident about using arrays with pointers, so if anybody could help me with the theory here, it would be GREATLY appreciate it. Thanks in advance.
The code is supposed to take literally one block of size 512 bytes and stick it into the array. Then I am just using a debugger and printf to examine the arrays output.
/**
* recover.c
*
* Computer Science 50
* Problem Set 4
*
* Recovers JPEGs from a forensic image.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(int argc, char* argv[])
{
//Size of EACH FAT JPEG in bytes
#define FILESIZE 512
unsigned char* buffer[FILESIZE];
///Step 1: Open jpeg
FILE* readfrom = fopen("card.raw", "rb");
if (readfrom == NULL)
{
printf("Could not open");
}
///Step 2: Find Beginning of JPEG. The first digits will be 255216255 Then 224 or 225
fread(&buffer, FILESIZE, 1, readfrom);
for(int x = 0; x < FILESIZE; x++)
{
printf("%d = %c\n", x, buffer[x]);
}
fclose(readfrom);
}
Use return values from input functions. fread() reports how many elements were read - code might not have read 512. Swap FILESIZE, 1 to detect the number of characters/bytes read.
// fread(&buffer, FILESIZE, 1, readfrom);
size_t count = fread(&buffer, 1, FILESIZE, readfrom);
Only print out up to the number of elements read. Recommend hexadecimal (and maybe decimal) output rather than character.
for(size_t x = 0; x < count; x++) {
// printf("%d = %c\n", x, buffer[x]);
printf("%3zu = %02X % 3u\n", x, buffer[x], buffer[x]);
}
If the fopen() failed, best to not continue with for() and fclose().
if (readfrom == NULL) {
printf("Could not open");
return -1;
}
The second parameter is size, in bytes, of each element to be read.
The third parameter is Number of elements each one with a size of the <second parameter> bytes.
So, swap your second and first parameters.
Replace unsigned char* buffer[FILESIZE]; with unsigned char buffer[FILESIZE];. For now, you have an array of unsigned char *, when you need unsigned char. Because buffer is already a pointer, you don't need to take its address. In fread call, replace &buffer with buffer.
It must go like this: fread(buffer, 1, FILESIZE, readfrom);
One more thing: add return with a specific error code after printf("Could not open");, because if file hasn't been open, you cannot read from it, can you? And add return 0; in the end of main.
And take your #define out of main.
Read more about fread here: http://www.cplusplus.com/reference/cstdio/fread/

Reading first 5 characters from a file using fread function in C

How do i read some 5 to 10 characters from a sample txt file using an fread funtion.
I have the following code:
#include <stdio.h>
main()
{
char ch,fname[20];
FILE *fp;
printf("enter the name of the file:\t");
gets(fname);
fp=fopen(fname,"r");
while(fread(&ch,1,1,fp)!=0)
fwrite(&ch,1,1,stdout);
fclose(fp);
}
when i enter any sample filename..it prints all the data of the file.
my question is how to print only the first 5 to 10 characters from the sample file.
Your while loop runs until read reaches the end of the file (reads 0 bytes for the first time).
You will want to change the condition by using a for loop or a counter.
i.e. (these are suggestions, not the full working code):
int counter = 10;
while(fread(&ch,1,1,fp)!=0 && --counter)
fwrite(&ch,1,1,stdout);
or
int i;
for(i=0; i < 10 && fread(&ch,1,1,fp) > 0 ; i++)
fwrite(&ch,1,1,stdout);
Good luck!
P.S.
To answer your question in the comments, fread allows us to read the data in "atomic units", so that if a whole unit isn't available, no data will be read.
A single byte is the smallest unit (1), and you are reading one unite (of a single byte), this is the 1,1 part in the fread(&ch,1,1,fp).
You could read 10 units using fread(&ch,1,10,fp) or read all the bytes unrequited for a single binary int (this won't be portable - it's just a demo) using int i; fread(&i,sizeof(int),1,fp);
read more here.
Here is a modified version of your code. Check the comments at the lines that are modified
#include <stdio.h>
#define N_CHARS 10 // define the desired buffer size once for code maintenability
int main() // main function should return int
{
char ch[N_CHARS + 1], fname[20]; // create a buffer with enough size for N_CHARS chars and the null terminating char
FILE *fp;
printf("enter the name of the file:\t");
scanf("%20s", fname); // get a string with max 20 chars from stdin
fp=fopen(fname,"r");
if (fread(ch,1,N_CHARS,fp)==N_CHARS) { // check that the desired number of chars was read
ch[N_CHARS] = '\0'; // null terminate before printing
puts(ch); // print a string to stdout and a line feed after
}
fclose(fp);
}

Correctly store content of file by line to array and later print the array content

I'm getting some issues with reading the content of my array. I'm not sure if I'm storing it correctly as my result for every line is '1304056712'.
#include <stdio.h>
#include <stdlib.h>
#define INPUT "Input1.dat"
int main(int argc, char **argv) {
int data_index, char_index;
int file_data[1000];
FILE *file;
int line[5];
file = fopen(INPUT, "r");
if(file) {
data_index = 0;
while(fgets(line, sizeof line, file) != NULL) {
//printf("%s", line); ////// the line seems to be ok here
file_data[data_index++] = line;
}
fclose(file);
}
int j;
for(j = 0; j < data_index; j++) {
printf("%i\n", file_data[j]); // when i display data here, i get '1304056712'
}
return 0;
}
I think you need to say something like
file_data[data_index++] = atoi(line);
From your results I assume the file is a plain-text file.
You cannot simply read the line from file (a string, an array of characters) into an array of integers, this will not work. When using pointers (as you do by passing line to fgets()) to write data, there will be no conversion done. Instead, you should read the line into an array of chars and then convert it to integers using either sscanf(), atoi() or some other function of your choice.
fgets reads newline terminated strings. If you're reading binary data, you need fread. If you're reading text, you should declare line as an array of char big enough for the longest line in the file.
Because file_data is an array of char, file_data[data_index] is a single character. It is being assigned a pointer (the base address of int line[5] buffer). If reading binary data, file_data should be an array of integers. If reading strings, it should be an array of string, ie char pointers, like char * file_data[1000]
you also need to initialize data_index=0 outside the if (file) ... block, because the output loop needs it to be set even if the file failed to open. And when looping and storing input, the loop should test that it's not reached the size of the array being stored into.

C fread binary number and convert it to Ascii code

I'm trying to read the following binary (01100001) from a file and convert it to ascii code (97), but when using fread i'm getting a very big numbers.
the file "c:/input.txt" contain only the following line -01100001
printf of the array values print big numbers, such as 825241648
My code:
int main()
{
unsigned int arr[8];
int cnt,i,temp=0;
FILE * input;
if(!(input=fopen("C:/input.txt","r")))
{
fprintf(stderr,"cannot open file\n");
exit(0);
}
cnt = fread(arr,1,8,input);
for(i=0;i<cnt;i++)
{
printf("%d\n",arr[i]);
}
return 0;
}
any idea why?
arr is an array of integers. But you read only 8 bytes into it. So your first integer will have some large value, and so will your second, but after that they will have garbage values. (You made arr an "automatic" variable, which is allocated on the stack, so it will have random garbage in it; if you made it a static variable it would be pre-initialized to zero bytes.)
If you change the declaration of arr so that it is of type char, you can read your string in, and your for loop will loop over those bytes one at a time.
Then you can write a string-to-binary translator, or alternatively you could use strtol() to do the conversion with the base set to 2. strtol() is not available in all compilers; GCC is fine but Microsoft C doesn't have it.
Pl. see if the code (Compiled using gcc on Linux) below works for this.
#include<stdio.h>
#include<stdlib.h>
int main()
{
char arr[8];
int cnt,i,temp=0;
FILE * input;
if((input=fopen("data","r"))==NULL)
{
fprintf(stderr,"cannot open file\n");
exit(1);
}
//Read the 8 bytes in a character array of size 8
cnt = fread(arr,1,8,input);
for (i = 0; i < cnt; i++)
{
//Now change it to 0/1 form by substracting 48
arr[i] = arr[i] - '0';/* Ascii of 0 = 48*/
//Also Left shift..
arr[i] = arr[i] << (cnt - (i+1));
//Now Bit wise OR with the integer...
temp = temp | arr[i];
}
printf("The ascii value is %d and the character is %c\n", temp, temp);
return 0;
}
You first declare unsigned int arr[8]; which means 8 integers or more precisely 8*4=32 bytes. After that you read 8 bytes and then again try to output 8 integers. I suppose you want to read 8 bytes and output them as numbers? If you change type int to char, code might work. If file size is 32 bytes and contains integers, you may want to change fread() like this: fread(arr,sizeof(int),8,input);

Resources