Why is that?

P

Profetas

I know what is causing the problem, but I couldn't
find out why.

#define newline "\n"
#define question_mark "\?"
#define single_quotas "\'"
#define double_quotas "\""
#define form_feed "\f"
#define horizontal_tab "\t"
#define vertical_tab "\v"
#define backslash "\\"
#include <stdio.h>

main(){
int var;
printf("Type a number:");
scanf("%d",&var);
printf("The number is ");
printf("%d",var);
printf(newline);

char *var2;
printf("Type a string:");
int bytes_read=0;
int nbytes = 100;

var2 = (char *) malloc (nbytes + 1);
bytes_read = getline (&var2, &nbytes, stdin);
if(bytes_read == -1)
{puts ("ERROR!: invalid input");}

printf("The string is ");
printf("%s",var2);
printf(newline);
}
 
M

Michael Mair

Hi Profetas,

I know what is causing the problem, but I couldn't
find out why.

Very enlightening. What do you think your problem is?
Your code does not even compile...
#define newline "\n"
#define question_mark "\?"
#define single_quotas "\'"
#define double_quotas "\""
#define form_feed "\f"
#define horizontal_tab "\t"
#define vertical_tab "\v"
#define backslash "\\"

Won't comment on the sense or nonsense of these macros.
Apart from the newline, you do not need that stuff. Please
keep your examples minimal.
#include <stdio.h>

Where is <stdlib.h> needed for malloc()?
And where is the header for the non-standard getline()
function? (see below, too)

int main ()
int var;
printf("Type a number:");
scanf("%d",&var);
printf("The number is ");
printf("%d",var);
printf(newline);

char *var2;
printf("Type a string:");
int bytes_read=0;
int nbytes = 100;

var2 = (char *) malloc (nbytes + 1);
You have been around here long enough: Do not cast the
result of malloc(). Btw: If you want to apply a cast,
then cast nbytes -- malloc takes a size_t argument.
bytes_read = getline (&var2, &nbytes, stdin);
from 'man getline':
#define _GNU_SOURCE
#include <stdio.h>

ssize_t getline(char **lineptr, size_t *n, FILE *stream);
I do not know the return type ssize_t but the rest of the manpage
seems to tell me that it is an improved version of fgets() such
as most of us have in their personal library...
I would just make var2=NULL -- as getline is taking care of
allocation, this is alright for a short program.
if(bytes_read == -1)
bytes_read is not of type ssize_t.
{puts ("ERROR!: invalid input");} It might be another problem

printf("The string is ");
printf("%s",var2);
printf(newline);
}
free() var2. Apart from that: Why use printf() for giving
a '\n'.

Please produce code that compiles for
gcc -ansi -pedantic
and then come back.


--Michael
 
M

Michael Mair

Before I forget it:

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

#define newline "\n"

int main (void)
{
int var;
char *var2 = NULL;
ssize_t bytes_read = 0;
size_t nbytes = 0;


printf("Type a number: "); (void) fflush(stdout);
bytes_read = getline (&var2, &nbytes, stdin);
if(bytes_read == -1)
{
fprintf(stderr,"ERROR in line %d in return value from"
" getline()" newline, __LINE__);
(void) fflush(stderr);
exit(EXIT_FAILURE);
}
if (sscanf(var2, "%d", &var) != 1)
{
fprintf(stderr,"ERROR in line %d: scanf() could not squeeze"
" a number out of your input" newline, __LINE__);
(void) fflush(stderr);
exit(EXIT_FAILURE);
}
printf("The number is %d" newline, var);

printf("Type a string: "); (void) fflush(stdout);
bytes_read = getline (&var2, &nbytes, stdin);
if(bytes_read == -1)
{
fprintf(stderr,"ERROR in line %d in return value from"
" getline()" newline, __LINE__);
(void) fflush(stderr);
exit(EXIT_FAILURE);
}

printf("The string is %s" newline, var2); (void) fflush(stdout);

free(var2);
exit(EXIT_SUCCESS);
}


does the job for those of us with a new enough gcc compiler.

Your problem, of course, was the part I replaced by the
getline()/sscanf() pair.
Everyone else: Think fgets()/sscanf() and allocated buffer
var2.
As to the why: scanf() and family just do not empty the
input buffer as you seem to expect but get only what
they want. getline() found the leftover '\n' and that was
it. So, if you want to do it with scanf(), you will have
to empty the input buffer line with s.th. like

while ( (c=getchar()) != EOF )
if (c=='\n')
break;

(not tested)

Cheers
Michael
 
P

Profetas

Which problem is that?

after the scanf is edxecuted it won't execute the getline

bash-2.05b$ ./a.out
Type a number:12
The number is 12
Type a string:The string is
 
P

Profetas

Your problem, of course, was the part I replaced by the
getline()/sscanf() pair.
Everyone else: Think fgets()/sscanf() and allocated buffer
var2.
As to the why: scanf() and family just do not empty the
input buffer as you seem to expect but get only what
they want. getline() found the leftover '\n' and that was
it. So, if you want to do it with scanf(), you will have
to empty the input buffer line with s.th. like

That is what I was looking for.

Thanks Michael Mair
 
J

Jack Klein

I know what is causing the problem, but I couldn't
find out why.

There is no version of standard C where this is a legal program.

The implicit int return type of main() is illegal from C99 onward.
int var;
printf("Type a number:");

[snip]
char *var2;

Defining a variable after executable statements in a block is only
legal from C99 onward.

And as for these:
#define newline "\n"
#define question_mark "\?"
#define single_quotas "\'"
#define double_quotas "\""
#define form_feed "\f"
#define horizontal_tab "\t"
#define vertical_tab "\v"
#define backslash "\\"

The standard doesn't allow it, but my opinion is that any program
written by anyone who writes macros this dumb should automatically
fail.
 
K

Keith Thompson

Jack Klein said:
[...]
And as for these:
#define newline "\n"
[snip]
The standard doesn't allow it, but my opinion is that any program
written by anyone who writes macros this dumb should automatically
fail.

I think you meant "The standard *does* allow it...".
 
C

CBFalconer

Keith said:
Jack Klein said:
And as for these:
#define newline "\n"
[snip]
The standard doesn't allow it, but my opinion is that any program
written by anyone who writes macros this dumb should automatically
fail.

I think you meant "The standard *does* allow it...".

I think he means the standard doesn't allow automatic failing of
extremely dumb programs.
 
K

Keith Thompson

CBFalconer said:
Keith said:
Jack Klein said:
And as for these:

#define newline "\n" [snip]
The standard doesn't allow it, but my opinion is that any program
written by anyone who writes macros this dumb should automatically
fail.

I think you meant "The standard *does* allow it...".

I think he means the standard doesn't allow automatic failing of
extremely dumb programs.

I think you're right. And so was he. And so am I (now).
 
P

Profetas

The standard doesn't allow it, but my opinion is that any program
written by anyone who writes macros this dumb should automatically
fail.

How do you know that it is dumb, if you don't even know the
rest of my program, and you don't know why it has been used
and its purpose, and how it has been written

don't judge what you don't know.
 
D

Dan Pop

In said:
fail.

How do you know that it is dumb, if you don't even know the
rest of my program, and you don't know why it has been used
and its purpose, and how it has been written

It is obvious, to anyone with a clue, that those macro definitions can
serve no good purpose in *any* C program.
don't judge what you don't know.

The judgment was entirely based on known things. Feel free to prove it
wrong by showing an example of good usage for those macros.

Here's an example of sensible macro:

#define SEPARATOR ','

and one of idiotic macro:

#define COMMA ','

The need to change the definition of SEPARATOR later in program's life is
conceivable, but there is no such need for a macro named COMMA.

Dan
 
C

Christopher Benson-Manica

Profetas said:
How do you know that it is dumb, if you don't even know the
rest of my program, and you don't know why it has been used
and its purpose, and how it has been written

Hang around here long enough and you'll realize that when certain
people (the eminent Mr. Klein being among them) call something you've
done "dumb", they're probably right. Lord knows it's happened to me
enough to know :)
 
T

Thomas Matthews

Profetas said:
I know what is causing the problem, but I couldn't
find out why.

