# user input problems in c



## graudeejs (Dec 9, 2009)

```
/************************************************************
 * By:		Aldis Berjoza <killasmurf86@gmail.com>
 * Date:	Sat 24 Oct 2009
 ************************************************************/

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

#define MAX_BOOKS 5


struct s_book {
	char	title[100];
	char	author[100];
	int	year;
	char	publishing[100];
};
typedef struct s_book t_book;


int main (void) {
	t_book *book;
	int	i,
		from,
		to;
	char tmp[5];


	if ((book = (t_book *) calloc(MAX_BOOKS, sizeof(struct s_book))) == NULL) {
		perror(NULL);
		exit(1);
	}

	printf("Input data!\n\n\n");

	for (i=0; i<MAX_BOOKS; i++) {

		printf("Author: ");
		scanf("%100s", book[i].author);
//		fgets(book[i].author, 100, stdin);
		printf("Title: ");
		scanf("%100s", book[i].title);
//		fgets(book[i].title, 100, stdin);
		printf("Publishing: ");
		scanf("%100s", book[i].publishing);
//		fgets(book[i].publishing, 100, stdin);
		printf("Year: ");
		scanf("%d", &(book[i].year));
//		fgets(tmp, 5, stdin);
//		book[i].year = atoi(tmp);
	


		printf("ok\n=========================\n\n");
	}

//	clrscr();

	printf("Search from year: ");
	scanf("%d", &from);
	printf("Search to year: ");
	scanf("%d", &to);

	printf("=================\n");
	for (i=0; i<MAX_BOOKS; i++) {
		if ((book[i].year >= from) && (book[i].year <= to)) {
			printf("%s - \"%s\", %s, %d\n",
				book[i].author,
				book[i].title,
				book[i].publishing,
				book[i].year);
		}
	}


	free(book);
	return 0;
}
```

I don't understand why this stupid app sometimes skip asking some fields....

What did I code wrong?
Please enlighten me.


----------



## Zare (Dec 9, 2009)

Why are you using scanf and fgets at the same time?


----------



## graudeejs (Dec 9, 2009)

I'm not using them at same time....
currently fgets is commented out

I just tried bo*th*, and get about same result....


----------



## SeanC (Dec 9, 2009)

No problem with input here, but changing >= to <= helps the search function:


```
for (i=0; i<MAX_BOOKS; i++) {
		if ((book[i].year >= from) && (book[i].year [color="Red"]<=[/color] to))
```


----------



## pmg (Dec 9, 2009)

The standard output is, by default, line buffered. That means output that isn't a full line (ends with '\n') might not appear immediately.

You have 2 solutions for that:

a) include a '\n' in the printf()
b) "force" the output to be displayed even incomplete.

a)

```
printf("Publishing:\n");
```

b)

```
printf("Publishing: ");
    fflush(stdout);
```


----------



## expl (Dec 9, 2009)

Problem was with reading integers, you should read everything as strings then convert.

fixed for ya:


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

#define MAX_BOOKS 5


struct s_book {
	char	title[100];
	char	author[100];
	char	year[100];
	char	publishing[100];
};
typedef struct s_book t_book;


int main (void) {
	t_book *book;
	int	i,
		from,
		to,
		year;
	char tmp[5],
		 s_from[100],
		 s_to[100];


	if ((book = (t_book *) calloc(MAX_BOOKS, sizeof(struct s_book))) == NULL) {
		perror(NULL);
		exit(1);
	}
	
	memset(book, 0, sizeof(struct s_book) * MAX_BOOKS);

	printf("Input data!\n\n\n");

	for (i=0; i<MAX_BOOKS; i++) {

		printf("Author: ");
		scanf("%99s", book[i].author);
//		fgets(book[i].author, 100, stdin);
		printf("Title: ");
		scanf("%99s", book[i].title);
//		fgets(book[i].title, 100, stdin);
		printf("Publishing: ");
		scanf("%99s", book[i].publishing);
//		fgets(book[i].publishing, 100, stdin);
		printf("Year: ");
		scanf("%99s", book[i].year);
//		fgets(tmp, 5, stdin);
//		book[i].year = atoi(tmp);
	


		printf("ok\n=========================\n\n");
	}

//	clrscr();

	printf("Search from year: ");
	scanf("%99s", s_from);
	printf("Search to year: ");
	scanf("%99s", s_to);

	printf("=================\n");
	
	from = atoi(s_from);
	to = atoi(s_to);
	for (i=0; i<MAX_BOOKS; i++) {
		year = atoi(book[i].year );
		if ((year >= from) && (year <= to)) {
			printf("%s - \"%s\", %s, %s\n",
				book[i].author,
				book[i].title,
				book[i].publishing,
				book[i].year);
		}
	}


	free(book);
	return 0;
}
```


----------



## graudeejs (Dec 9, 2009)

@ expl  <<< no that didn't work... 
after I press Enter it sometimes skips asking for year... it show *year:* then without waiting for my input it writes *ok*...

```
Author: asda dasd 
Title: Publishing: asd asd 
Year: ok
=========================

