【问题标题】:c fgets retrieves the whole array?c fgets 检索整个数组?
【发布时间】:2014-02-07 13:17:20
【问题描述】:

我有一个名为 phobebook 的文件,我在其中检索我拥有的联系人数量(这里的 int 是在变量 cc 上分配的),然后保存了姓名、地址等。 问题是当我显示信息时,细节在那里,但它们用新行分隔。我试图把 \0 但它似乎不起作用。

typedef struct myphonebook{
  char name[31];
  char address[101];
  char cellphone[11];
  char email[21];
} Myphonebooktype;

FILE*db;

db = fopen("db.txt", "r");

fscanf(db, "%d" , &cc);

pb = (Myphonebooktype*)malloc(cc*sizeof(Myphonebooktype));
addcounter = cc;

for(i = 0; i<cc ; i++){
  size_t lenn = strlen(pb[i].name);
  if (pb[i].name[lenn - 1] == '\n') {
    pb[i].name[lenn - 1] = '\0';
  }
  fgets(pb[i].name, sizeof(pb[i].name), db);

  size_t lena = strlen(pb[i].address);
  if (pb[i].address[lena - 1] == '\n') {
    pb[i].address[lena - 1] = '\0';
  }
  fgets(pb[i].address, sizeof(pb[i].address), db);

  size_t lenc = strlen(pb[i].cellphone);
  if (pb[i].cellphone[lenc - 1] == '\n') {
    pb[i].cellphone[lenc - 1] = '\0';
  }
  fgets(pb[i].cellphone, sizeof(pb[i].cellphone), db);

  size_t lene = strlen(pb[i].email);
  if (pb[i].email[lene - 1] == '\n') {
    pb[i].email[lene - 1] = '\0';
  }
  fgets(pb[i].email, sizeof(pb[i].email), db);
}

【问题讨论】:

  • 也尝试检查\r,即如果找到\n 或\r,则替换为\0
  • 2 bruce wayne mansion 88888888 batman@hero.com john yeung 46 linggo 9393293226 my@yahoo.com 我的 db.txt 看起来像这样
  • @user3266210 把它放在问题中,不可能理解评论中的确切结构。
  • 如果你在做lenn = strlen(pb[i].name) 那么我想pb[i].name[lenn - 1] 将永远是\0...

标签: c file fgets strlen


【解决方案1】:

您不能在新分配的Myphonebooktype 数组中引用数据在初始化它之前。您调用strlen() 都会产生未定义的行为,因为结构成员尚未初始化。

另外,don't cast the return value of malloc() in C。

【讨论】:

    【解决方案2】:

    正如@unwind 所说,代码在写入之前引用了未初始化的数据

      size_t lenn = strlen(pb[i].name);  // pb[i].name contents are not defined yet.
      ...
      fgets(pb[i].name, sizeof(pb[i].name), db);
    

    建议创建一个函数来处理行的读取。

    void ReadLine(FILE *db, char *dest, size_t size) {
      char buffer[size+2];
      dest[0] = '\0';
      if (fgets(buffer, sizeof buffer, db) != NULL) {
        size_t len = strlen(buffer);
        // Get rid of potential \n
        if (len > 0 && buffer[len-1] == '\n') buffer[--len] = '\0';
        strncpy(dest, buffer, size);
      }
    } 
    
    
    for(i = 0; i<cc ; i++) {
      ReadLine(db, pb[i].name, sizeof pb[i].name);
      ReadLine(db, pb[i].address, sizeof pb[i].address);
      ReadLine(db, pb[i].cellphone, sizeof pb[i].cellphone);
      ReadLine(db, pb[i].email, sizeof pb[i].email);
    }
    

    可以添加到ReadLine() 以在读取NULL、行过长或@MadHatter 提出的\r 问题时返回EOF。这一切都在一个功能中,因此更易于维护和增强代码。

    【讨论】:

    • 对不起这个菜鸟问题,我应该先 fgets 然后使用这个 readline 函数吗?
    • @user3266210 不,fgets() 并入ReadLine()。
    • 好的...但是我的 dp(文件*dp)在哪里,我应该用 dp 替换 Readline() 中的标准输入吗?
    • 哇,这很有效,就像魔术一样:) tnx。它甚至解决了我没有检索到一个联系人的电子邮件添加的问题。我稍后会研究你的功能。 PS.anyway 对于将参考这个问题的人来说,文件指针不是 dp 而是 db。对此感到抱歉。
    猜你喜欢
    • 2012-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-09
    • 1970-01-01
    • 2020-08-22
    相关资源
    最近更新 更多