Fread read wrong number of valid bytes C - c

I read two ppm images and I have a struct that stores all the informations (magic number, width, height, level of colors, and pixels). I read the pixels using fread, but the problem is that we have some test to run to see if our code is valid and can create a new ppm. One test must be not valid (not creating an image because the number of pixels is different from the size given), but my code create the image anyway, because in the fread the successful bytes read must be 83 (the condition to exit from the code is that if the number of bytes is different from the given size (width * height * 3) we return 1 and stop executing), but actually it reads 84 bytes, that is equal to the size, then it continue to execute the code, instead of blocking it, and I don't understand why. The error is after the read pixel comment.
P.s Because the code works giving two images, I give the same invalid image twice.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct image
{
char *magicNumber;
int width;
int height;
int level;
uint8_t *pixels;
};
int main(int argc, char *argv[])
{
struct image img1;
struct image img2;
struct image img3;
// Read files
FILE *file1 = fopen(argv[1], "r");
FILE *file2 = fopen(argv[2], "r");
// Check files
if (!file1 || !file2)
{
fprintf(stderr, "Error while opening the file.\n");
return 1;
}
// Alloc memory for pixels array
img1.magicNumber = (char *)malloc(3 * sizeof(char));
img2.magicNumber = (char *)malloc(3 * sizeof(char));
// Take magic number
fscanf(file1, "%s", img1.magicNumber);
fscanf(file2, "%s", img2.magicNumber);
// Check magic number
if (strcmp(img1.magicNumber, "P6") != 0 || strcmp(img2.magicNumber, "P6") != 0)
{
fprintf(stderr, "Invalid magic number.\n");
return 1;
}
// Take width
fscanf(file1, "%d", &img1.width);
fscanf(file2, "%d", &img2.width);
// Take height
fscanf(file1, "%d", &img1.height);
fscanf(file2, "%d", &img2.height);
// Check size
if (img1.width != img2.width || img1.height != img2.height)
{
fprintf(stderr, "Invalid Dimension.");
return 1;
}
// Take level
fscanf(file1, "%d", &img1.level);
fscanf(file2, "%d", &img2.level);
// Check level
if (img1.level != 255 || img2.level != 255)
{
fprintf(stderr, "Invalid Level.");
return 1;
}
// Alloc memory for pixels array
img1.pixels = (uint8_t *)malloc(img1.width * img1.height * 3 * sizeof(uint8_t));
img2.pixels = (uint8_t *)malloc(img2.width * img2.height * 3 * sizeof(uint8_t));
// Read pixels
size_t nrPixel1 = fread(img1.pixels, sizeof(uint8_t), img1.width * img1.height * 3, file1);
size_t nrPixel2 = fread(img2.pixels, sizeof(uint8_t), img2.width * img2.height * 3, file2);
// Check pixels read
if (nrPixel1 != img1.width * img1.height * 3 || nrPixel2 != img2.width * img2.height * 3)
{
fprintf(stderr, "Invalid pixels.");
return 1;
}

Related

Corrupted data when using a multidimensional char array

I'm currently implementing a function to use the "external sort" method because I have to sort a big file (+200K lines) on a device with low RAM, right now just trying to make it run on a windows pc.
I'm working on the function to split the file in tiny sorted files.
The problem I'm facing is that among the tiny sorted files the function creates, the data on certain lines are truncated.
I'm quite sure I've done a mistake somewhere but was not able to find it, yet. Could you help me to discover the problem please ?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_LINE_LEN 50
#define MAX_LINES_SORTED 130
void createSortedFiles(FILE*);
int main()
{
FILE *fp = fopen("C:\\C\\Tests\\1.txt", "r+");
if(fp == NULL){
printf("Error opening fp");
return 1;
}
createSortedFiles(fp);
fclose(fp);
return 0;
}
int cmp(const void *p1, const void *p2) {
return strcmp(p1, p2);
}
void createSortedFiles(FILE* fp) {
FILE* sfp;
//FILE* sfp2 = fopen("C:\\C\\Tests\\test.txt", "w+");
char lines[MAX_LINES_SORTED][MAX_LINE_LEN + 1] = {0}, buffer[MAX_LINE_LEN + 1] = { 0 }, fnum[6];
char fname[20] = "C:\\C\\Tests\\";
char *p;
int i = 0, j = 0 /*file names*/, int max_lines = MAX_LINES_SORTED - 1;
size_t N;
while (1){
p = fgets(buffer, MAX_LINE_LEN, fp);
// fwrite(buffer, strlen(buffer), 1, sfp2);
if(strlen(buffer) > 0 || i > 0){
if(p != NULL)
memcpy(lines[i], buffer, strlen(buffer));
//If reached the max number of lines accepted in the array
//Or reached EOF
//=> Sort and write the array "lines"
if (i >= max_lines || p == NULL) {
N = sizeof(lines) / sizeof(lines[0]);
qsort(lines, N, sizeof(*lines), cmp);
//sets the name of the current file
memset(&fname[11], 0, 9);
itoa(j, fnum, 10);
strcat(fname, fnum);
if ((sfp = fopen(fname, "w+")) == NULL) {
printf("Error opening sfp");
return;
}
for (i = 0; i < N; i++) {
fwrite(lines[i], strlen(lines[i]), 1, sfp);
}
fclose(sfp);
memset(lines, 0, sizeof(lines[0][0]) * MAX_LINES_SORTED * MAX_LINE_LEN);
j++; i = -1; //because incremented right after
}
}
if(p == NULL){
break;
}
i++;
}
//fclose(sfp2);
return;
}
Here's an example of the fp file (each lines ending with \r\n):
8023796280724;00060-014.W47
8023796280731;00060-014.W48
;0009070305/08007
;0009470337/08007
;0009490338/13001
;0010480311/08007
;0010830308/08007
;0011S
8033280129293;002004GRS4XL
;002015RSM
5708628117005;00207-630-06T42
5708628117012;00207-630-06T44
5708628117036;00207-630-06T46
4051428088756;647530241000045
4051428088763;647530241000046
4051428088770;647530241000047
;647BLPMF
4051428092586;648510256000040
4051428092593;648510256000041
4051428092609;648510256000042
4051428092616;648510256000043
4051428092623;648510256000044
4051428092630;648510256000045
4051428092647;648510256000046
Your "truncated lines" are not really truncated lines, they are stray data left in the buffer from previous files.
This array:
#define MAX_LINE_LEN 50
#define MAX_LINES_SORTED 130
char lines[MAX_LINES_SORTED][MAX_LINE_LEN + 1];
has 6630 bytes, but here:
memset(lines, 0, sizeof(lines[0][0]) * MAX_LINES_SORTED * MAX_LINE_LEN);
you zero out only 6500 bytes and leave the last two lines as they are.
You can fix this by using (MAX_LINE_LEN +1) in the size calculation, but the array can be zeroes out more tersely (and more reliably) with just:
memset(lines, 0, sizeof(lines));

Fast double file read in C

I have a large file containing floating point numbers and I want to read them.
52.881 49.779 21.641 37.230 23.417 7.506 120.190 1.240 79.167 82.397 126.502 47.377 112.583 124.590 103.339 5.821 24.566 38.916 42.576
This is just the beggining of the file. It has 10000000 numbers.
I got this code but I don't know how to print the numbers.
#include <stdio.h>
#include <stdlib.h>
#include <err.h>
#include <fcntl.h>
#include <sysexits.h>
#include <unistd.h>
int main()
{
int fd;
size_t bytes_read, bytes_expected = 1000000*sizeof(double);
double *data;
char *infile = "file.dat";
if ((fd = open(infile,O_RDONLY)) < 0)
err(EX_NOINPUT, "%s", infile);
if ((data = malloc(bytes_expected)) == NULL)
err(EX_OSERR, "data malloc");
bytes_read = read(fd, data, bytes_expected);
if (bytes_read != bytes_expected)
err(EX_DATAERR, "Read only %d of %d bytes",
bytes_read, bytes_expected);
/* print all */
free(data);
exit(EX_OK);
}
You are attempting to read a text file as if the data was binary, so you will read some bytes but the double values stored in the array will not be the values that you wanted to read from the file, you can probably do this
FILE *file;
double *array;
size_t count;
const char *infile = "file.dat";
file = fopen(infile, "r");
if (file == NULL)
return -1;
count = 0;
while (fscanf(file, "%*lf") == 1)
count += 1;
rewind(file);
array = malloc(count * sizeof(*array));
if (array == NULL) {
fprintf(stderr, "cannot allocate %zu bytes!\n", count * sizeof(*array));
fclose(file);
return -1;
}
// Read the values into the array
for (size_t i = 0; i < count; ++i) {
fscanf(file, "%lf", &array[i]);
}
// Print the array
for (size_t i = 0; i < count; ++i) {
fprintf(stdout, "%f\n", array[i]);
}
// Release memory
free(array);
Since you want a fast solution, maybe you have to sacrifice memory.
The faster manner of reading a file is in binary form.
Thus, I would obtain the file size with an efficient method,
then I would allocate memory accordingly,
with the idea of uploading the entire file to memory.
There, since memory reading is faster than file reading,
the data can be quickly read by using sscanf(...).
We can also observe that each floating point number
needs at least 3 characters to be stored in a text file:
1 char for the dot ('.'),
1 char for some digit,
and 1 char for
a space (' ') used to separating a value from its succesor in the
file.
Thus, the file size divided by 3 will be the upper bound for the size of the array of doubles.
#include <stdio.h>
int main(void) {
char *filename = "file.dat";
FILE *F = fopen(filename, "rb");
fseek(F, 0L, SEEK_END);
long int filesize = ftell(F);
rewind(F);
char *data = malloc(filesize+1);
fread(data, filesize, 1, F);
data[filesize] = '\0'; // End of string, just in case
fclose(F);
// The desired data will be stored in array:
double *array = malloc(sizeof(double) * filesize/3);
int ret;
int n; // represents the no chars in a sscanf(...) reading
double *a = array;
while (1) { // Infinite loop...
ret = sscanf(data, " %lg%n", a, &n);
if (ret == EOF) break; // <<---- EXIT POINT of the loop
a++;
data += n;
}
long int array_size = a - array + 1;
}

Console stuck at reading file and filter number of data characters

I didn't have any error when running the codes below. But on the command console it seems to be stuck on Processing filename xxxxx as below.
May I ask how do I use if condition to filter out number of data characters of less than 50 in line 67, I try to use strlen(array[count].data) >= 1 && strlen(array[count].data) <= 50 but doesn't seem to work ?
Enter filename: testdata.txt
Processing filename testdata.txt ...
Sample Source txt file:
9001:0002:9003:0021:CLS
0001:0010:0003:0021:CLS
8001:0002:8002:0080:<HTML>
0001:4002:0002:0080:<BODY>
0004:0002:0002:0080:JHJKJBKHJBIUHBKBKHBKHHBKJBKJNKJKHHKUHKJLHBKHBKHBHBHBKHBHBHBHBBHHBHBJKJHKJHKJHKUHIUJ
Source code:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
//struct definition
struct record{
int src;
int dest;
int type;
int port;
char data[100];
};
int main()
{
struct record *array;
FILE* inFile; //file handle or pointer
FILE* outFile;
FILE* errorFile;
char filename[100];
int count = 0; //keep track of number of records in memory
int i = 0;
int test;
int n1 = 0; //keep track number of correct records
int n2 = 0; //keep track number of error records
array = (struct record *) malloc(sizeof(struct record));
//User to enter filename
printf("Enter filename: ");
scanf("%s", filename);
printf("Processing filename %s ...\n", filename);
inFile = fopen(filename, "r");
if (inFile == NULL) //check if file handler is invalid
{
printf("Could not open file %s\n", filename);
exit(1); //error status code
}
test = fscanf(inFile, "%d:%d:%d:%d",
&array[count].src, &array[count].dest, &array[count].type, &array[count].port);
fgets(array[count].data, 100, inFile);
while (test != EOF){
count++;
array = (struct record *) realloc(array, (count + 1)*sizeof(struct record));
test = fscanf(inFile, "%d:%d:%d:%d:%s",
&array[count].src, &array[count].dest, &array[count].type, &array[count].port, &array[count].data);
}
fclose(inFile); //must always close file once done
outFile = fopen("data_1.txt", "wt");
errorFile = fopen("data_error.txt", "wt");
if (outFile == NULL) //check if file handler is invalid
{
printf("Could not write to file \n", filename);
exit(1);
}
if (count > 0){
printf("Viewing all records: ", count);
for (i = 0; i < count; i++){
if (array[count].src >= 1 && array[count].src <= 1024 && array[count].dest >= 1 && array[count].dest <= 1024 && array[count].type >= 1 && array[count].type <= 10 && array[count].port >= 1 && array[count].port <= 1024)
n1++;
fprintf(outFile, "%d %d %d %d",
(i + 1),
array[count].src,
array[count].dest,
array[count].type,
array[count].port
);
}
}
else
{
n2++;
fprintf(errorFile, "%d %d %d %d",
(i + 1),
array[count].src,
array[count].dest,
array[count].type,
array[count].port
);
}
fclose(errorFile);
fclose(outFile);
return 0;
}
There are many common errors in this. Which book are you reading?
array = (struct record *) malloc(sizeof(struct record));
test = fscanf(inFile, "%d:%d:%d:%d",
&array[count].src, &array[count].dest, &array[count].type, &array[count].port);
fgets(array[count].data, 100, inFile);
while (test != EOF){
count++;
array = (struct record *) realloc(array, (count + 1)*sizeof(struct record));
test = fscanf(inFile, "%d:%d:%d:%d:%s", &array[count].src, &array[count].dest
, &array[count].type, &array[count].port
, &array[count].data);
}
Forgive me. I took the liberty to clean up a bit of your code and condense some of the logic.
You shouldn't cast the return value of malloc or realloc.
While I'm on the topic of types, isn't your compiler warning you about the type of &array[count].data being incompatible with the type that corresponds to %s? Don't cast it. Just remove the & and recognise how the expression array[count].data that denotes an array is converted to a pointer of the appropriate type.
x = realloc(x, ...); where x is whatever expression is (almost) always incorrect. You need to use a temporary variable so you can handle errors correctly without leaking memory (example below)... While I'm on the topic of realloc usage, the first argument can be NULL and realloc will act like malloc in that case, so technically that first malloc is unnecessary bloat...
struct record *array = NULL;
void *temp = realloc(array, (count + 1) * sizeof *array);
if (!temp) {
puts("ERROR ALLOCATING MEMORY!");
exit(EXIT_FAILURE);
}
array = temp;
Have you considered the difference between fgets and fscanf("%s", ...)? Are you aware that the former is for reading lines, while the latter is for reading words? This would explain your problem; fscanf is halting when it sees a space, leaving everything after the space to be processed by the next fscanf call. The result? An infinite loop of fscanf fails.
Have you considered that not all fscanf fails return EOF? If you ask fscanf to read an int (using %d) and it immediately encounters non-decimal digits it can't proceed any further; a conversion failure occurs.
If you want to ensure that fscanf reads all 5 fields successfully, you need to compare the return value to 5, not to EOF.
I think you most likely meant to read the remainder of the line following your four colon-separated ints, and here's how I'd naively do that:
array = NULL;
struct record record;
while (fscanf(inFile, "%d:%d:%d:%d:%99[^\n]", &record.src, &record.dest
, &record.type, &record.port
, record.data) == 5) {
/* It's possible that a user might enter more than *
* 99 chars for the last field, so when that happens *
* we should discard the remainder... */
if (getchar() != '\n') {
puts("WARNING: Maximum field length for data is 99; user input truncated");
fscanf(inFile, "%*[^\n]");
}
void *temp = realloc(array, (count + 1) * sizeof *array);
if (!temp) {
puts("ERROR ALLOCATING MEMORY!");
exit(EXIT_FAILURE);
}
array = temp;
array[count++] = record;
}

convert unsigned int to char alphabets

I have the following code that converts a stream data of 16-bit integer to unsigned 8-bit integer.
I am looking to convert them to alphabetical data values and see what they contain.
#include<stdio.h>
int main() {
FILE *fp,*out;
char buffer[256];
size_t i = 0;
fp=fopen("c:/Gosam/input.txt", "rb");
if(fp != NULL) {
fread(buffer, sizeof buffer,1, fp);
}
out = fopen("c:/Gosam/res.txt", "w");
if(out != NULL) {
// buffer = (char*) malloc (sizeof(char)*Size);
for( i = 0; i < sizeof(buffer); i += 2)
{
const unsigned int var = buffer[i] + 256 * buffer[i + 1];
fprintf(out, "%u\n", var);
}
fclose(out);
}
fclose(fp);
}
The following is the form of my output:
263 4294966987 4294967222 4294967032 64 4294967013 73 4294967004 90
4294967028 83 4294966975 37 4294966961 5 4294966976 82 4294966942
4294967022 4294966994 11 4294967024 29 4294966985 4294966986 4294966954 50
4294966993 4294966974 4294967019 4294967007
This are the values I want to convert to alphabetical characters and see their content.
I don't know what you expect as an answer (you didn't ask a question), but there seems to be one suspicious thing in your code:
char buffer[256];
Here char means signed char. If your code does manipulations on them (like multiplying by 256), it probably doesn't do what you expect (though I can only guess what you expect - your question doesn't mention it).
Try the following:
unsigned char buffer[256];
Also please ask a question (that is, something with a question mark), and give some examples (input, output).
Your basic mistakes were:
after opening the inputfile checking out instead of fp against NULL
fread until eof won't return the number of characters that could be read (I've used fseek and ftell for this purpose)
writing uint values instead of char values to your file
I've fixed them and commented the affected lines appropriate. I also changed the buffer to use dynamic memory allocation instead of static allocation (that's how you can allocate memory for a buffer of a size that is unknown at compile-time). Please try the following code, which will copy all ASCII characters from one file to your output file (which is probably what you meant by 'alphabetical strings'):
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]){
FILE *fp, *out;
char *buffer = NULL; /* use a pointer for dynamic memory allocation */
size_t i = 0, charCount = 0;
fp = fopen("c:/input.txt", "r"); /*read as ascii - not binary */
if(fp != NULL){ /*use 'fp' here 'out' is not initalized */
fseek(fp, 0, SEEK_END); /* go to end of the file */
charCount = ftell(fp) - 1; /* get position */
fseek(fp, 0, SEEK_SET); /* return to the beginning of the file */
buffer = (char*)malloc(sizeof(char)*charCount); /* allocate memory */
fread(buffer, sizeof(char) * charCount, 1, fp); /* reads all characters from the file */
}
out = fopen("c:/output.txt", "w");
if(out != NULL){
for(i = 0; i < charCount; i += 1){ /* loop from 0 to count of characters */
const unsigned char var = buffer[i];
fprintf(out, "%c", var);
}
fclose(out);
}
fclose(fp);
if(buffer != NULL){
free(buffer); /* deallocate memory */
}
return 0;
}

