我对编程还比较陌生。我正在尝试显示在以前基于用户创建的文件中找到的所有数据(用户必须在单个条目中输入产品代码、产品名称和产品价格)。 我的代码有一个包含 3 个选项的菜单:
- 显示文件中的所有数据(仅使用选项 2 中的最后一个条目。实际上,我故意让程序像这样工作,因为我不知道如何打印文件中的所有数据)
- 向该文件添加数据(100% 正常工作)
- 退出(100% 工作)
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;
}
}
}
最佳答案
文件的第一行将是 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
失败了,因此您的程序将打印结构内的任何垃圾值,因为您尚未在代码开头初始化它。
尝试将结构体的成员初始化为零,您将看到程序打印零。
<小时/>所以...尝试挽救大部分代码和逻辑,我能想到的一种解决方法是创建一个名为 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:如果您愿意,您可以将其 sscanf
放入您的 struct
中,而不是像我那样只打印 last_product
然后打印struct
内容。
关于C - 如何将(来自基于用户的输入)各种字符串存储在结构内的数组中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41085282/