#c #fread #ppm
#c #fread #ppm
Вопрос:
Я прочитал два изображения ppm, и у меня есть структура, в которой хранится вся информация (магическое число, ширина, высота, уровень цветов и пикселей). Я считываю пиксели с помощью fread, но проблема в том, что нам нужно выполнить некоторый тест, чтобы проверить, является ли наш код допустимым и может ли создать новый ppm. Один тест должен быть недействительным (не создавать изображение, потому что количество пикселей отличается от заданного размера), но мой код все равно создает изображение, потому что в fread прочитанных успешных байтов должно быть 83 (условие выхода из кода заключается в том, что если количество байтов отличаетсяиз заданного размера (ширина * высота * 3) мы возвращаем 1 и останавливаем выполнение), но на самом деле он считывает 84 байта, что равно размеру, затем он продолжает выполнять код, вместо того, чтобы блокировать его, и я не понимаю, почему. Ошибка возникает после комментария к прочитанному пикселю. P.s Поскольку код работает, выдавая два изображения, я дважды даю одно и то же недопустимое изображение.
#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", amp;img1.width);
fscanf(file2, "%d", amp;img2.width);
// Take height
fscanf(file1, "%d", amp;img1.height);
fscanf(file2, "%d", amp;img2.height);
// Check size
if (img1.width != img2.width || img1.height != img2.height)
{
fprintf(stderr, "Invalid Dimension.");
return 1;
}
// Take level
fscanf(file1, "%d", amp;img1.level);
fscanf(file2, "%d", amp;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;
}
Комментарии:
1. Не совсем уверен, что вы хотите, чтобы мы с этим делали. Если
fread
возвращает положительное число, которое не является переданнымsize*nmemb
, значит, произошла ошибка или достигнут конец файла. Вы не проверяете наличие ошибок в обоих из двухfread
вызовов. Вы должны лучше объяснить, чего вы пытаетесь достичь, и почему, по вашему мнению, это не работает, по вашей формулировке действительно трудно сказать. Кроме того, учтите тот факт, что код может быть правильным, но содержимое файла может быть нет.2. Кроме того, примечание:
fscanf(file1, "%s", img1.magicNumber);
ожидается ли явное переполнение буфера. Используйте%2s
вместо (да, 2, а не 3, терминатор добавляется автоматически) или лучшеfgets()
.3. Смешивание методов чтения может привести к проблемам. Есть ли новая строка, оставшаяся во входном файле после
fscanf()
(которая считывает текст) иfread()
(которая считывает двоичные данные)?4. Также вы говорите: «во fread прочитанных успешных байтов должно быть 83». Как может быть 83 байта пиксельных данных? 83 — простое число.
5. Трудно сказать, правильно ли вы читаете, не имея под рукой точного файла, который вы пытаетесь прочитать, вызов
fread
выглядит правильным для меня, но вам могут не хватать некоторых байтов, которые не были прочитаны предыдущим вызовомfscanf
as @WeatherVane notes . Вы должны это проверить.