【问题标题】:C - strtok() function assistanceC - strtok() 函数辅助
【发布时间】:2020-07-18 17:23:35
【问题描述】:

软件将一个文件分成三个文件,男性、女性和错误。文本文件已格式化:

名字、姓氏、年龄、性别...但是用空格分隔。

example.txt 如下所示:

Tim Smith 18 M
Jonathon Jones 26 M
Kathy Black 13 F
Sarah Saxby 28 F

我已经根据男性或女性对其进行了拆分,但我正在努力根据年龄使其工作......这是代码,非常感谢任何帮助。

/*
 * C program to split lines of text according to gender and age
*/

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

/* Function declarations */
int isMale(char gender, int age);
int isFemale(char gender, int age);

/* Returns true (1) if the character in the last field is M and age is 4-18 */
int isMale(char gender, int age)
{
    if (gender == 'M' && age<=18 && age>=5)
    {
        // printf("Male %i \n", age);
        return 1;
    }
    return 0;
}

/* Returns true (1) if the character in the last field is F and age is 4-18 */
int isFemale(char gender, int age)
{
    if (gender == 'F') 
    {
        // printf("Female %i \n", age);
        return 1;
    }
    return 0;
}


int main()
{
    /* File pointer to hold reference to different files */
    FILE * fPtrIn,      // Input file
         * fPtrMale,    // Males of school age 
         * fPtrFemale,  // Females of school age
         * fPtrMisc;    // Data not within the given parameters

    // Open all files to perform read/write.
    fPtrIn       = fopen("data/example.txt", "r");
    fPtrMale     = fopen("data/males.txt" , "w");
    fPtrFemale   = fopen("data/females.txt"  , "w");
    fPtrMisc     = fopen("data/erroneus.txt", "w");
        
    // current_char is the current character being read
    char current_char;

    // hoping that too long lines won't come
    char line[300], line_parse[300];

    // Last field is where gender is stored, ret is the token used for strtok()
    char *last_field, *ret;

    // 0 or 1, if the age is outside or within the age limits
    int age;
    int field_count = 0;

    // fopen() return NULL if unable to open file in given mode
    if(fPtrIn == NULL || fPtrMale == NULL || fPtrFemale == NULL || fPtrMisc == NULL)
    {
        // Unable to open file, exit program print result
        printf("Unable to open file.\n");
        printf("Check file exists and permissions are correct.\n");
        exit(EXIT_FAILURE);
    }

    // File open success message
    printf("File opened successfully. \n\n");

    // Read an integer and store read status in success.
    while (fgets(line, sizeof(line), fPtrIn) != NULL)
    {
        // Copy the line for parsing
        strcpy(line_parse, line);

        // Separate the line into tokens
        last_field = ret = strtok(line_parse, " ");
        while (ret != NULL)
        {
            age = 0;
            last_field = ret;
            printf("%s \n", ret);

            if (field_count == 2)
            {
                age = atoi(ret);
            }

            field_count++;
            if (field_count == 4)
            {
                field_count = 0;
            }

            ret = strtok(NULL, " ");
        }

        // Get the first character of the last field
        if (last_field == NULL) current_char = '\0';
        else current_char = last_field[0];

        // Write each line to a separate file
        if (isMale(current_char, age))
            fputs(line, fPtrMale);
        else if (isFemale(current_char, age))
            fputs(line, fPtrFemale);
        else
            fputs(line, fPtrMisc);
    }

    // Close each file
    fclose(fPtrIn);
    fclose(fPtrMale);
    fclose(fPtrFemale);
    fclose(fPtrMisc);
    printf("Data written to files successfully. \n");

    return(0);
}

【问题讨论】:

  • edit问题并逐字显示example.txt文件的前3-4行。
  • 感谢您的回复。 fopen 失败在第 66 行处理,即如果任何文件指针返回 NULL,则以 err 退出...另外,我已经编辑以显示文件的第一行
  • @LewisFarnworth 是的,我后来看到了。在fopens 之后进行检查很奇怪,因此我错过了,但您没有提供文件的前 3-4 行。
  • @user3121023 太棒了!这似乎已经完美解决了问题,谢谢! Jabberwocky 现在你已经指出了它,这很奇怪......对其进行了重组以使其阅读更容易......感谢大家的帮助:D
  • 可能是这种情况...我现在就继续研究。大量的帮助,伙计们!

