【问题标题】:Print the user input strings into a least sized user input files将用户输入字符串打印到最小的用户输入文件中
【发布时间】:2020-05-28 06:40:50
【问题描述】:

程序应该读取文件名列表,打开这些文件并将它们的句柄放入结构数组中,然后使用结构数组中包含的句柄读取字符串并将连续的字符串行打印到最小的文件中。

我的程序将所有行的数据仅放入一个文件,该文件最初是最小的,这是错误的,因为每次将数据打印到文件中时,它都应该是最小的文件。这是我的程序:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <math.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;
 }
 FILE* fp;
 fp = fopen(filename, "ab");
 if (fp == NULL) {
     return 2;
 }
 long int res = ftell(fp);
 fclose(fp);
 f->size = res;
 f->f = fopen(filename, "ab+");
 if (fp == NULL) {
     return 2;
 }
 return 0;
}
struct file_t* find_min(const struct file_t* files, int size) {
 if (files == NULL || size <= 0) {
     return NULL;
 }
 int x = (files + 0)->size, i = 0, index = 0;
 for (i = 0; i < size; i++) {
     if ((files + i)->size <= x) {
         x = (files + i)->size;
         index = i;
     }
 }
 return (struct file_t*)(files + index);
}
int main() {
 puts("Input files' names:");
 char tab[100];
 int num = 0;
 while(1==1){
     if(fgets(tab, 100, stdin)==NULL||*tab=='\n'){
         if (num == 0) {
             printf("Couldn't open file");
             return 4;
         }
         break;
     }
     int index=strlen(tab);
     *(tab+index-1)='\x0';
     if (strlen(tab) > 30) {
         *(tab + 30) = '\x0';
     }
     if (open_file((t + num), tab) > 0) {
     }
     else {
         num++;
     }
 }
 if (num == 0) {
     printf("Couldn't open file");
     return 4;
 }
 char str[1000];
 printf("Input text:");
 *str = '\x0';
 while (fgets(str, 1000, stdin)==NULL||*str!='\n') {
     int index=strlen(str);
     *(str+index-1)='\x0';
     struct file_t* p = find_min(t, num);
     fwrite(str, sizeof(char), strlen(str), p->f);
 }
 for (int i = 0; i < num; i++) {
     close_file(t + i);
 }
 printf("File saved");
 return 0;
}



【问题讨论】:

  • 发布问题后,社区将尝试解决您的问题。您不能在两者之间更新问题。如果你想做。提及编辑并做任何你想做的事。现在我的回答对社区毫无意义!

标签: c file structure file-structure


【解决方案1】:

您需要解决一些严重的错误。

事实上,即使fflush() 也行不通。 fflush 是为刷新输出流而设计的,它对输入流的行为取决于实现。更多详情请参考此链接stdinflush

  • scanf("%[^\n]s", tab)

如果您在循环中或多次使用它,则只有第一次读取会成功。原因是,\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

注意从第一个循环中断(文件输入)。您需要输入空格,然后按回车键(您可以对此进行调整)。

【讨论】:

    【解决方案2】:

    当您写入文件时,您在哪里更新 file_t->size? 你这样称呼:

    fwrite(str, sizeof(char), strlen(str), p->f);

    但在那之后你应该执行 p->size += strlen(str) 来更新它的大小,否则所有文件大小都会设置为初始值,因此所有字符串都会写入单个文件。

    至于获取垃圾数据,请尝试在 while 循环中打印您从 scanf 读取的字符串。

    您正在使用 scanf 读取字符直到 '\n',但您没有读取 '\n' 本身。您还需要在该循环中使用fseek(stdin, 0, SEEK_END);

    最后,你为什么要使用这样的语法:

    (文件 + i)->大小

    当你可以像这样更干净地调用它时:

    files[i].size

    因此,您的代码真的很难阅读。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-19
      • 2013-03-31
      相关资源
      最近更新 更多