【问题标题】:reading from file using fgets() then using information in another function使用 fgets() 从文件中读取,然后在另一个函数中使用信息
【发布时间】:2013-06-22 10:23:46
【问题描述】:

我有一个这样的文本文件:

123-55555-1 10000 0   
123-55533-3 12300 500 
123-99971-3 50000 0 
123-38951-2 350 10  
120-39888-0 4910 100   
121-12345-3 50000 150 
121-xptoz-3 1000 100  
150-23857-1 350000 20000 
521-71750-4 500000 25000 
191-11999-7 1200

我想要的是能够使用fgets() 逐行检索此信息。当我阅读它时,我想调用另一个函数,该函数使用 read 行处理信息并将其放在列表中。问题是当我尝试调用函数并将字符串作为参数传递时,它给了我 seg error:11。这是我的代码。

typedef struct identificador_s
{
  int a;
  int b;
  int c;

} identificador;

typedef struct contaBancaria_s
{
  identificador id;
  int saldo;
  unsigned short int credito;
  struct contaBancaria_s * proximo;

} contaBancaria;

contaBancaria * contaP = NULL;
char contas[] = "contas.txt";
char movimentos[] = "movimentos.txt";

char divideString(char line[], int contagem, char parametro[])
{
  int i = 0;
  char *a = NULL;
  char string1;
  a = strtok(line, parametro);
  while (i != contagem)
  {
    a = strtok(NULL, parametro);
    i++;
  }
  string1 = (char) *a;
  return string1;

}

void contaFill(char line[])
{
  printf("passo -2");
  contaBancaria * p = malloc(sizeof(contaBancaria));
  printf("passo 0");
  int i = 0;
  char parametro1[] = "-";
  char parametro2[] = " ";
  p->id.a = (int) divideString(line, i, parametro1);
  printf("passo 1");
  p->id.b = (int) divideString(line, i += 1, parametro1);
  printf("passo2");
  p->id.c = (int) divideString(line, i += 1, parametro1);
  printf("passo 3");
  /*if(!(validaIdentificador(p-id.a,p->id.b,p-id.c))){
   return;
   }*/
  p->saldo = (int) divideString(line, i += 1, parametro2);
  printf("passo 4");
  p->credito = (int) divideString(line, i += 1, parametro2);
  printf("passo 5");
  printf("%d - %d - %d %d %d", p->id.a, p->id.b, p->id.c, p->saldo, p->credito);
}

void loadFile(char fileType[])
{
  FILE * fp;
  fp = fopen(fileType, "r");
  int size = 100;
  char buffer[100];
  char string1[100];
  if (fp)
  {
    while (fgets(buffer, 100, fp) != NULL)
    {
      puts(buffer);
      if (strcmp(fileType, "contas.txt") == 0)
      {
        contaFill(buffer);
      }
    }
    fclose(fp);
  }
}

int main(int argc, char* argv[])
{
  loadFile(contas);
  return 0;
}

【问题讨论】:

  • 什么是“代码格式”?
  • 如您所见,我将代码放在引号中,因为我不理解代码选项。所以它保持在一起有点难以识别和阅读。
  • 是的,我明白了,你最好尝试使用一些编辑器并正确缩进,这样它才能变得可读。
  • 重新格式化完成... Ctrl-Shift-F ;-)
  • 既然代码没问题,没人能回答我的问题xD

标签: c file pointers fgets


【解决方案1】:

第一次打电话divideString(line, i, parametro1);

p->id.a = (int) divideString(line, i, parametro1);

返回值为 '1' -> 49

line 中的第一个 '-''\0' 替换为 strtok

