Hi,

I tried to do like below, but its not printing the expected one. Plz suggest to proceed further.

OUTPUT:

Enter the string: abc
Entered string is : NULL

void main()
{
    char *a;

    printf("Enter the string: ");
    scanf("%s",&a);

    printf("\nEntered string is :%s", a);
    getch();
}

Recommended Answers

All 9 Replies

OK. This is a common problem for beginners. You have a pointer (*a). This pointer points to nothing.
You do a scanf into the pointer. The program has an aneurysm. The stock market collapses! Puppies and kittens around the world suddenly vanish!
Heh. So yeah. *a needs something to point to.

Try one of the following:
1: Using an array.

#include <stdio.h>
#include <conio.h>

void main()
{
    char a[101];

    printf("Enter the string: ");
    scanf("%s",&a); //You can keep the ampersand, but you don't need it here.

    printf("\nEntered string is :%s", a);
    getch();
}

2: Allocating a buffer.

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
void main()
{
    char *a;
    a=(char*)malloc(101*sizeof(char));
    printf("Enter the string: ");
    scanf("%s",a);  // You definitely don't want the ampersand here.
                    //That'd be a pointer to a pointer

    printf("\nEntered string is :%s", a);
    getch();
    free(a);
}

Now, why did I use 101 as my size? C needs a zero terminator at the end of its strings, so you have to allocate +1 more than the size you want.

commented: Thanks for prompt reply.. +0

Also, here's an instructional video from Stanford on using Pointers.
Stanford Explains Pointers
I'm putting this as a second post as my first post deserves an up-vote while this post, despite its clearly educational value, will brand me as an insufferable troll.
And I probably deserve that.
Enjoy!

There are a number of mistakes in this code, starting with the use of void main() rather than int main(). While the older C standard allows for it, it is a non-portable variant, and the IIRC newest version of the standard closes that loophole by requiring main() to return an int.

The next major issue is that while you declare a char pointer, you do not actually set aside any memory to store the string in. You will want to either use a static buffer:

char a[1024];

or else allocate the memory you are using dynamically:

char* a;
a = calloc(1024, sizeof(char));

If you do the latter, remember to free() the memory when finished.

Finally, in the line scanf("%s",&a);, you are taking a reference a, which is a pointer; thus, you are passing scanf() the address of a itself, not the address of the buffer you are trying to put the string into. You would want to use

scanf("%s", a);

There's still an issue with that, however, in that you aren't taking any precautions agains overrunning the buffer. This can be fixed using a string width modifier:

