Hi!

On different occassions (random as much as I can tell) the "gets" command does not work.
The compiler simply skips it and moves on to the next code line.
Like I said, other times it does work.
Any suggestions?

Thanks
Ami

Without code it's hard to tell, but going on my experience, I'd say that you're mixing scanf with gets somewhere. It looks like gets is skipped, but it's actually reading an empty line and terminating right away since scanf tends to leave a newline in the stream. This simple program shows the problem:

#include <stdio.h>

int main(void)
{
  int i;

  printf("Enter an integer: ");
  fflush(stdout);

  if (scanf("%d", &i) == 1)
    printf("The next character is %d\n", getchar());

  return 0;
}

You'll probably get 10 for the output, which is a newline in ASCII. Gets reads characters up to a newline, so it'll terminate right away.

Hi!
Ok I think you're right. It so happens that my "gets" comes after a "scanf" like here:

void input(struct student vec[],int i)
{
 puts("Enter ID");
 scanf("%ld",&vec[i].id);
 if (vec[i].id)
 {
  puts("Enter student name");
  gets(vec[i].name);
  puts("Enter course");
  gets(vec[i].course);
  puts("Enter mark");
  scanf("%d",&vec[i].mark);
 }
}

What's the solution? I have to use gets for spaces and I need scanf for integer.

thanks
Ami

What's the solution?

Welp, the solution with gets is to not use it. gets is dangerous because it doesn't check for buffer overflow. But that's not your current problem, stream corruption is. The solution to that is to always clean up the stream. The best way to always clean up the stream is to avoid getting it messy in the first place, and that means avoiding scanf. Instead, use fgets and sscanf.

void input(struct student vec[], int i)
{
  char buffer[BUFSIZ];

  puts("Enter ID");
  fgets(buffer, sizeof buffer, stdin);
  sscanf(buffer, "%ld", &vec[i].id);

  if (vec[i].id)
  {
    puts("Enter student name");
    fgets(vec[i].name, sizeof vec[i].name, stdin);
    puts("Enter course");
    fgets(vec[i].course, sizeof vec[i].course, stdin);
    puts("Enter mark");
    fgets(buffer, sizeof buffer, stdin);
    sscanf(buffer, "%d", &vec[i].mark);
  }
}

It's also a great idea to validate any input, especially user input. fgets returns NULL if it fails and sscanf will return the number of items that are successfully converted. So each of the sscanf calls should return 1 if all is well. :)

There are more details, but you should be good for now.

Comments
Good answer - Salem

But that's not your current problem, stream corruption is.

I've been learning C now since May (twice a week 3 hours at a time). I don't know what "stream corruption" means!
I live in Israel so the classes are in hebrew but I don't believe the teacher mentioned the word "stream" in any way shape or form. I hope this is normal for the stage I'm at. I learnt the following so far:
of course all the basics of int, char etc.
Condtion (If else)
Loops (for, while, do)
Arrays (regular AND matrix. strlen, strcmp etc.)
Pointers (and p2p)
Functions/Procedures
Structures

I decided to try and do also some learning on my own. for a few reasons:
1) I love programming and 6 hours a WEEK with a slow pace just aint enough for me.
2) I don't want to wait till I finish the course to get a job (2.5 years from now), I'd rather try and be an intern somewhere so I need to advance my self abit.
3) Personally I don't believe we learn enough in class. And I think our teacher also encoureges us to do some learning on owr own.

Anyway....

Please explain what a "stream" is?
I'm going thru "Thinking in C" by Chuck Allison and it's great so far. He also mentions stream all the time so it sounds pretty basic...I dunno Maybe I just know the hebrew word for it.

Thanks
Ami

I don't know what "stream corruption" means!

In this case, stream corruption means that there's stuff in the stream that you didn't expect or want.

Please explain what a "stream" is?

You've probably heard about stdin and stdout, right? Those are streams. When you write to stdout with printf, you're putting characters onto the stream and then they're written to your monitor. When you type on the keyboard, characters are sent to stdin, which you can read using scanf. That's a simple explanation, but it works for the most part. :)

Thanks.
I also see in the "help" of Borland C++ that they recommend using the combination of fgets and sscanf rather than scanf.
Can you please explain something to me: you wrote:

char buffer[BUFSIZ];

  puts("Enter ID");
  fgets(buffer, sizeof buffer, stdin);
  sscanf(buffer, "%ld", &vec[i].id);

buffer will get whatever i type from the keyboard as long as it's less than BUFSIZ (512).
you defined buffer as char. how does it take in a long int as a number and therefore allowing me to then put it into vec.id? Why doesn't it "ASCII it" to a char/string?