(例如,"123-55555-1 10000 0" -> "123\055555-1 10000 0" 表示“123”

第二次通话divideString(line, i += 1, parametro1);

a = strtok(line, parametro);//not find parametro return `a=line`(top)
...
a = strtok(NULL, parametro);//a=`NULL`
...
string1 = (char) *a;//*(NULL) seg fault!!

更新

集合在一起并停止调用(divideString)一个的每个成员。

例如

void stringToContaBancaria(char line[], contaBancaria *p, char para1[], char para2[]){
    char *a, *endp;
    //To convert to int from numeric strings for example it use strtol
    p->id.a    = strtol(a=strtok(line, para1), &endp, 10);
    if(*endp) fprintf(stderr, "id.a not number : %s\n", a);
    p->id.b    = strtol(a=strtok(NULL, para1), &endp, 10);
    if(*endp) fprintf(stderr, "id.b not number : %s\n", a);
    p->id.c    = strtol(a=strtok(NULL, para2), &endp, 10);
    if(*endp) fprintf(stderr, "id.c not number : %s\n", a);
    p->saldo   = strtol(a=strtok(NULL, para2), &endp, 10);
    if(*endp) fprintf(stderr, "saldo not number : %s\n", a);
    p->credito = strtoul(a=strtok(NULL, para2), &endp, 10);
    if(*endp) fprintf(stderr, "credito not number : %s\n", a);
}

void contaFill(char line[]){
    contaBancaria * p = malloc(sizeof(contaBancaria));
    char parametro1[] = "-";
    char parametro2[] = " ";//" \n"?
    stringToContaBancaria(line, p, parametro1, parametro2);
    printf("%d - %d - %d %d %hu\n", p->id.a, p->id.b, p->id.c, p->saldo, p->credito);
    //free(p);//deallocate! 
}

它给了我段错误

    //less a(=strtok return value) becomes to NULL element when reading is less than expected.
    p->credito = strtoul(a=strtok(NULL, para2), &endp, 10);
    if(*endp) fprintf(stderr, "credito not number : %s\n", a);

例如改为

    if(NULL!=(a=strtok(NULL, para2))){
        p->credito = strtoul(a, &endp, 10);
        if(*endp)fprintf(stderr, "credito not number : %s\n", a);
    } else
        fprintf(stderr, "credito not exist\n");

但我认为检查之前的时间而不是阅读这些必要的项目之间是否有。


进行简单的预检查

#include <ctype.h>

int isInvalidRecord(char line[]){
//[number]-[number]-[number][space][number][space][number][space*]
//521-71750-4 500000 25000[newline]
    int i=0, j;
    while(isdigit(line[i]))++i;
    if(i==0 || line[i]!='-') return 1;//1st item bad
    j=++i;
    while(isdigit(line[i]))++i;
    if(i==j || line[i]!='-') return 2;
    j=++i;
    while(isdigit(line[i]))++i;
    if(i==j || line[i]!=' ') return 3;
    j=++i;
    while(isdigit(line[i]))++i;
    if(i==j || line[i]!=' ') return 4;
    j=++i;
    while(isdigit(line[i]))++i;
    if(i==j || (line[i]!='\0' && !isspace(line[i]))) return 5;
    return 0;//ALL OK
}

void contaFill(char line[]){
    contaBancaria * p = malloc(sizeof(contaBancaria));
    char parametro1[] = "-";
    char parametro2[] = " ";//" \n"?
    int check = isInvalidRecord(line);
    if(check == 0)//0 is OK
        stringToContaBancaria(line, p, parametro1, parametro2);
    else
        fprintf(stderr, "%s %d item(near) is bad\n", line, check);
    printf("%d - %d - %d %d %hu\n", p->id.a, p->id.b, p->id.c, p->saldo, p->credito);
    //free(p);//deallocate! 
}

【讨论】:

  • 对不起,我不明白这一点,所以我怎样才能更新我的代码来做同样的事情,那就是“123-55555-1 10000 0”每个数字框应该在一个不同的变量中列表中的 5 个变量。谢谢
  • @RicardoSacramento 我是写代码修改的例子。
  • @RicardoSacramento 示例最后一条记录 191-11999-7 1200 只有四项。你需要这样检查吗?
  • 谢谢你的帖子,是的,如果文件不是所有阵营,我需要限制它们,所以条目无效,我不把它放在列表中。贷方的最后一个阵营也是 unsigned short int 我该如何转换?
  • @RicardoSacramento strtoulunsigned short int 的使用方式相同。
【解决方案2】:

您的代码在这里崩溃:

string1 = (char) *a;

您会在任何调试器中看到这一点。首先,请注意这里的(char) 是不必要的。但真正的问题是a 有时是NULL,因此无法取消引用。你需要弄清楚在这种情况下你想做什么。

【讨论】:

    【解决方案3】:

    好吧,您的代码中存在很多问题。我已尝试修复所有错误并且工作正常,不,这是我所做的改进:

    这里

    函数strtok();返回您分配给a的指针类型,而它应该分配给*a

    我已经在 cmets(//) 中编写了任何其他改进。

    #include<stdio.h>
    #include<stdlib.h>
    typedef struct identificador_s
    {
      int a;
      int b;
      int c;
    
    } identificador;
    
    typedef struct contaBancaria_s
    {
      identificador id;
      int saldo;
      unsigned short int credito;
      struct contaBancaria_s * proximo;
    
    } contaBancaria;
    
    contaBancaria * contaP = NULL;
    char contas[] = "contas.txt";
    char movimentos[] = "movimentos.txt";
    
    char divideString(char line[], int contagem, char parametro[])
    {
      int i = 0;
      char *a = NULL;
      char string1;
      *a = strtok(line, parametro);
      while (i != contagem)
      {
        *a = strtok(NULL, parametro);
        i++;
      }
      string1 = (char) *a;
      return string1;
    
    }
    
    void contaFill(char line[])
    {
      printf("passo -2");
      contaBancaria *p=malloc(sizeof(contaBancaria));
      printf("passo 0");
      int i = 0;
      char parametro1[] = "-";
      char parametro2[] = " ";
      p->id.a = (int) divideString(line, i, parametro1);
      printf("passo 1");
      p->id.b = (int) divideString(line, i += 1, parametro1);
      printf("passo2");
      p->id.c = (int) divideString(line, i += 1, parametro1);
      printf("passo 3");
      /*if(!(validaIdentificador(p-id.a,p->id.b,p-id.c))){
       return;
       }*/
      p->saldo = (int) divideString(line, i += 1, parametro2);
      printf("passo 4");
      p->credito = (int) divideString(line, i += 1, parametro2);
      printf("passo 5");
      printf("%d - %d - %d %d %d", p->id.a, p->id.b, p->id.c, p->saldo, p->credito);
    }
    
    void loadFile(char fileType[])
    {
      FILE * fp;
      fp = fopen(fileType, "r");
      int size = 100;
      char buffer[100];
      char string1[100];
      if (fp)
      {
        while (fgets(buffer, 100, fp) != NULL)
        {
          puts(buffer);
          if (strcmp(fileType, "contas.txt") == 0)
          {
            contaFill(buffer);
          }
        }
          }
      fclose(fp);// file should close outside the if statement 
    }
    
    int main(int argc, char* argv[])
    {
      loadFile(contas);
      return 0;
    }
    

    【讨论】:

    • 在 C 中,没有需要转换malloc() 的结果。更建议这样做:stackoverflow.com/a/605858/694576
    • 那么为什么会显示错误:“malloc() 的错误定义”@alk
    • @alk 好吧,实际上代码的问题在于,没有声明指针变量 p,我采取了另一种方式,感谢您的指导和该链接,最终我进行了更正跨度>
    • 啊啊!! downvote 太令人沮丧了,每个人都不会像这里的家伙一夜之间成为天才。错误确实会发生,但主要部分是从那个错误中即兴发挥。它太苛刻了,无论如何我接受它。
    • 我认为你得到了反对,因为暗示了一些事情,这不一定是 OP 的意图:“......而它应该分配给 *a”。通过 C 语言,也可以使用 char string1, * a = strtok; string1=*a; return string1。是否有意义,最终由作者决定。 char * a = NULL; *a = strtok(...) 无论如何都是 UB。
    猜你喜欢
    • 1970-01-01
    • 2019-05-29
    • 1970-01-01
    • 2015-09-06
    • 1970-01-01
    • 1970-01-01
    • 2017-01-09
    • 2018-11-26
    相关资源
    最近更新 更多