如何在C a a中将用户输入添加到文本文件中特定行的末尾

jv4diomz  于 2023-01-25  发布在  其他
关注(0)|答案(1)|浏览(85)

我正在开发一个休假管理系统,我已经将员工的详细信息写入了一个文本文件,但是现在我想通过将员工ID作为输入将休假类型添加到特定行的末尾。

James720 | Name: James | Department: Administration | Leave Balance: 30
Kyle790 | Name: Kyle | Department: Administration | Leave Balance: 30

这就是我写入文件的方式(见上图)
目标是:
x一个一个一个一个x一个一个二个x
我尝试了此操作,但更新的文本文件为:

JMedical0 | Name: James | Department: Administration | Leave Balance: 30
Kyle226 | Name: Tariq | Department: Management | Leave Balance: 30

如上所示,单词Medical被添加到开头以替换ID

92vpleto

92vpleto1#

您的方法将不起作用,因为您的方法只允许您覆盖文件的一部分,而不允许插入任何内容。
另一个问题是在标准C中

fseek(file, -i, SEEK_CUR);

不允许,因为您是以文本模式打开文件的。在文本模式下,fseek的唯一合法偏移量是0或上一次调用ftell的返回值。有关详细信息,请参阅fseekthe documentation。但是,如果您使用的是POSIX平台(如Linux),则这些限制不适用,允许使用此行。
虽然是some file systems do support inserting data into the middle of a file,但这并不容易,而且一般要求插入的数据块是某个大小的倍数,因此,我不建议您使用这种解决方案。
写一个添加了所需数据的新文件会更容易一些。如果你愿意,你可以删除旧文件,然后用旧文件的名字重命名新文件。
我建议您打开两个文件,一个输入文件"staff.txt"和一个输出文件"staff_new.txt"。以"r"模式打开输入文件,以"w"模式打开输出文件。注意,这将覆盖文件"staff_new.txt"。请不要对任何文件使用"r+""w+"。然后,您可以使用fgets逐行读取输入文件(正如您已经在做的那样),然后将该行复制到输出文件中。之后,您可以在开始复制下一行之前,将所需的所有信息添加到输出文件中。
下面是一个例子:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

//forward declarations
void get_line_from_user( char prompt[], char buffer[], int buffer_size );
bool get_line_from_stream( char buffer[], int buffer_size, FILE *fp );

int main( void )
{
    char line[200], id[100], leave_type[100];
    FILE *input, *output;

    //attempt to open input file
    input = fopen( "staff.txt", "r" );
    if ( input == NULL )
    {
        fprintf( stderr, "Error opening input file!\n" );
        exit( EXIT_FAILURE );
    }

    //attempt to open output file
    output = fopen( "staff_new.txt", "w" );
    if ( output == NULL )
    {
        fprintf( stderr, "Error opening output file!\n" );
        exit( EXIT_FAILURE );
    }

    //get all requiredinput from the user
    get_line_from_user(
        "Please confirm staff ID: ",
        id, sizeof id
    );
    get_line_from_user(
        "Enter leave type: ",
        leave_type, sizeof leave_type
    );

    //iterate through each line of the file
    while ( get_line_from_stream( line, sizeof line, input ) )
    {
        //copy line to output file
        fputs( line, output );

        //add leave type, if appropriate
        if ( strstr( line, id ) != NULL )
        {
            fprintf( output, " | Type of Leave: %s", leave_type );
        }

        //write newline character to output file
        putc( '\n', output );
    }

    fclose( output );
    fclose( input );
}

//This function will read exactly one line of input from the
//user. If the line is too long to fit in the buffer, then the
//function will automatically reprompt the user for input. On
//failure, the function will never return, but will print an
//error message and call "exit" instead.
void get_line_from_user( char prompt[], char buffer[], int buffer_size )
{
    for (;;)
    {
        char *p;

        //prompt user for input
        fputs( prompt, stdout );

        //attempt to read one line of input
        if ( fgets( buffer, buffer_size, stdin ) == NULL )
        {
            printf( "Error reading from input!\n" );
            exit( EXIT_FAILURE );
        }

        //attempt to find newline character
        p = strchr( buffer, '\n' );

        //make sure that entire line was read in (i.e. that
        //the buffer was not too small to store the entire line)
        if ( p == NULL )
        {
            int c;

            //a missing newline character is ok if the next
            //character is a newline character or if we have
            //reached end-of-file (for example if the input is
            //being piped from a file or if the user enters
            //end-of-file in the terminal itself)
            if ( !feof(stdin) && (c=getchar()) != '\n' )
            {
                printf( "Input was too long to fit in buffer!\n" );

                //discard remainder of line
                do
                {
                    if ( c == EOF )
                    {
                        printf( "Error reading from input!\n" );
                        exit( EXIT_FAILURE );
                    }

                    c = getchar();

                } while ( c != '\n' );

                continue;
            }
        }
        else
        {
            //remove newline character by overwriting it with
            //null character
            *p = '\0';
        }

        //input was ok, so break out of loop
        break;
    }
}

//This function will read exactly one line of input and remove the
//newline character, if it exists. On success, it will return true.
//If this function is unable to read any further lines due to
//end-of-file, it returns false. If it fails for any other reason, it
//will not return, but will print an error message and call "exit"
//instead.
bool get_line_from_stream( char buffer[], int buffer_size, FILE *fp )
{
    char *p;

    //attempt to read one line from the stream
    if ( fgets( buffer, buffer_size, fp ) == NULL )
    {
        if ( ferror( fp ) )
        {
            fprintf( stderr, "Input error!\n" );
            exit( EXIT_FAILURE );
        }

        return false;
    }

    //make sure that line was not too long for input buffer
    p = strchr( buffer, '\n' );
    if ( p == NULL )
    {
        //a missing newline character is ok if the next
        //character is a newline character or if we have
        //reached end-of-file (for example if the input is
        //being piped from a file or if the user enters
        //end-of-file in the terminal itself)
        if ( !feof(fp) && getc(fp) != '\n' )
        {
            printf( "Line input was too long!\n" );
            exit( EXIT_FAILURE );
        }
    }
    else
    {
        //remove newline character by overwriting it with a null
        //character
        *p = '\0';
    }

    return true;
}

请注意,在上面的程序中,我没有像您在问题中那样使用带有%s说明符的scanf,因为这样只能读取单个单词,而不是整行。此外,通常不推荐使用scanf作为用户输入。根据我的经验,通常使用fgets会更好,我为此创建了函数get_line_from_user,它会自动删除换行符并执行额外的输入验证,我还创建了一个类似的函数get_line_from_stream,它也会自动删除换行符,但在输入错误时不会重新提示用户,第二个函数用于从文件中读取,而不是从用户那里读取。
此程序具有以下行为:
当用户输入

Please confirm staff ID: James720
Enter leave type: Medical

并且staff.txt的含量为

James720 | Name: James | Department: Administration | Leave Balance: 30
Kyle790 | Name: Kyle | Department: Administration | Leave Balance: 30

则将以下输出文件写入staff_new.txt

James720 | Name: James | Department: Administration | Leave Balance: 30 | Type of Leave: Medical
Kyle790 | Name: Kyle | Department: Administration | Leave Balance: 30

相关问题