标签: c strtok


【解决方案1】:

以下建议的代码:

  1. 干净编译
  2. 执行所需的功能
  3. 正确检查和处理来自fopen() 的错误
  4. 不包括那些内容未被使用的头文件。
  5. fopen() 未能将错误消息和系统认为发生错误的文本原因输出到stderr 时,调用perror()

警告:OP 应添加检查以确保在每个输入行中找到足够的字段。当输入行中发现太多字段时,建议的代码已经处理。

现在,建议的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include <ctype.h>


#define MAX_LINE_LEN 300
#define MAX_FIELD_LEN 50

struct lineFields
{
    char firstName[ MAX_FIELD_LEN ];
    char lastName[ MAX_FIELD_LEN ];
    int  age;
    char gender;
};


/* Function declarations */
int isMale(char gender, int age);
int isFemale(char gender, int age);


/* Returns true (1) if the character in the last field is M and age is 4-18 */
int isMale(char gender, int age)
{
    if (gender == 'M' && age<=18 && age>=5)
    {
        // printf("Male %i \n", age);
        return 1;
    }
    return 0;
}


/* Returns true (1) if the character in the last field is F and age is 4-18 */
int isFemale(char gender, int age)
{
    if (gender == 'F' && age<=18 && age>=5) 
    {
        // printf("Female %i \n", age);
        return 1;
    }
    return 0;
}


int main( void )
{
    /* File pointer to hold reference to different files */
    FILE * fPtrIn,      // Input file
         * fPtrMale,    // Males of school age 
         * fPtrFemale,  // Females of school age
         * fPtrMisc;    // Data not within the given parameters

    // Open all files to perform read/write.
    fPtrIn       = fopen("data/example.txt", "r");
    if( !fPtrIn )
    {
        perror( "fopen to read input file failed" );
        exit( EXIT_FAILURE );
    }
    
    fPtrMale     = fopen("data/males.txt" , "w");
    if( !fPtrMale )
    {
        perror( "fopen to write male file failed" );
        exit( EXIT_FAILURE );
    }
    
    fPtrFemale   = fopen("data/females.txt"  , "w");
    if( !fPtrFemale )
    {
        perror( "fopen to write female file failed" );
        exit( EXIT_FAILURE );
    }
    
    fPtrMisc     = fopen("data/erroneus.txt", "w");
    if( !fPtrMisc )
    {
        perror( "fopen to write not of school age file failed" );
        exit( EXIT_FAILURE );
    }
    
    char line[ MAX_LINE_LEN ];
    char line_parse[ MAX_LINE_LEN ];    

    while( fgets( line, sizeof(line), fPtrIn ) )
    {
        // Copy the line for parsing
        strcpy(line_parse, line);

        struct lineFields fields;
        
        int fieldCount = 0;
        // Separate the line into tokens
        char * token = strtok(line_parse, " ");
        while ( token )
        {
            printf( "%s \n", token );

            switch( fieldCount )
            {
                case 0:
                    strcpy( fields.firstName, token );
                    break;
            
                case 1:
                    strcpy( fields.lastName, token );
                    break;
                    
                case 2:
                    fields.age = atoi( token );
                    break;

                case 3:
                    fields.gender = token[0];
                    break;

                default:
                    printf( "too many fields in input: %s\n", line );
                    break;
            }

            fieldCount++;

            token = strtok( NULL, " " );
        }

        // Write each line to a separate file
        if ( isMale( fields.gender, fields.age ) )
            fputs(line, fPtrMale);
        else if ( isFemale( fields.gender, fields.age ) )
            fputs(line, fPtrFemale);
        else
            fputs(line, fPtrMisc);
    }

    // Close each file
    fclose(fPtrIn);
    fclose(fPtrMale);
    fclose(fPtrFemale);
    fclose(fPtrMisc);
    printf("Data written to files successfully. \n");

    return(0);
}

【讨论】:

  • 这比我写的原始解决方案更好地处理坏数据...感谢您的输入!
猜你喜欢
  • 2014-01-23
  • 2021-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多