Author:
```

here it skipped asking for Title, and year....
It's acting like if I hit enter more than once after I tryped *asda dasd* for example

fflush didn't help either....
I'm really pissed about this behavior... i'm trying to figure this out for long time now.....


I bet solution is simple


----------



## SeanC (Dec 9, 2009)

Also, overflowing your arrays with more than 100 inputs will make it seem like the program is skipping the next field, but is actually using the overflow as new input for that field instead.


----------



## graudeejs (Dec 9, 2009)

OK, but i'm not even close to enter 100 characters... I typed some 10 max


----------



## pmg (Dec 9, 2009)

killasmurf86 said:
			
		

> @ expl  <<< no that didn't work...
> after I press Enter it sometimes skips asking for year... it show *year:* then without waiting for my input it writes *ok*...
> 
> ```
> ...



The scanf will stop at the first space, leaving " asd" for the year.

You really should read user input with fgets() and sscanf().


----------



## graudeejs (Dec 9, 2009)

ye, i just figured this out


----------



## graudeejs (Dec 9, 2009)

Ok seams i fixed this


----------



## graudeejs (Dec 9, 2009)

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

#define MAX_BOOKS 5


struct s_book {
	char	title[100];
	char	author[100];
	int		year;
	char	publishing[100];
};
typedef struct s_book t_book;


int main (void) {
	t_book *book;
	int	i,
		s_from,
		s_to;
	char tmp[7];


	if ((book = (t_book *) calloc(MAX_BOOKS, sizeof(struct s_book))) == NULL) {
		perror(NULL);
		exit(1);
	}
	
	memset(book, 0, sizeof(struct s_book) * MAX_BOOKS);

	printf("Input data!\n\n\n");

	for (i=0; i<MAX_BOOKS; i++) {

		printf("Author: ");
		fgets(book[i].author, 99, stdin);
		book[i].author[ (int) strlen(book[i].author) -1] = 0x0;

		printf("Title: ");
		fgets(book[i].title, 99, stdin);
		book[i].title[(int) strlen(book[i].title) -1] = 0x0;

		printf("Publishing: ");
		fgets(book[i].publishing, 99, stdin);
		book[i].publishing[(int) strlen(book[i].publishing) -1] = 0x0;

		printf("Year: ");
		fgets(tmp, 6, stdin);
		book[i].year = atoi(tmp);
	


		printf("ok\n=========================\n\n");
	}

//	clrscr();

	printf("Search from year: ");
	fgets(tmp, 6, stdin);
	s_from = atoi(tmp);

	printf("Search to year: ");
	fgets(tmp, 6, stdin);
	s_to = atoi(tmp);

	printf("=================\n");
	
	for (i=0; i<MAX_BOOKS; i++) {
		if ((book[i].year >= s_from) && (book[i].year <= s_to)) {
			printf("%s - \"%s\", %s, %d\n",
				book[i].author,
				book[i].title,
				book[i].publishing,
				book[i].year);
		}
	}


	free(book);
	return 0;
}
```

Thanks for help


----------



## pmg (Dec 9, 2009)

killasmurf86 said:
			
		

> ```
> #include <stdio.h>
> /* ... */
> char tmp[7];
> ...



You can use the full size of the array in fgets(), it already takes the terminating zero into consideration.

I usually do

```
char buf[100];
    fgets(buf, sizeof buf, stdin);
```


----------



## ocean (Dec 10, 2009)

i think the problem is that you are reading from buffer without counting "\n" that will be read from the next scanf (buffered input) just change the scanf like this

```
scanf("%100s%*c", book[i].author);
```
"%*c" tells scanf to jump one character (the newline)


----------

