字符串标记化麻烦

时间:2016-11-14 08:08:34

标签: c string tokenize

我有这个代码,它接受一个文件“schedule.txt”,然后让用户输入一个类,它显示了这个类的时间,不幸的是我在标记化方面遇到了困难......

int main(int argc, char *argv[]) 
{
    // Declare variables
    FILE *inp = NULL;
    char str[200];
    char class[7][20];
    double times[15];
    double times2[15];
    int i;
    const char delim[] = " 0123456789:";

    // Open the file, quit if it fails...
    inp = fopen(argv[1], "r");
    if(inp == NULL){
        fprintf(stderr, "Unable to open file: %s\n", argv[1]);
        exit(1);
    }

    // Read the file and tokenize it for names of classes and times
    i = 0;
    while(fgets(str, 200, inp) != NULL){
        str[strlen(str)-1] = '\0';

        char *classToken = strtok(str, "0123456789");
        strcpy(class[i], classToken);

        char *timeToken = strtok(NULL, " ");
        times[i] = atof(timeToken);

        i++;
    }

    for(i = 2; i < 6; i++){
        printf("%f\n", times[i]);
    }

    return 0;
}

我希望将文件标记为两个不同的数组,一个包含类的字符串,另一个是没有“:”的时间,但是当我将分隔符作为数字时它不允许我使用第一个数字的时间,但是当分隔符是“”时,字符串数组也包含时间,我怎么能这样做? 该文件如下所示

 Class Schedule
 Class          Time
 Physics            15:30
 Calculus       9:00
 Biology            14:30
 Chemistry      11:30

2 个答案:

答案 0 :(得分:1)

你有两个问题:第一个是<script language='JavaScript'> <!-------------------------------------------------------------------- var Memory = "0"; // initialise memory variable var Current = ""; // and value of Display ("current" value) var Operation = 0; // Records code for eg * / etc. var MAXLENGTH = 8; // maximum number of digits before decimal! function AddDigit(dig){} //ADD A DIGIT TO DISPLAY (keep as 'Current') if (Current.indexOf("!") == -1) {}//if not already an error Current = Current + dig; } else { Current = "Hint! Press 'Clear'"; //Help out, if error present. }; document.calc.display.value = Current.charAt(0).toUpperCase() + Current.substr(1);; } function Clear() {} //CLEAR ENTRY Current = ""; document.calc.display.value = Current; } function backspace() { Current = document.calc.display.value; var num = Current; Current = num.slice(0,num.length-1); document.calc.display.value = Current; } //---------------------------------------------------------------> </script> 修改字符串,并用字符串终止符替换找到的标记分隔符。

因此,如果您的输入字符串看起来像strtok,则在第一次调用"Physics 15:30"后,它将被修改为strtok

解决方法是使用 space (或tab,或两者)作为标记分隔符,然后在获取下一个标记时跳过空格。

第二个问题是您使用"Physics \05:30"来获取时间。时间不是浮点值,尤其是当前编号系统不使用atof来分隔整数和小数部分。更不用说:作为浮点数将是15:30,它与15.30不同(后者与时间15.50不同)。

这两个问题的简单解决方案是使用sscanf代替将该行解析为两个字符串

答案 1 :(得分:0)

主要问题是分隔符不合适 具体来说,它将标记为如下。

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

typedef struct schedule {
    char className[20];
    int  time;//minute
}Schedule;

int main(int argc, char *argv[]) {
    FILE *inp;
    char line[200];
    char title[32];
    char fieldName[2][20];
    Schedule schedule[7];
    int i;

    if(argc != 2){
        fprintf(stderr, "Usage : %s filename\n", argv[0]);
        exit(1);
    }
    inp = fopen(argv[1], "r");
    if(inp == NULL){
        fprintf(stderr, "Unable to open file: %s\n", argv[1]);
        exit(1);
    }

    fgets(title, sizeof title, inp);
    fgets(line, sizeof line, inp);
    char *token;
    token = strtok(line, " \t\n");
    strcpy(fieldName[0], token);
    token = strtok(NULL, " \t\n");
    strcpy(fieldName[1], token);

    i = 0;
    while(i < 7 && fgets(line, sizeof line, inp)){
        token = strtok(line, " \t\n");//maybe "\t\n"
        strcpy(schedule[i].className, token);
        token = strtok(NULL, " \t\n");
        schedule[i].time = atoi(token)*60 + atoi(strchr(token, ':')+1);//"hh:mm" : hh * 60 + mm 
        i++;
    }
    int n = i;

    printf("%s", title);
    printf("%-20s%s\n", fieldName[0], fieldName[1]);
    for(i = 0; i < n; i++){
        printf("%-20s%02d:%02d\n", schedule[i].className, schedule[i].time/60, schedule[i].time%60);
    }

    return 0;
}