【问题标题】:fscanf a line from file in cfscanf c 中文件中的一行
【发布时间】:2015-03-17 11:32:03
【问题描述】:

我有一个文件需要从某些变量中读取。信息存储在带有分隔符的文件中;将每一位信息分开。例如:

308163583 ;Adam ;Fro ;22;M ;mogar ;mmMM8675 ;喜欢在沙滩上散步 ;1,2,3,4;

之后我将把这些信息放入一个结构中,但现在不相关了。问题是它扫描一切都很好,直到“喜欢在沙滩上散步”,它停在“喜欢”,只把这个词扫描成描述字符串

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXID 10
#define MAXN 11
#define MAXPAS 7
#define MAXDES 201
#define MAXHOB 4
#define MAXGEN 2
typedef enum { false, true } bool;
typedef struct {

    char* id;
    char* fname;
    char* lname;
    int age;
    char* gender;
    char* username;
    char* password;
    char* description;
    int hobbies;
}User;
typedef struct {
    User *users;
    int num_users;
}List;

void inputFunction(FILE *ifp);
void main() {
    FILE *ifp;
    char mode[] = "r";
    ifp = fopen("input.txt", mode);
    if (ifp == NULL) {
        puts("Can't open input file");
        exit(1);
    }
    inputFunction(ifp);
}

void inputFunction(FILE *ifp) {
    List userList;
    userList.users = (User*)malloc(1 * sizeof(User));
    int i = 0;
    char id[MAXID], fname[MAXN], lname[MAXN], gender[MAXGEN],
       username[MAXN], password[MAXPAS], description[MAXDES];
    int age, hobbies[MAXHOB];
    while (fscanf(ifp, "%s ;%s ;%s ;%d;%s ;%s ;%s ;%s;%d,%d,%d,%d", id,
      fname, lname, &age, gender, username, password, description,
      &hobbies[0], &hobbies[1], &hobbies[2], &hobbies[3])!=EOF)
    {

    }
}

【问题讨论】:

  • scanf() 会忽略空格字符,%s 指令会在找到空格时停止。
  • 这是int main(void) 而不是void main(void)
  • int hobbies; 错字?
  • @BLUEPIXY:“爱好”是“爱好”的复数形式。类似于“婴儿”、“女士”等。
  • 添加到@iharob 所说的内容:因此,在描述已填充“like”之后输入中的下一个“token”是“to”,它是非数字的,不适合 %d 所以那个 scanf() 在那里中止。

标签: c string file scanf


【解决方案1】:

@Jens:对于当前的分配,我不需要检查所有字段是否正确,它是给定的。 找到了不同的解决方案:

List loadFile(FILE *ifp) {
    int i = 0;
    List userList;
    userList.users = NULL;
    char id[MAXID], fname[MAXN], lname[MAXN], gender[MAXGEN], username[MAXN], password[MAXDES], description[MAXDES];
    int age, hobbies[MAXHOB];
    while (fscanf(ifp, "%s ;%s ;%s ;%d;%s ;%s ;%s ;%200[^;];%d,%d,%d,%d;\n", id, fname, lname, &age, gender, username, password, description, &hobbies[0], &hobbies[1], &hobbies[2], &hobbies[3]) != EOF)
    {

【讨论】:

    【解决方案2】:

    这是因为 scanf 的 %s 被指定为匹配非空白字符序列。您希望它扫描 一系列非分号字符。留作练习 :-) 提示:阅读手册并了解 %[...] 说明符是如何工作的。

    还要注意

    while (fscanf(...) != EOF)
    

    是一个巨大的错误,因为 fscanf 返回成功转换项目的数量,即如果没有转换任何项目,则返回 0,如果转换所有项目,则返回 12。测试 EOF 您无法检测正确转换的项目是否少于 12 个。您应该认真考虑从上到下阅读scanf/fscanf manual from。它很有启发性,并且会在你的整个编程生涯中一次又一次地证明是有价值的。

    【讨论】:

    • 对不起,我只是破坏了你的锻炼。要我删除答案吗? :-(
    • @MikeofSST 不,很高兴看到有不止一种方法可以做到这一点。听起来很糟糕,不是吗?我会赞成你这么有礼貌的提问。
    • @MikeofSST 你没有告诉他要使用什么格式字符串......所以你没有破坏练习,还有很多其他方法可以做到,但是有 12 个标记解析一个疑问,任何其他方法都会击败 fscanf()fgets() sscanf() 组合,后者稍微好一些。
    【解决方案3】:

    通常,scanf() 函数只读取字符串直到空白字符。您应该尝试使用 strtok() 函数让流达到指定的分隔符。

    【讨论】:

      【解决方案4】:

      您可以使用strtok 函数使用您自己的分隔符集来分割行。

      /* strtok example */
      #include <stdio.h>
      #include <string.h>
      
      int main ()
      {
          const char delims[] = ";"; //List of delimiters
          char str[] = "308163583 ;Adam ;Fro ;22;M ;mogar ;mmMM8675 ;like to walk on the beach ;1,2,3,4;";
          char * pch;
          // Split the string at specified set of delimters
          pch = strtok (str,delims);
          while (pch != NULL)
          {
              // Do whatever you need to process the token here
              printf ("%s\n",pch);
      
              // Find the next token
              pch = strtok (NULL,delims);
          }
          return 0;
      }
      

      【讨论】:

      • 但如果我从字符串中读取信息,我没有包含所有信息的“str”。
      • 您可以在处理之前一次将整行从文件中读入字符串缓冲区。或者选择使用显式字符串分隔符的其他 fscanf 答案之一。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-03
      • 2022-01-14
      • 2011-03-22
      • 1970-01-01
      • 1970-01-01
      • 2021-05-12
      • 2017-06-14
      相关资源
      最近更新 更多