простой c scanf не читает и не анализирует мой ввод - PullRequest
0 голосов
/ 13 февраля 2020

Я создал Date struct для хранения формата даты как date, month, year, который вводится пользователем в виде одной строки, разделенной пробелом.

Я хочу разделить вход и хранить его соответственно. Я использовал простой C sscanf(), чтобы разделить и сохранить свой ввод в struct Date. Но когда я пытаюсь распечатать свои данные, они показывают какое-то мусорное значение, я не знаю, чего не хватает.

Помогите мне решить эту проблему.

Мой код:

Input: 24 Jan 1980
output: 24 ? -978635323 

вот мой C код.

struct Date 
{
  int date;
  char* month;
  int year;
};

int main()
{
  struct Date date[1];
  char* string;
  scanf("%s",string);
  sscanf(string,"%d %s %d",&date[0].date,date[0].month,&date[0].year);
  printf("%d %s %d",date[0].date,date[0].month,date[0].year);
  return 0;
}

Заранее спасибо.

Ответы [ 3 ]

1 голос
/ 13 февраля 2020

это работает для меня. Вы можете проверить это.

struct Date
{
    int dat;
    char month[20];
    int year;
};

int main()
{
    struct Date date[1];
    char str[20];
    scanf("%[^\n]%*c", str);
    sscanf(str,"%d %s %d",&date[0].dat,&date[0].month,&date[0].year);
    printf("%d %s %d",date[0].dat,date[0].month,date[0].year);
    return 0;
}
1 голос
/ 13 февраля 2020

char* string - неинициализированный указатель, он не может содержать строку, вам необходимо выделить память, инициализировать ее как массив символов или указать ее на переменную с уже выделенной памятью или на существующий массив символов. Ваш член структуры month страдает от той же проблемы.

Флаг -Wall в вашем компиляторе должен дать вам предупреждение:

'string is used uninitialized in this function [-Wuninitialized]'

Другая проблема заключается в что %s получает только строку, когда он находит пробел, он прекращает чтение, поэтому он может читать только 24 в вашем случае.

Хотя "%[^\n]s" может работать, лучшее решение будет использовать fgets, это более безопасная функция, поскольку вы можете ограничить размер ввода до размера принимающего контейнера, в отличие от scanf.

#include <stdio.h>
#define SIZE 100

struct Date 
{
  int date;
  char month[SIZE];
  int year;
};

int main()
{
  struct Date date[1];
  char string[SIZE];
  fgets(string, sizeof(string), stdin); 
  sscanf(string,"%d %s %d",&date[0].date, date[0].month, &date[0].year);
}
0 голосов
/ 13 февраля 2020

ОБЪЯСНЕНИЕ

В вашем коде вы объявили два char * указателя char *month и char *string и пытаетесь сохранить в них строковые значения , Вы должны понимать, что эти два - просто указатели. Все, что они могут хранить, это адреса памяти для массивов char. Это правда, что переменная массива взаимозаменяема с указателем в C. Но объявление массива также включает атрибут size.

Когда вы объявляете массив символов как:

char str[10];

Он фактически резервирует блок размером 10 в памяти, неявно создает char *str, и сохраняет базовый адрес вновь созданного блока в str. Но когда вы просто объявляете char *str, все, что он делает, это создает указатель. У него нет связанного блока памяти для массива.

Вот почему вы должны объявить массив символов некоторого размера, прежде чем сохранять в нем строки с помощью scanf(). Или вы должны динамически распределять память с помощью calloc или malloc после объявления указателя char *. Только тогда вы можете сохранить в ней строковые данные.

Я изменил ваш код для правильной работы. Теперь он производит желаемый результат. Надеюсь, это поможет.

РАБОЧИЙ КОД

#include <stdio.h>
#include <stdlib.h>

struct Date 
{
  int date;
  char month[10];
  int year;
};

int main()
{
  struct Date date[1];

  char string[20];

  scanf("%[^\n]s",string);
  sscanf(string,"%d %s %d",&date[0].date,date[0].month,&date[0].year);
  printf("%d %s %d",date[0].date,date[0].month,date[0].year);

  return 0;
}

РЕДАКТИРОВАТЬ

Они сами по себе являются целыми числами (как и все указатели).
Как уже упоминалось в anastaciu , указатели не эквивалентны целым числам как таковым. Вы можете перейти по ссылкам, приведенным в его комментариях для получения дополнительных знаний. Я упомянул это утверждение, чтобы утверждать разницу между указателями и объявлениями массивов.

...