C - Mirror a PPM from left to right

I have to write a program where I take user input for a PPM image and then mirror the image from left to right (basically flipping it over the y-axis). So if the image was <, the new image would now be >. This should not be a 180 degree rotation, as that would make the image upside down. It should still be the same, just reflected.
I have the code here that I used to input and output the PPM, but I don't know how to mirror it. I made a function that would theoretically be used for the mirror code, but I'm not sure if that's the best way to do it either. If you know a better place to put the code, be my guest.
I have researched this topic quite a bit, but was only able to find issues where people needed to rotate the image.
Here is what I have so far:
#include<stdio.h>
#include<stdlib.h> //for fopen()
typedef struct {
unsigned char red,green,blue;
} pixel_t; //struct for pixels
typedef struct {
int x, y;
pixel_t *data;
} PPMImage; //struct for creating the image
#define RGB_COMPONENT_COLOR 255
static PPMImage *readPPM(const char *filename)
{
char buff[16];
PPMImage *img;
FILE *fp;
int c, rgb_comp_color;
fp = fopen(filename, "rb");
if (!fp) {
fprintf(stderr, "Unable to open file '%s'\n", filename);
exit(1);} //opens the ppm and checks to make sure it can be opened
if (!fgets(buff, sizeof(buff), fp)) {
perror(filename);
exit(1);} //read the format of the image
if (buff[0] != 'P' || buff[1] != '6') {
fprintf(stderr, "Invalid image format (must be 'P6')\n");
exit(1);} //checks to see if the format is ppm
img = (PPMImage *)malloc(sizeof(PPMImage));
if (!img) {
fprintf(stderr, "Unable to allocate memory\n");
exit(1);} //allocates the memory needed to form the input image
c = getc(fp);
while (c == '#') {
while (getc(fp) != '\n') ;
c = getc(fp);
}//checks for comments
ungetc(c, fp);
if (fscanf(fp, "%d %d", &img->x, &img->y) != 2) {
fprintf(stderr, "Invalid image size (error loading '%s')\n", filename);
exit(1);} //reads the size of the image, height becomes img->y, and width becomes img->x
if (fscanf(fp, "%d", &rgb_comp_color) != 1) {
fprintf(stderr, "Invalid rgb component (error loading '%s')\n", filename);
exit(1);} //reads how much of each color there is
if (rgb_comp_color!= RGB_COMPONENT_COLOR) {
fprintf(stderr, "'%s' does not have 8-bits components\n", filename);
exit(1);} //makes sure the the component is 8 bits
while (fgetc(fp) != '\n') ;
img->data = (pixel_t*)malloc(img->x * img->y * sizeof(pixel_t));
if (!img) {
fprintf(stderr, "Unable to allocate memory\n");
exit(1);} //allocates the memory need for the pixel data
if (fread(img->data, 3 * img->x, img->y, fp) != img->y) {
fprintf(stderr, "Error loading image '%s'\n", filename);
exit(1);} //reads the pixel data
fclose(fp);
return img;
}
void writePPM(const char *filename, PPMImage *img)
{
FILE *fp;
fp = fopen(filename, "wb");
if (!fp) {
fprintf(stderr, "Unable to open file '%s'\n", filename);
exit(1);} //opens the file for output
//write the header file
//image format
fprintf(fp, "P6\n");
//image size
fprintf(fp, "%d %d\n",img->x,img->y);
// rgb component depth
fprintf(fp, "%d\n",RGB_COMPONENT_COLOR);
// pixel data
fwrite(img->data, 3 * img->x, img->y, fp);
fclose(fp);
}
void mirror(PPMImage *img)
{
//this is where I want to insert the code for mirroring the image
}
int main(int argc, char* argv[]){ //takes command line parameters
PPMImage *image;
char* filename = argv[1];
image = readPPM(filename);
mirror(image);
writePPM("OutputFile.ppm",image); //creates the output file
printf("Press Enter");
getchar();
}
Your mirror() function can work on the image one row at a time. For each row, take the left-most pixel in the row and swap its value with the value of the right-most pixel in the row. Then take the second-left-most pixel and swap its value with the second-right-most pixel, and so on, until the column-positions of the pixels you are swapping "meet in the middle". (Then move on to the next row and do the same thing to it, until you've done all the rows).
Note that if the image contains an odd number of columns, there will be one column in the center of the image that stays unmodified (since it forms the axis around which the mirroring occurs). With an even number of columns, all columns will be swapped.
To mirror image vertically you can use this function:
void mirrorVert(PPMImage *img)
{
int y;
int x;
const int middleX = img->x / 2;
pixel_t tmp;
pixel_t* p;
for (y = 0; y < img->y; ++y)
{
p = img->data + y * img->x;
for (x = 0; x < middleX; ++x)
{
// swap pixels
tmp = p[x];
p[x] = p[img->x - 1 - x];
p[img->x - 1 - x] = tmp;
}
}
}
And to mirror it horizontally:
void mirrorHoriz(PPMImage *img)
{
const int line_size = img->x * sizeof(pixel_t);
const int middle = img->y / 2;
int y;
// allocate swap buffer
pixel_t* buff = (pixel_t*)malloc(line_size);
pixel_t* top;
pixel_t* bottom;
for (y = 0; y < middle; ++y)
{
// swap lines from top and bottom
top = img->data + (y * img->x);
bottom = img->data + ((img->y - y - 1) * img->x);
memcpy(buff, top, line_size);
memcpy(top, bottom, line_size);
memcpy(bottom, buff, line_size);
}
}

Resources