-1

I have created Date struct to store date format as date, month, year which is inputed by the user as a single line string seperated by space.

I want to split the input and store it accordingly. I have used simple C sscanf() to split and store my input in struct Date. But when I try to print my data it's showing some garbage value, I don't know what is missing.

Help me to clear this issue.

My code:

Input: 24 Jan 1980
output: 24 ? -978635323 

here is my C code.

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;
}

Thanks in advance.

anastaciu
  • 23,467
  • 7
  • 28
  • 53
  • Need to allocate memory for string. For example `char *string = malloc(MY_MAX_LEN);` Currently your code doesn't set `string` and hence it is a junk/invalid pointer and writing to it with `scanf` results in undefined behaviour. – kaylum Feb 13 '20 at 10:39
  • `string` is declared to be a pointer. A pointer is a variable that is used to store the address of some memory. So you need some memory (which `malloc` for example gives) and you need to set `string` to that memory address. – kaylum Feb 13 '20 at 10:41
  • What about strdup() ? –  Feb 13 '20 at 10:42
  • `strdup` requires an original string to copy from. You don't have an original string. You are reading something from `STDIN`. – kaylum Feb 13 '20 at 10:42
  • Besides allocating memory for a string (instead of a pointer), consider using `fgets` instead of `scanf` – Support Ukraine Feb 13 '20 at 10:44
  • How can I use it in Loop. Let say I need to get Set of inputs from user and need to sort it based on date. –  Feb 13 '20 at 10:47
  • You can use memset to reinitialize the array when you need to reuse the memory – newbie Feb 13 '20 at 10:58
  • Suggestion: `struct Date { int date; char month[4]; int year; };` ... and `if (sscanf(string, "%d%3s%d", &date->date, date->month, &date->year) != 3) /* error */;` – pmg Feb 13 '20 at 11:18
  • This is an exact duplicate of [your earlier question that was closed](https://stackoverflow.com/questions/60202125/simple-c-scanf-not-reading-input) – ad absurdum Feb 13 '20 at 11:35

3 Answers3

1

char* string is an uninitialized pointer, it cannot hold a string, you need to allocate memory, initialize it as an array of chars or point it to a variable with memory already allocated or to an existing array of chars. Your structure member month suffers from the same problem.

A -Wall flag in your compiler should give you a warning:

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

Another problem is that %s only gets a string, when it finds a blank space, it stops reading, so it can only read 24 in your case.

Though "%[^\n]s" can work, a better solution would be to use fgets, it's a safer function since you can limit the size of the input to the size of receiving container, unlike 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);
}
anastaciu
  • 23,467
  • 7
  • 28
  • 53
1

it works for me. You can check it.

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;
}
soykot2910
  • 101
  • 1
  • 8
  • Almost there, in `sscanf()`, `&date[0].month` is of type `char (*)[20]`, `%s` is of type `char*` use `date[0].month`. See https://wandbox.org/permlink/yFelJXh9uuy4GGuO – anastaciu Feb 13 '20 at 11:49
  • 1
    If input is only `"\n"`, then `scanf("%[^\n]%*c", str)` writes nothing to `str` and following `sscanf(str, ...` leads to undefined behavior. Use `fgets()`. – chux - Reinstate Monica Feb 13 '20 at 14:26
1

EXPLANATION

In your code, you have declared two char * pointers char *month and char *string, and trying to store string values in them. You have to understand that these two are mere pointers. All they can store are memory addresses to char arrays. It is true that an array variable is interchangeable with a pointer in C. But an array declaration also involves a size attribute.

When you declare a character array as:

char str[10];

It actually reserves a block of size 10 in memory, implicitly creates char *str, and stores the base address of the newly created block in str. But when you just declare char *str, all it does is create a pointer. This doesn't have any associated memory block for the array.

That's why you have to declare a character array of some size before storing strings in it with scanf(). Or you have to dynamically allocate memory with calloc or malloc after declaring the char * pointer. Only then can you store a string input in it.

I have modified your code to work properly. It produces the desired output now. Hope this helps.

WORKING CODE

#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;
}

EDIT

They themselves are integers actually (as are all pointers).
As mentioned by anastaciu, pointers are not equivalent to integers per se. You can follow the links given in his comments for more knowledge. I had mentioned that statement to assert the difference between pointers and array declarations.

Akash Das
  • 163
  • 15
  • Pointers are not just integers, it's more complicated than that, even their sizes are usually different deppending on the platform, see https://wandbox.org/permlink/BjRgO4VutCMKxzMg, you can also see [Is pointer just an integer?](https://stackoverflow.com/questions/27199805/is-pointer-just-an-integer) and [Are pointers stored as integers?](https://stackoverflow.com/questions/17114343/are-pointers-stored-as-integers). – anastaciu Feb 13 '20 at 12:25
  • 1
    @anastaciu I was aware of the fact. It was an oversimplification on my part to make the OP understand. I think my post touches on all of his doubts and makes an effort to clarify the same. And thank you for the posts. I learned something more today. It is easy to imagine pointers as integers. The reason I had stated that was to distinguish them from array declaration. I'll make an edit to my answer to highlight your point. It'll be nice if you can remove the downvote. – Akash Das Feb 13 '20 at 12:33
  • 1
    @anastaciu Thanks anyway mate. It helped me make the answer better. – Akash Das Feb 13 '20 at 12:50