0

我有一个功能可以读取以下格式的文本文件

 string int int
 string int int
 string int int

我想编写一个函数,将文本文件中的值分配给变量,但在某些情况下,文本文件的格式会是

string int
string int
string int

在这种情况下,我想将最后一个 int 变量的值设置为 1。到目前为止,我的代码适用于第一个示例,但我有点坚持让第二个场景工作:

void readFile(LinkedList *inList, char* file)
    {
    char tempName[30];
    int tempLoc, tempNum;

    FILE* f;
    f = fopen(file, "r");
    if(f==NULL) 
        {
        printf("Error: could not open file");
        }
    else
        {
        while (fscanf(f, "%s %d %d\n", tempName, &tempLoc, &tempNum) != EOF)
            {
            insertFirst (inList, tempName, tempLoc, tempNum);
            }
        }   
    }
4

1 回答 1

3

在第二种情况下,fscanf 将返回 2 而不是 3。因此您可以像这样重写代码:

while (1) {
    int ret = fscanf(f, "%s %d %d\n", tempName, &tempLoc, &tempNum);
    if (ret == EOF) {
        break;
    }
    if (ret == 2) {
        tempNum = 1;
    } else if (ret != 3) {
        // line appear invalid, deal with the error
    }
    insertFirst (inList, tempName, tempLoc, tempNum);

}

一种更老套的方法是在调用 fscanf 之前将 tempNum 设置为 1,然后像上面那样检查 EOF。但我认为上面的代码更清晰。

编辑:为避免溢出,这会更好。代码会执行得更好,但这更难编写。就像上面一样,我没有为错误条件编写任何代码,但你肯定想处理它们

char lineBuf[255];
while (fgets(lineBuf, sizeof(lineBuf), f) != NULL) {
    int spaceIdx, ret;
    const int len = strlen(lineBuf);
    if (len == (sizeof(lineBuf) - 1) {
         // line is too long - either your buf is too small and you should tell the user
         // that its input is bad
         // I recommend to treat this as an error
    }
    lineBuf[len - 1] = '\0'; // remove \n
    --len;  // update len, we've removed one character
    if (isspace(*lineBuf)) {
        // error, line should not start with a space
    }
    spaceIdx = strcspn(lineBuf, "\t ");
    if (spaceIdx == len) {
        // error, no space in this line
    }

    // Ok, we've found the space.  Deal with the rest.
    // Note that for this purpose, sscanf is a bit heavy handed (but makes the code
    // simpler). You could do it with strtol.
    // Also, the first space in the format string is important, so sscanf skips 
    // all the space at the beginning of the string.  If your format requires only
    // one space between fields, you can do sscanf(lineBuf + spaceIdx + 1, "%d %d"...

    ret = sscanf(lineBuf + spaceIdx, " %d %d", &tempLoc, &tempNum);
    if (0 == ret) {
        // error, no ints
    }
    else if (1 == ret) {
        tempNum = 1;
    }

    // at that point, you could copy the first part of lineBuf to tempName, but then
    // you have to deal with a potential overflow (and spend time on an useless copy),
    // so use lineBuf instead

    lineBuf[spaceIdx] = '\0';

    insertFirst (inList, lineBuf, tempLoc, tempNum);
}
于 2013-05-19T04:32:53.437 回答