Есть некоторые критические ошибки, которые необходимо исправить.
На самом деле даже fflush()
не будет работать. fflush
- это то, что разработано для очистки выходных потоков, и его поведение с входными потоками зависит от реализации. Пожалуйста, обратитесь к этой ссылке для получения дополнительной информации stdinflu sh
Если вы используете это в al oop или несколько раз, только первое чтение будет успешным. Причина в том, что символ \n
исключен из предыдущего ввода, и, как было сказано ранее, fflush()
может не удастся удалить этот \n
. Дальнейшие вызовы scanf()
просто вернутся, ничего не читая.
'\0x'
Если вы собираетесь использовать это как терминатор строки, то это не так. Это многосимвольная константа с целым числом 120
. Ниже приведен нечеткий тестовый прогон
Код
#include <stdio.h>
int main()
{
if ('\0' == '\0x' )
printf("both are same\n");
printf("%d",'\0x');
}
Предупреждения компиляции
test.c: In function ‘main’:
test.c:5:14: warning: multi-character character constant [-Wmultichar]
5 | if ('\0' == '\0x' )
| ^~~~~
test.c:8:14: warning: multi-character character constant [-Wmultichar]
8 | printf("%d",'\0x');
| ^~~~~
Вывод
120
1) Вы должны вычислять размер файла каждый раз в find_min()
, поскольку он изменяется всякий раз, когда вы записываете данные в файл.
2) fwrite()
фактически не выгружает данные в файл сразу. Вам необходимо позвонить по номеру fflush()
.
Это измененный код после решения вышеуказанных проблем.
Код
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <math.h>
#include <sys/stat.h>
struct file_t
{
FILE* f;
int size;
}t[5];
void close_file(struct file_t* f) {
if (f == NULL || f->f == NULL) {
}
else {
fclose(f->f);
}
}
int open_file(struct file_t* f, const char* filename) {
if (f == NULL || filename == NULL) {
return 1;
}
f->f = fopen(filename, "a");
if (f->f == NULL)
return 2;
struct stat statbuf;
fstat(fileno(f->f), &statbuf);
f->size = statbuf.st_size;
return 0;
}
struct file_t* find_min(const struct file_t* files, int size) {
if (files == NULL || size <= 0) {
return NULL;
}
struct stat statbuf;
fstat(fileno(files->f), &statbuf);
int x = statbuf.st_size, i = 0, index = 0;
for (i = 0; i < size; i++) {
fstat(fileno((files+i)->f), &statbuf);
if (statbuf.st_size < x) {
x = statbuf.st_size;
index = i;
}
}
return (struct file_t*)(files + index);
}
int main() {
puts("Input files' names:");
char tab[100];
int num = 0;
while(1){
int c;
while (1) {
c = getc(stdin);
if (c == EOF || c == ' ')
goto user_input;
if(c != '\n')
break;
}
tab[0] = c;
if (scanf("%[^\n]s", tab+1) == EOF)
break;
if (*tab == '\0') {
if (num == 0) {
printf("Couldn't open file");
return 4;
}
break;
}
if (strlen(tab) > 30) {
*(tab + 30) = '\0';
}
if (open_file((t + num), tab) > 0) {
}
else {
num++;
}
*tab = '\0';
}
user_input:
if (num == 0) {
printf("Couldn't open file");
return 4;
}
fflush(stdin);
char str[1000];
printf("Input text:\n");
*str = '\0';
while(1) {
int c;
while(1) {
c = getc(stdin);
if (c == EOF)
goto main_exit;
if (c != '\n')
break;
}
str[0] = c;
if (scanf("%[^\n]s", str+1) == EOF)
break;
struct file_t* p = find_min(t, num);
fwrite(str, sizeof(char), strlen(str), p->f);
fflush(p->f);
}
main_exit:
for (int i = 0; i < num; i++) {
close_file(t + i);
}
printf("File saved");
return 0;
}
Терминальная сессия
$ ./a.out
Input files' names:
test file1.txt
test file2.txt
' '(NOTE: Space character inputted before pressing enter.)
Input text:
this is
stackoverflow
File saved
тестовый файл1.txt
this is
тестовый файл2.txt
stackoverflow
Примечание по взлому с первого l oop (ввод файлов). Вам нужно ввести пробел и затем нажать Enter (это можно исправить).