Thanks for your patiance,
Ami

>Why doesn't it "ASCII it" to a char/string?
It does. Everything that goes to stdout or comes from stdin is a character or a collection of characters. So fgets reads a bunch of characters from stdin. Then sscanf is used to convert those characters into an integer value. The same thing goes the other way with printf, where non-string types are converted to strings so that they can be written to stdout.

Hi again!
Ok I need another clearfication about sscanf.
If understand correctly sscanf kinda works like atoi, right?

char buffer[BUFSIZ]="10989";
int b;
b=atoi(buffer);
printf("%d",b); /* 10989 */

Only better because it's not limited to a specific format (i.e integer).
Is this correct?

Thanks
Ami

How does "b" end up b==10989?

If understand correctly sscanf kinda works like atoi, right?

Ya, more or less.

Only better because it's not limited to a specific format (i.e integer).

That's one reason. atoi is a bad idea because it doesn't handle errors well, that's another reason sscanf is better. :)

How does "b" end up b==10989?

Here's the idea behind it.

int atoi(char *s)
{
  int result = 0;

  while (*s && isdigit(*s))
    result = 10 * result + (*s - '0');

  return result;
}

uh oh! the more "examples" and code you write it seams I have more question. I hope you don't mind:
1) Can you explain or reffer me to explanation in the help for this:

(*s - '0');

2) I read the help on "isdigit" - why do you need it here? isn't while(*s) enough?
3) And finally, did you mean to s++ at some point in the code?

Thanks
Ami

uh oh! the more "examples" and code you write it seams I have more question.I hope you don't mind

Ya, that's how it works with me too. :) I don't mind at all.

Let's see.

1) *s is a character, one of '0', '1', '2', '3', '4', '5', '6', '7', '8', or '9'. But let's say the character set is ASCII. The values of those characters range from 48 to 57. If you wanted to convert "256" to 256 then using 50, 53, and 54 instead of 2, 5, and 6 kinda screws the math up. ;) But! If you subtract '0' from the number then you get the number it represents. Subtract 48 from 50 and you get 2. Subtract 48 from 53 and you get 5. Cool, huh?

2) What if the string is "Hi! I'm gonna blow your algorithm to smithereens!"? ;)

3) Yes. Yes, I did. :)

Thanks for the explanations.

What would isdigit retun on the NULL byte?

What would isdigit retun on the NULL byte?

It won't test the null character. The first part of the loop expression stops it. But if isdigit did test the null character, it would return false because 0 doesn't represent a digit.

0 doesn't represent a digit.

Well thats news to me :cheesy: (maybe you wanted to say that 0 doesnt represent true condition )

The description of the function:

The function isdigit() returns non-zero if its argument is a digit between 0 and 9. Otherwise, zero is returned.

So if anything from '0' to '9' is encountered a non zero value is returned and if anything else 0 is returned which would invalidate the conditional stmt like "if", "while" etc.

0 doesn't represent a digit.

Well thats news to me :cheesy: (maybe you wanted to say that 0 doesnt represent true condition )

I'm with Inana here. 0 does not represent a digit, it represents a binary 0. '0' represents a digit. A digit is an ASCII character, therefore it's '0' thru '9'.

Well thats news to me :cheesy: (maybe you wanted to say that 0 doesnt represent true condition )

0 is 0, but 0 is not '0', and '0' is the representation of 0 that isdigit is looking for. :cheesy: Makes perfect sense, right? ;)

Hmm looks like there is some misunderstanding here.

I was refering to the "zero" as you say which is returned by the isdigit (char mychar) which is used to test a condition using "if", "while"....

So the zero which returned by the function isdigit (char mychar) when it encounters a null character is actually 0 and not '0' or binary 0 or octal 0 or hexadecimal 0 and what not zero :D.

Hmm looks like there is some misunderstanding here.

Mine or yours? :cheesy: I'm good at misunderstanding things.

So the zero which returned by the function isdigit (char mychar) when it encounters a null character is actually 0 and not '0' or binary 0 or octal 0 or hexadecimal 0 and what not zero .:D

It's not '0', but it is the rest of 'em. The value 0 is pretty versatile after all. ;)

Mine or yours? :cheesy: I'm good at misunderstanding things.

Hmm.. ok lets call this umm... a communication gap.

It's not '0', but it is the rest of 'em. The value 0 is pretty versatile after all.

But still i would call it 0 just to save my head all the extra swimming.
Versatile nature will be exploited by me when it comes to it.:P

This article has been dead for over six months. Start a new discussion instead.