C Программа не печатает строку в структуре

Я сделал программу, которая принимает несколько входных данных в виде строки, сохраняет и распечатывает их. Почему-то «Номер счета», который хранится в a[i].acn, не печатается. Я пробовал отладку, и проблема, похоже, в цикле, который добавляет пробелы к a[i].name .

#include <stdio.h>
#include <string.h>
struct Bank
{
    char name[10],acn[8];
    float bal;
}a[100];
int n,i,flag;
void add()
{
//function to add Rs. 100 to accounts that have balance over 1000
//and print the details.
    for(i=0;i<n;i++)
        if (a[i].bal>=1000)
            a[i].bal+=100;
    printf("\nS.No.\tName\t\tAcc. No.\tBalance(in Rs.)");
    for(i=0;i<n;i++)
        printf("\n[%d]\t%s\t%s\t%.2f",i+1,a[i].name,a[i].acn,a[i].bal);
}
void main()
{
    printf("Enter the number of customers: ");
    scanf("%d",&n);
    printf("Enter the details of %d customers:\n",n);
    for(i=0;i<n;i++)
    {
        printf("\nCustomer-%d",i+1);
        printf("\nFirst Name: ");
        fflush(stdin);
        gets(a[i].name);
        printf("Account Number: ");
        fflush(stdin);
        gets(a[i].acn);
        printf("Account Balance: ");
        scanf("%f",&a[i].bal);
    }
    for(i=0;i<n;i++)//The problem seems to be in this loop
        while(strlen(a[i].name)<10)
            strcat(a[i].name," ");
    add();
}

Вход:

Enter the number of customers: 2
Enter the details of 2 customers:

Customer-1
First Name: Aarav
Account Number: ASDF1234
Account Balance: 1200

Customer-2
First Name: Asd
Account Number: abcd1122
Account Balance: 999.9

Выход:

S.No.   Name            Acc. No.        Balance(in Rs.)
[1]     Aarav                   1300.00
[2]     Asd                     999.90

Какой ввод использовался?

chux - Reinstate Monica 20.12.2020 08:39

@chux-ReinstateMonica, мой плохой. Я также отредактирую и добавлю ввод.

Aarav 20.12.2020 08:59
fflush(stdin); Очистка входного потока вызывает неопределенное поведение
Gerhardh 20.12.2020 09:29
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
464
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

В вашей программе есть несколько вещей, которые нужно исправить.

  1. Используйте fgets вместо gets, потому что в gets нет проверки границ и есть опасность чтения за пределами выделенного размера.

  2. При использовании fgets , scanf и даже gets все они считывают оставшиеся \n символы из стандартного буфера, поэтому с помощью fgets мы можем избежать этого, если будем использовать его правильно. (scanf также избегает пробелов, но его нельзя использовать для чтения строк, состоящих из нескольких слов)

  3. удалить fflush(stdin), это не обязательно, вы можете увидеть причину здесь

  4. И последнее, но не менее важное: используйте int main() вместо void main().

Пункт 2 неверен по нескольким причинам, например. что scanf не может читать строки из нескольких слов — может.

Support Ukraine 20.12.2020 08:30

@ 4386427, пожалуйста, укажите их, добавите к ответу, конечная цель - помочь.

IrAM 20.12.2020 08:33

«scanf ... но его нельзя использовать для чтения строк, состоящих из нескольких слов» --> scanf("%*[^\n]%*1[\n]" "%*[^\n]%*1[\n]" "%*[^\n]%*1[\n]" ); будет хорошо читаться в 3 непустых строках ввода. Тем не менее, использование fgets() — хорошая и предпочтительная идея.

chux - Reinstate Monica 20.12.2020 08:36

@chux-ReinstateMonica, это полезно знать, тогда я должен изменить свой ответ на то, что он не может читаться прямо (просто используя %s), если только мы не используем несколько списков символов escape-последовательности.

IrAM 20.12.2020 08:41

Спасибо всем за ответы и полезные комментарии!

Aarav 20.12.2020 08:59

У вас есть это:

struct Bank
{
    char name[10],acn[8];
    float bal;
}a[100];

поскольку строки C должны заканчиваться символом NUL (он же '\0'), длина name может быть не более 9 символов.

Но здесь

    while(strlen(a[i].name)<10)
        strcat(a[i].name," ");

вы продолжаете добавлять пробелы, пока он не станет 10 символов. Другими словами, вы пишете вне массива.

Измени name на name[11]

Кроме того, следует избегать gets и fflush(stdin).

Ответ принят как подходящий

scanf() значит gets() плохо

scanf("%d",&n); читает целое число, но оставляет следующее '\n' в stdin, которое gets() читается как пустая строка "".

Я рекомендую использовать fgets() для чтения всей строки в буфер большого размера, а затем анализировать с помощью sscanf(), strtol() и т. д.


Код переполняет буфер

a[i].nam достаточно места только для 9 символов, а затем для нулевого символа. Добавление пробела до тех пор, пока его длина не превысит 9 переполнений .name[10].

struct Bank {
  char name[10],acn[8];
  float bal;
} a[100];

while(strlen(a[i].name)<10)
   strcat(a[i].name," ");

Используйте while(strlen(a[i].name)<9), чтобы добавить пробелы, но не слишком много.


Деньги требуют особых соображений. А пока рассмотрим long наименьшего номинала (центов). Читайте в double, а затем long balance = lround(input*100.0);

Существуют и другие слабости.

Да, gets после scanf это плохо, но.... gets всегда плохо - даже без scanf непосредственно перед.

Support Ukraine 20.12.2020 08:49

Спасибо @chux-ReinstateMonica за ответ!

Aarav 20.12.2020 08:59

Другие вопросы по теме