Я пытаюсь хранить какие-то products в массиве и далее я буду вставлять новый товар в этот массив или удалять существующий из этого массива. Это мой план, и я пытаюсь что-то вроде ниже.
При зацикливании первый цикл выполняется успешно, но из второго цикла отображается только Enter product name, но scanf("%s", p[i].pname) не дает мне вставить значение. Кто-нибудь поможет мне решить эту проблему!!
#include <stdio.h>
struct product{
char pname[30];
int quantity;
float cost;
};
/*void insertnew();
void delete();*/
void main()
{
struct product p[50];
int i;
for(i = 0; i < 3; i++){
printf("Enter Product Name:\n");
scanf("%s", p[i].pname);
printf("Enter Quantity:\n");
scanf("%d", &p[i].quantity);
printf("Enter Cost:\n");
scanf("%.2f", &p[i].cost);
printf("*****************\n");
}
for(i = 0; i < 3; i++){
printf("Name = %s\n",p[i].pname);
printf("Quantity = %d\n",p[i].quantity);
printf("Cost = %.2f\n",p[i].cost);
printf("-----------\n");
}
}
/*void insertnew(){}
void insertnew(){}*/
Мне будет полезнее, если insertnew() и delete(), что мне делать, правильный ли путь?
Выход:
OT: относительно: scanf("%s", p[i].pname); 1) при вызове любой из scanf() функций всегда проверяйте возвращаемое значение (а не значения параметров), чтобы убедиться, что операция прошла успешно. В текущем утверждении: if ( scanf("%s", p[i].pname) != 1 ) { fprintf( stderr, "scanf for pname failed\n" ); возможно, за которым следует: exit( EXIT_FAILURE ); '}' 2) при использовании спецификаторов формата ввода '%s' и/или '%[...]' всегда включайте модификатор MAX CHARACTERS, который на 1 меньше длины входного буфера, поскольку эти спецификаторы всегда добавляют байт NUL ко входу
OT: независимо от того, что позволяют некоторые компиляторы (например, Visual Studio), есть только две допустимые подписи для main(): int main( void ) и int main( int argc, char *argv[] )
ОТ: в опубликованном коде есть несколько "магических" чисел (3, 30, 50). «магические» числа — это числа без основы. «магические» числа значительно усложняют понимание кода, отладку и т. д. Предложите использовать операторы #define или операторы enum, чтобы дать этим «магическим» числам осмысленные имена, а затем использовать эти осмысленные имена во всем коде.
OT: зачем объявлять массив из 50 экземпляров структуры, а затем использовать только первые 3?
относительно: Мне будет полезнее, если вставить новый() и удалить(), что мне делать, это правильный путь? О чем вы спрашиваете? Просьба уточнить.
Настоятельно рекомендуем сделать struct product p[50]; в начале связанного списка (для этого потребуется добавить указатель «следующий» в структуру. Затем объявите заголовок списка как: struct produce *head = NULL; Затем используйте динамическую память для каждой записи в списке





Когда я попытался скомпилировать ваш код с помощью gcc, я получил предупреждение:
prod.c:20:8: warning: unknown conversion type character ‘.’
in format [-Wformat=]
scanf("%.2f", &p[i].cost);
Это привлекло мое внимание к ложному "." в аргументе scanf. Как только я его удалил, он скомпилировался без предупреждений, и ваш код отсканировал для меня все три элемента и правильно их распечатал.
Обратите внимание, однако, что, хотя вышеприведенное заставит работать простой случай, вам необходимо выполнить проверку ввода, проверяя возвращаемые значения scanf() и повторяя или прерывая ввод в случае сбоя - в зависимости от того, что вы намеревались сделать в случае недопустимого ввода. . Или, чтобы быть более надежным, как было предложено в комментарии Weather Vane, прочитать ввод в строку с помощью fgets(), а затем попытаться проанализировать его с помощью sscanf().
В целом, scanf() не подходит, если входные данные могут содержать недопустимые записи — вместо этого вам следует создать какое-то собственное решение.
Это не решает. Ввод стоимости как 1.23 по-прежнему пропускает ввод следующей строки. Я рекомендую вводить все данные с помощью fgets в большую строку, а затем использовать sscanf в строке с проверкой.
Использование %2f ищет 2 символа. Если вы введете 1.23, scanf() обрабатывает 1. (как 1,00) и оставляет 23 интерпретироваться как следующее имя. В целом ширина бесполезна для пользовательского ввода; это может быть полезно для машинно-генерируемых строго отформатированных данных.
почему gcc не предупредил вас о void main(), потому что у него нет возвращаемого типа int?
OT: при компиляции с gcc всегда включайте предупреждения, Suggest: gcc -c sourceFile.c -o objectFile.o -Wall -Wextra -Wconversion -pedantic -std=gnu11
Также "warning: too many arguments for format [-Wformat-extra-args]"
Проблема здесь, когда вы пытаетесь прочитать в float:
scanf("%.2f", &p[i].cost);
Спецификаторы формата для scanf, в отличие от спецификаторов для printf, не используют спецификатор точности. Это означает, что символ . недопустим как часть строки формата.
Если вы скомпилируете с включенными предупреждениями (-Wall -Wextra на gcc), он предупредит вас об этом:
x1.c:20:8: warning: unknown conversion type character ‘.’ in format [-Wformat=]
scanf("%.2f", &p[i].cost);
^
Это приводит к тому, что при вводе значения для этого поля ничего не считывается, и заданный текст остается в буфере ввода. Когда следующий scanf выполняется, ожидая строку, он без запроса считывает то, что уже находится в буфере.
Правильный способ справиться с этим (по крайней мере, для float) — удалить любой спецификатор длины:
scanf("%f", &p[i].cost);
Если пользователь введет более значащие цифры, вы не увидите их при печати с помощью %.2f.
стоимость ожидает хранения типа float. Итак, сканируйте поплавок. (тогда он может отображаться в любом формате)
scanf("%f", &p[i].cost);
тогда это работает:
Enter Product Name:
boxa
Enter Quantity:
10
Enter Cost:
11.5
*****************
Enter Product Name:
boxb
Enter Quantity:
4
Enter Cost:
12.4
*****************
Enter Product Name:
boxc
Enter Quantity:
122
Enter Cost:
3.3
*****************
Name = boxa
Quantity = 10
Cost = 11.50
-----------
Name = boxb
Quantity = 4
Cost = 12.40
-----------
Name = boxc
Quantity = 122
Cost = 3.30
-----------
ты не можешь сделать
scanf("%.2f",&p[i].cost);
Scanf не принимает форматированное значение с плавающей запятой. Вы можете изменить его только во время печати значения. измените эту строку на
scanf("%f",&p[i].cost)
Все остальное кажется в порядке.
Обратите внимание, что
scanf("%.2f", &p[i].cost);неверно. Попробуйтеint res = scanf("%f", &p[i].cost);%.не является допустимым спецификатором формата. Даже если вам удастся усечь до двух знаков после запятой, все, что останется, будет введено в следующееscanf("%s", p[i].pname);Это не волшебным образом забыто.