C - 如何在结构内的数组中存储(来自基于用户的输入)各种字符串?

时间:2016-12-11 10:39:51

标签: c arrays file menu structure

我对编程比较陌生。我尝试显示以前基于用户的创建文件中找到的所有数据(用户必须在单个条目中输入产品代码,产品名称和产品价格)。 我的代码有一个包含3个选项的菜单:

  1. 显示所有文件中的数据(仅使用选项2中的最后一个条目。实际上,我让程序故意工作,因为我无法弄清楚如何打印文件中的所有数据)
  2. 将数据添加到该文件(100%工作)
  3. 退出(100%工作)
  4. PS:当我在重新打开程序后尝试使用(1)选项时,它只显示垃圾。有没有办法解决这个问题? PS2:抱歉我对英语的使用不当,我不是本地人。

    这里我显示整个代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <windows.h>
    
    typedef struct
    {
    
      unsigned long long codigo_producto;
      char nombre_producto[60];
      float precio_producto;
    
    } datos_de_productos;
    
    int i;
    
    main()
    {
    
      datos_de_productos datos;
    
      char U = 233;
      char o = 162;
      int x = 0;
      int tam;
      FILE *p_datos;
    
      p_datos = fopen("datos.txt", "a");
      fseek(p_datos, 0, SEEK_END);
      tam = ftell(p_datos);
      if (tam == 0)
      {
        p_datos = fopen("datos.txt", "w");
        fprintf(p_datos,
            "CODIGO DE PRODUCTO\tNOMBRE DE PRODUCTO\tPRECIO DE PRODUCTO\n\n\n");
        fclose(p_datos);
      }
    
      while (x != 3)
      {
    
        system("cls");
        system("color 84");
        printf("****** MEN%c PRINCIPAL ******\n\n", U);
        printf("(1) - Ver el %cltimo producto ingresado en esta sesi%cn\n", U, o);
        puts("(2) - Agregar datos");
        puts("(3) - SALIR\n");
        menu_principal: printf("Por favor, ingrese la opci%cn deseada: ", o);
        scanf("%i", &x);
    
        switch (x)
        {
    
        case 1:
    
          system("cls");
          system("color 84");
          p_datos = fopen("datos.txt", "r");
          if (fopen == NULL )
          {
            exit(1);
          }
          if (fopen != NULL )
          {
            printf(
                "CODIGO DE PRODUCTO\tNOMBRE DE PRODUCTO\tPRECIO DE PRODUCTO\n\n\n");
            fscanf(p_datos, "%llu %s %f", &datos.codigo_producto,
                datos.nombre_producto, &datos.precio_producto);
            printf("%llu\t\t%s\t\t%.2f\n", datos.codigo_producto,
                datos.nombre_producto, datos.precio_producto);
            fclose(p_datos);
            puts("\n\n");
            system("pause");
            system("color 0E");
          }
    
          break;
    
        case 2:
    
          system("cls");
          puts("Se ingresaran los datos con el siguiente prototipo:\n");
          puts("codigo_producto | nombre_producto | precio_producto\n");
          puts("Ejemplo: '1763482 Placa_de_video 749.99'\n");
          printf(
              "(n%ctese que se usan guiones bajos para separar las palabras)\n\n",
              o);
          system("pause");
          system("cls");
          system("color 0E");
          puts("codigo_producto | nombre_producto | precio_producto\n");
          scanf("%llu %s %f", &datos.codigo_producto, datos.nombre_producto,
              &datos.precio_producto);
          p_datos = fopen("datos.txt", "a");
          if (fopen == NULL )
          {
            exit(1);
          }
          if (fopen != NULL )
          {
            fprintf(p_datos, "%llu\t\t%s\t\t%.2f\n", datos.codigo_producto,
                datos.nombre_producto, datos.precio_producto);
            fclose(p_datos);
            system("color 84");
            puts("\nProducto cargado correctamente.");
            system("pause");
          }
    
          break;
    
        case 3:
    
          system("cls");
          system("color 0F");
          puts("Nos\t\t\t\t\t\t\t\tby viciecal");
          sleep(1);
          puts("Re");
          sleep(1);
          puts("Vimos");
          sleep(1);
          puts("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\t\t\t\t\t\t\t\t\tputo");
    
          break;
    
        default:
    
          goto menu_principal;
    
          break;
    
        }
      }
    }
    

1 个答案:

答案 0 :(得分:0)

您文件的第一行将是fprintf中的内容:

fprintf(p_datos,
        "CODIGO DE PRODUCTO\tNOMBRE DE PRODUCTO\tPRECIO DE PRODUCTO\n\n\n");

当您到达case 1内的这一行时,该文件将在其开头(第一行)打开:

p_datos = fopen("datos.txt", "r");

所以fscanf

fscanf(p_datos, "%llu %s %f", &datos.codigo_producto,
            datos.nombre_producto, &datos.precio_producto);

将尝试从第一行读取llu

CODIGO DE PRODUCTO  NOMBRE DE PRODUCTO  PRECIO DE PRODUCTO

但会立即失败,因为它找不到llu,因此您不会扫描文件中的任何内容(尝试检查fscanf的返回值,您会看到它会是0)。

为什么会看到垃圾被打印出来?

因为,正如我所说,fscanf失败了,所以你的程序会打印你的struct中的任何垃圾值,看你没有在代码的开头初始化它。

尝试将struct的成员初始化为零,你会看到程序打印零。

所以...试图挽救你的大部分代码和你的逻辑,我能想到的一个解决方法是创建一个名为last_product的char数组,例如文件中的fgets,直到它结束了,所以读入缓冲区的最后一个条目将是文件的最后一行。

然后你printf last_product,就像这样:

case 1:

  p_datos = fopen("datos.txt", "r");
  if (p_datos == NULL )
  {
    exit(1);
  }
  if (p_datos != NULL )
  {
    char last_product[100];
    while (fgets(last_product, 100, p_datos) != NULL)
        ;
    printf(
        "CODIGO DE PRODUCTO\tNOMBRE DE PRODUCTO\tPRECIO DE PRODUCTO\n\n\n");
    printf("%s", last_product);
    fclose(p_datos);
    puts("\n\n");
  }

我没有分析或测试过您的整个代码,但这应该足以让您前进。

PS:如果它让您满意,而不是像我一样打印last_product,您可以sscanf将其struct打印到struct,然后打印select PROJECT_ID, STAFF_ID, STAFF_NAME from ASSIGNMENTS inner join STAFF on STAFF.STAFF_ID=ASSIGNMENTS.STAFF_ID 内容。