#define newline "\n"
#define question_mark "\?"
#define single_quotas "\'"
#define double_quotas "\""
#define form_feed "\f"
#define horizontal_tab "\t"
#define vertical_tab "\v"
#define backslash "\\"

One of the main problems of the above macros is
that you are using strings instead of characters.

If I have:
const char statement[] = "Hello\t\"World?\"";
And I want to search for a "question_mark",
I would naturally want to use:
char * posn;
posn = strchr(statement, question_mark);
Which will not work because strchr() requires
a single char as the second parameter. Also,
this one will be hard to find:
posn = strchr(question_mark, statement);
In the above line, the first parameter has the
correct type, but wrong logic.

Also, please check your spelling. Note that
in English, "quota" and "quote" are two different
words. A quota is a limit. One could have a
single quota. There could also be double quotas,
which means having two limits; which is far from
the symbol (").

At some point, macros lead more to obfuscating
a program than to readablility.
If you want to keep down this path, may I also
suggest these macros:
#define begin {
#define end }
#ifndef and
#define and &&
#endif
#ifndef or
#define or ||
#endif
#ifndef not
#define not !
#endif
#define ever 1
#define forever 1

while (forever)
begin
if (a and b)
begin
continue;
end
else
begin
break;
end
end


--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.comeaucomputing.com/learn/faq/
Other sites:
http://www.josuttis.com -- C++ STL Library book
 
C

Christopher Benson-Manica

Jack Klein said:
The standard doesn't allow it, but my opinion is that any program
written by anyone who writes macros this dumb should automatically
fail.

#define Splat '*'

(a real line of source code here)

It's definitely dubious :)
 
D

Dave Thompson

Profetas wrote:
One of the main problems of the above macros is
that you are using strings instead of characters.
Maybe. The only one the OP actually uses is as a string.

You (i.e. everyone) certainly should understand the difference between
(single) char and string (array of char, null terminated), and if you
need char's #define them -- if you #define at all; as others have
noted, these macros for obvious constants aren't very valuable.

But if you (may) need both, it's easier to get a char from a string
"\n" and *"\n' or possibly "\n"[0]
than it is to get a string from a char, which is impossible in C89
without introducing a variable and in C99 requires the clumsy
(/*const*/ char []){ '\n' }


- David.Thompson1 at worldnet.att.net
 
O

ozbear

Maybe. The only one the OP actually uses is as a string.

You (i.e. everyone) certainly should understand the difference between
(single) char and string (array of char, null terminated), and if you
need char's #define them -- if you #define at all; as others have
noted, these macros for obvious constants aren't very valuable.

The difference becomes specious and/or non-existent in the case
of a single char which contains '\0' as its value.

Given a definition
char mychar = '0';

and passing &mychar to a function expecting "string" is legal.

It is therefore both a single char and a 0-terminated string.

It is purely a point-of-view thing.

Oz
 
D

Dan Pop

In said:
The difference becomes specious and/or non-existent in the case
of a single char which contains '\0' as its value.

Given a definition
char mychar = '0';

You've been correct in the plain English text, but not in the C code:
'\0' and '0' are completely different things, so make it:

char mychar = '\0';

To avoid this mistake (probably a typo in Oz's case), I simply never
bother using '\0'. A plain 0 will not leave any place for doubts when
used in a character context and mistyping '0' when you mean 0 (or vice
versa) is highly unlikely (this typically happens due to a thinko).

Dan
 
O

ozbear

You've been correct in the plain English text, but not in the C code:
'\0' and '0' are completely different things, so make it:

char mychar = '\0';

To avoid this mistake (probably a typo in Oz's case), I simply never
bother using '\0'. A plain 0 will not leave any place for doubts when
used in a character context and mistyping '0' when you mean 0 (or vice
versa) is highly unlikely (this typically happens due to a thinko).

Hmmm... dunno where the '\' went but indeed it was a typo.
Using the unadorned 0 is a better idea, at least in this case.
Thanks for the correction.

Oz
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,146
Messages
2,570,832
Members
47,374
Latest member
anuragag27

Latest Threads

Top