scanf(%1023s", a);

(There are tricks for setting the width dynamically, but that's getting a bit complicated at this stage). However, for string input, you might be better off using fgets() anyway, as it will read a string up to a maximum size, without stopping at whitespace.

#include <stdio.h>

#define BUFFER_SIZE 1024

int main()
{
    char a[BUFFER_SIZE];
    printf("Enter the string: ");
    fgets(a, BUFFER_SIZE, stdin);
    printf("\nEntered string is: %s", a);
}

Thanks Schol-R-LEA for explaining scanf with & and without & for char data type.

how to allocate memory and set 0 as default for a char variable

I'm going to go into pedantic mode for a bit. Apologies if either of you are offended in the process.

#include <conio.h>

C is a widely portable language, which means it's possible to take code and compile it on a multitude of operating systems and compilers without any changes. But that doesn't mean code is always portable; it's the job of the programmer to make sure that code is as portable as possible while still doing what needs to be done.

Now, that said, conio.h is not a portable library. Even if a compiler supports it, the functions that are supported within can vary greatly. One excellent example is the clrscr() function which is only supported (to the best of my knowledge) by Borland compilers, yet it's very commonly--and unnecessarily--included as a first step in many example programs:

#include <stdio.h>
#include <conio.h>

int main(void)
{
    clrscr(); /* Not needed and not portable! */

    printf("Hello, world!\n");

    return 0;
}

On a side note, I'll be happy to explain the issues with clrscr() in another reply if you're interested. The result is that these example programs are only compilable without change on the same compiler used to test them (assuming they were even tested). The closing getch() is another example shown in this thread:

#include <stdio.h>
#include <conio.h>

int main(void)
{
    printf("Hello, world!\n");

    printf("Press any key to continue . . .");
    fflush(stdout);
    getch(); /* Not portable and only conditionally needed! */

    return 0;
}

Using getch() to pause at the end of the program isn't as asinine as using clrscr() to clear the screen at the beginning of the program, but it's still not portable. There's also a portable solution that is close enough, provided you make sure the input stream is clean:

#include <stdio.h>

int main(void)
{
    printf("Hello, world!\n");

    printf("Press [Enter] to continue . . .");
    fflush(stdout);
    getchar(); /* Portable, but still only conditionally needed */

    return 0;
}

The conditional need is important to understand. The output window for your program will only close by itself if it's owned by the process that runs your program. This will happen in some IDEs (Dev-C++ is a notable example) and also if the program's icon is run directly. It will not happen in most modern IDEs or if the program is run from the command line.

The take home lesson here is that if there is a portable substitute for a non-portable solution, the portable substitute should be preferred unless there's very good reason not to use it.

void main()

This is another portability issue. Using void as the return type for main() is conditionally defined, which means that if the compiler supports it you're fine. If the compiler doesn't support it then you've invoked undefined behavior. Undefined behavior is the kiss of death for a C program because it removes all restrictions; the program can do anything at all, at any time, and there's nothing you can do about it. You must avoid undefined behavior at all costs.

The C standard specifies main() to return int, and that's the only 100% portable return type. It further goes on to allow implementation-defined signatures, which includes a return type of void. Given the potentially disastrous results of returning void, and the very minor annoyance of including a return statement when the return type is int, it's generally seen as better to always use int. Compare and contrast the two options.

Returning void:

#include <stdio.h>

void main(void)
{
    printf("Hello, world!\n");
}

Returning int:

#include <stdio.h>

int main(void)
{
    printf("Hello, world!\n");

    return 0;
}

a=(char*)malloc(101*sizeof(char));

This is fine as-is, but I'll note three things to consider:

  1. sizeof(char) is absolutely guaranteed to produce 1. You can safely remove the multiplier, though it's also fine as it is to act as a kind of future proofing. I've done this before in anticipation of modifying the code to support wide characters for internationalization. In that case the multiplier is needed because you'll be using a character type larger than 1, such as sizeof(wchar_t).

    This is a common trick:

        a = malloc(101 * sizeof *a);
    

    It looks broken because a is being dereferenced, but sizeof doesn't actually evaluate the expression, it only determines the result type. So this trick is ideal for correctly acquiring the type of the destination pointer without needing to specify the type explicitly.

  2. In C there's an implicit conversion both to and from void*, so technically you don't need to cast the result of malloc(). In fact, casting malloc() can hide a bug where stdlib.h isn't included. Without the cast, the compiler will rightly tell you that malloc() has no declaration while the cast will silence that warning. However, the cast isn't wrong per se because one might want to write C code that also compiles cleanly as C++. C++ doesn't allow an implicit conversion from void*, so when compiled as C++ the cast is required.

  3. malloc() can fail and return a null pointer. This is an important case to check for.

printf("Enter the string: ");

Yet another portability issue. While this will work fine on Windows (in my experience), it's not required to show the output of printf() before scanf() blocks for input. In Unix and Linux, for example, scanf() may block for input before the prompt is shown, so the user won't know what to do.

In C the basic rule for output is if you don't print a newline character or explicitly flush the stream, there's no guarantee that the output will be shown immediately. So the two options are thus:

  1. Print a newline at the end of the prompt and allow the user to enter input on the next line.

        printf("Enter the string:\n");
    

    This can be irritating if you're a stickler for the user interface and want the input to be on the same line as the prompt.

  2. Use fflush() to force the output to show:

        printf("Enter the string: ");
        fflush(stdout);
    

scanf("%s",&a); //You can keep the ampersand, but you don't need it here.

If you keep the ampersand, it's undefined behavior. I'm not aware of a compiler that will actually break if you use the ampersand on an object that's already a pointer, but technically it's wrong. The problem is not with the address (which is the same for both a and &a), but the type. The type of a is char* while the type of &a is char**. This can confuse printf() internally, because the expected type of %s is char*.

It's clear from your comment in the example allocating a buffer that you understand the type difference, but the same problem exists with an array due to the conversion to a pointer type when array names are used in value context.

Also, using %s without a field width risks buffer overflow. There's nothing stopping the user from typing 1000 characters and scanf() will happily write all of them to the 101 sized a. You can fix this by specifying exactly how many characters you want at most (excluding room for the null character):

scanf("%100s", a);

Another important thing to remember is that scanf() can also fail. Be sure to check for error conditions by checking the return value. In the case of scanf(), you can test against the number of expected conversions (variables that are populated with data). If the return value doesn't match that number, scanf() failed for some reason and you cannot safely use those variables.

So the "correct" code, given all of this information would be as follows for the array solution:

#include <stdio.h>

int main(void)
{
    char a[101];

    printf("Enter the string: ");
    fflush(stdout);

    if (scanf("%100s", a) == 1)
    {
        printf("Entered string is: '%s'\n", a);
    }

    return 0;
}

And like this for the pointer solution:

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

int main(void)
{
    char* a = malloc(101);

    if (a)
    {
        printf("Enter the string: ");
        fflush(stdout);

        if (scanf("%100s", a) == 1)
        {
            printf("Entered string is: '%s'\n", a);
        }

        free(a);
    }

    return 0;
}

Last but not least, I'd like to question why scanf() is being used for string input in these programs. The %s specifier is delimited by whitespace, so you can technically only read a single "word" while a line-based input function like fgets() is generally preferred.

I'm going to go into pedantic mode for a bit. Apologies if either of you are offended in the process.

And here I thought I was being the insufferable troll. ;)

i'm not able to execute the below line.

consider string is "abc abc 123 abc123abcabc 123abc 123abcdef 123 abcde"

int i=0;
int j=0;
char      *TempString;
TempString = (char*)malloc(strlen(String)*sizeof(char));
TempString = String;
    while(String[i])
    {
        if((String[i] == '1') && (String[i+1] == '2')) // Deleting string "123" 
        {   
            while(String[i] != '3')
                i++;
            i++;
            flagcount++;
        }
        TempString[j] = String[i];//its crashing here while debugging.
        i++; j++;
    }
    TempString[j]=0;    

In Line 4, you're allocating a char buffer and assigning it to TempString.
And you need to add 1 to account for the trailing zero. strlen will only get the non-zero characters.
In Line 5, you're assigning String to TempString, overwriting the pointer to the buffer you'd just created. Um...why?
That buffer is gone and you can't get it back.
The rest of it I'm too lazy to check, though it looks like it would work though not the way I'd do it.
Have a look at strstr. It does a body good.

int i=0;
int j=0;
char      *TempString;
TempString = (char*)malloc((strlen(String)+1)*sizeof(char));
//TempString = String;
    while(String[i])
    {
        if((String[i] == '1') && (String[i+1] == '2')) // Deleting string "123" 
        {   
            while(String[i] != '3')
                i++;
            i++;
            flagcount++;
        }
        TempString[j] = String[i];//its crashing here while debugging.
        i++; j++;
    }
    TempString[j]=0;    
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.