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