簡體   English   中英

有人可以解釋這段代碼如何在不使用 strtok 的情況下拆分字符串嗎?

[英]can someone explain this code how to split the string without using strtok?

void filename()
{
    char c[50];
    FILE *fp;
    char d;
    int i;
    int s[5];
    printf("Enter the file name: ");
    scanf("%s", c);

    fp = fopen(c, "r");
    count = 0;
    fscanf(fp, "%d$", &id[count]);

    while(!feof(fp))
    {
        fscanf(fp, "%[^$]s)", names[count]);
        for(i = 0; i < 5; i++)
        {
            fscanf(fp, "%c", &d);
            fscanf(fp, "%d", &s[i]);
        }
        grades[count] = ((double)s[0] * 0.15 + (double)s[1] * 0.15 + (double)s[2] * 0.25 + (double)s[3] * 0.1 + (double)s[4] * 0.35);
        count++;
        fscanf(fp, "%d$", &id[count]);
    }
    fclose(fp);
}

請向我解釋如何在不使用strtok的情況下拆分字符串,例如fscanf(fp, "%[^$]s)", names[count]);

我怎樣才能做到這一點?

你的代碼有很多問題。 您錯誤地使用feof 您必須始終將寬度修飾符添加到讀取字符串的轉換說明符。 您必須檢查 scanf 返回的值以確保它成功匹配輸入。 我已嘗試對您用來演示預期輸入形式的格式字符串進行最小的更改。 也許讀取未使用的字符 'd' 是嘗試匹配$ ,但這不是在您的代碼中強加的(我已在輸入中插入d以供fscanf(fp, "%c", &d)讀取) . 由於您沒有提供預期輸入的樣本,我做了一些假設。 如果下面顯示的輸入與您的預期輸入不匹配,您應該修改格式字符串。 我猜你不打算匹配文字s) ,但你當前的代碼需要在輸入中。 而不是更冗長且可能措辭不佳的解釋嘗試:

$ gcc a.c
$ cat input
1$Alice $s)d 10d 5d 10d 15d 7
2$Bob   $s)d 11d 6d 11d 16d 8
2$Chuck $s)d 12d 7d 12d 17d 9
$ echo input | ./a.out
Enter the file name: grade for Alice  is 8.700000
grade for Bob    is 9.700000
grade for Chuck  is 10.700000
$ cat a.c
#include <stdio.h>
#include <stdlib.h>

int count;
int id[64];
char names[64][256];
double grades[64];

/* "filename" is a terrible name for a function that reads and parses data */
void 
filename(const char *prompt)
{
        char path[50];
        FILE *fp;
        char d;
        int i;
        double weight[] = { 0.15, 0.15, 0.25, 0.1, 0.35 };
        printf("%s: ", prompt);
        scanf("%49s", path);  /* Always use a width modifier with %s!! */

        if( (fp = fopen(path, "r")) == NULL ){
                perror(path);
                exit(EXIT_FAILURE);
        }
        count = 0;

        while(
                count < 64
                && 1 == fscanf(fp, "%d$", id + count)
                && 1 == fscanf(fp, "%255[^$]$s)", names[count])
         ){
                grades[count] = 0;

                for(i = 0; i < 5; i++) {
                        int s;
                        if( 0
                                || 1 != fscanf(fp, "%c", &d)
                                || 1 != fscanf(fp, "%d", &s)
                        ){
                                fprintf(stderr, "Unexpected input\n");
                                goto end;
                        }
                        grades[count] += (double)s * weight[i];
                }
                printf("grade for %s is %f\n", names[count], grades[count]);
                count += 1;
        }
end:
        fclose(fp);
}

int
main(void)
{
        filename("Enter the file name");
        return 0;
}

我猜你的意圖是做更多類似的事情:

$ cat input2
1$Alice$  10 $ 5 $ 10 $ 15 $ 7
2$Bob$    11 $ 6 $ 11 $ 16 $ 8
3$Chuck$  12 $ 7 $ 12 $ 17 $ 9

可以解析為:

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

int count;
int id[64];
char names[64][256];
double grades[64];

void
parse_file(FILE *fp)
{
        double weight[] = { 0.15, 0.15, 0.25, 0.1, 0.35 };
        count = 0;
        while(
                count < 64
                && 1 == fscanf(fp, "%d", id + count)
                && 1 == fscanf(fp, "$ %255[^$]", names[count])
         ){
                grades[count] = 0;

                for( int i = 0; i < 5; i += 1 ){
                        int s;
                        if( 1 != fscanf(fp, " $%d", &s) ){
                                fprintf(stderr, "Unexpected input\n");
                                exit(EXIT_FAILURE);
                        }
                        grades[count] += (double)s * weight[i];
                }
                printf("grade for %s is %f\n", names[count], grades[count]);
                count += 1;
        }
}

int
main(int argc, char **argv)
{
        const char *path = argc > 1 ? argv[1] : NULL;
        FILE *fp = path ? fopen(path, "r") : stdin;
        if( fp == NULL ){
                perror(path);
                exit(EXIT_FAILURE);
        }
        parse_file(fp);
        fclose(fp);
        return EXIT_SUCCESS;
}

請注意,這是功能性的,但肯定不應該被認為是健壯的。 (例如,如果最后一行有額外的 $,程序只會中止而沒有錯誤消息。)完全不清楚你想要什么行為,所以我不打算修改它,而只是說明一下scanf絕對是錯誤的工具。 它只是一個只能用於教育目的的玩具。 可悲的是,它永遠不應該用於教育目的,而實際上只是一個用來迷惑新手的玩具。 請閱讀http://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM