1

I have a few questions about C syntax.

  1. ch = (char *) malloc( sizeof( char ) * strlen(src) ); What do the first brackets mean (char *) ?

  2. c=getch();

    switch(c) {

    case '1' :{

    My teacher asked why 'this type' quotation marks are used and not "double". I said that it is C syntax if using char variable. But he said NO! Why are single quotation marks used and not double?

  3. Sometimes when using scanf nothing happens and it has be used two times to get something scanned. What is the reason of this problem? For example:

    printf("enter string \n");   
    scanf("%s",&str);
    printf("enter char \n");  
    scanf("%c",&ch);  //does not scan my char
    scanf("%c",&ch);  //with this second line do scan my char
    
ApproachingDarknessFish
  • 14,133
  • 7
  • 40
  • 79
va.
  • 848
  • 3
  • 17
  • 39

8 Answers8

13

Others have already answered yor First two Questions correctly, So I will answer your third Q:

When you enter a character and hit the ENTER key, two characters are placed in the input buffer, the character and the newline character.

You need to account for both of these. So First scanf consumes the newline and another reads the character.

Step by Step Code Analysis:

printf("enter string \n");   
scanf("%s",&str);

With above two statements, You see Enter the string and program waits for your input. Let us assume you enter the character C and pressed Enter once. When you perform this action, the input buffer receives two characters:

  1. The character C that you entered &
  2. The newline character \n

The scanf statement reads just one character(C) from the input buffer.Thus, the newline character remains unread in the Inuput buffer.

printf("enter char \n");  
scanf("%c",&ch);  //does not scan my char

With above two statements, enter char gets displayed but the scanf just skips(not wait for any uer input), this is because the unread newline character in the Input buffer is read by this scanf.

So to appropriately receive the next input character you need an additional scanf.

scanf("%c",&ch);  //with this second line do scan my char
Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • I'm curious, why does the `scanf` consume the characters in what seems like the reverse order? – David Heffernan Oct 19 '11 at 19:22
  • @DavidHeffernan:Sorry,I saw this comment quite late(the time diff),Apparantely, my answer was not explanatory,I added a detail step by step to answer your query. – Alok Save Oct 20 '11 at 04:00
5
ch = (char *) malloc( sizeof( char ) * strlen(src) );

The (char*) is a cast. It says to treat the return value of malloc as a pointer to char. However, this is not necessary since void*, the return type of malloc is assignment compatible with all pointer variables in C.

What's more the sizeof(char) is spurious since sizeof(char) == 1 by definition. Finally this allocation almost certainly allocates one element too few. There needs to be space for the zero terminator.

So, it should probably be written:

ch = malloc(strlen(src)+1);

As for '1', this is a char literal. It has type int.

This is not too be confused with "1" which is a string literal, of type char*, a pointer to a block of memory containing two chars, '1' followed by \0.


As for question 3, it's not clear to me what you mean and in any case I will invoke the one question at a time rule to justify not addressing it! Others have answered that for you.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
4

In simple terms:

1) since malloc returns a pointer of type void, you are casting that pointer to a pointer of type char so that the variable ch will later hold an array of characters (a string )

2) the single quotation marks are mainly used because a switch statement in C always expects an INTEGER and, not a string. having a character surrounded by single quotations would return the integer representation of the character.

3) This is a common problem when using scanf, basically it is caused by by the carriage return that is entered from the previous scanf. I would recommend that you always flush the input before using it.

Here's an example:

#include <stdio.h>

int main (void)
{
    char line[200];
    while(1)
    {
        printf("\nenter a string: ");
        fflush(stdout);         // safety flush since no newline in printf above
        scanf(" %[^\n]",line);  // note space character
        printf("you entered >%s<\n",line);
    }
    return 0;
}
Dahdahm
  • 513
  • 3
  • 16
2
  1. This is cast; it treats the return value of malloc (a void*) as a char*.

  2. This is an ordinary char literal.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
2

In:

char *ch = (char *) malloc( sizeof( char ) * strlen(src) );

The first (char *) casts the return value to a char *. In C, this is completely unnecessary, and can mask failure to #include <stdlib.h>.

In addition, sizeof(char) is always 1, so is never needed.

The character literal '1' has type int in C.

Most likely getch returns an int. The string literal "1" consists of two characters. The digit 1 and the end of string marker NUL character. If you had used case "1": the return value of getch would be compared to the value of the pointer to "1" (after an implicit conversion to int).

As for scanf, the input buffer might contain input that hasn't been processed by your program.

See also Why does everyone say not to use scanf? What should I use instead? .

Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339
1
  1. The (char ) at the beginning of the first statement is a typecast. By default malloc returns a void which should be fine to assign to a char*, but in other cases typecasting is required.

  2. You are correct single quotes should be used around charaters.

  3. Saying scanf sometimes doesn't work is a meaningless statement without example code.

Craig H
  • 7,949
  • 16
  • 49
  • 61
1
  1. (char *) is a cast; it means "treat the following value as a pointer to char". In this particular case it's redundant and considered bad practice.

  2. '1' is a character constant; somewhat non-intuitively, it has type int (this is different from C++, where character constants are type char). "1" would be a string constant, which is actually an array expression of type char [2] and has the contents {'1', 0}.

  3. This is because a newline has been left in the input stream from the previous input operation. Suppose you type "foo" and hit Return; the input stream will then contain the characters 'f', 'o', 'o', '\n'. The first scanf call reads and assigns "foo" to str, leaving the trailing '\n' in the input stream. That stray newline is being picked up by the next scanf call because the %c conversion specifier doesn't skip whitespace (unlike just about every other conversion specifier).

John Bode
  • 119,563
  • 19
  • 122
  • 198
0

I d like to add to @Alok Save s answer. He has analysed it correctly however, another simple solution exists for that case and that is to use scanf with a whitespace in the string format as follows:

scanf(" %c", &variable);

This is because %c does not absorb the newline character like others(like %d) do. Any whitespace in the format string will cause scan to absorb all consecutive whitespaces thereby obviating the need for another scanf statement.

Hope this helps!

Kevin
  • 566
  • 2
  • 5
  • 13