Is it possible to have dynamic memory allocation in a string that is read with scanf without first declaring it as an array?
It is not possible to dynamically allocate memory for a string after having read it with scanf, as scanf needs a pointer. This means that you must allocate memory first, in order to give it as an argument to scanf.
You can do this like the following example :
char *str;
str = malloc(X*sizeof(char)); //where x is the number of characters you want to allocate
if (str != NULL)
int result = scanf("%s", str);
In other words, pass the allocated pointer to scanf.
Note : You should be careful about the input you give, as you might cause a buffer-overflow if you give a string which is larger than the allocated space.
From your question is seems you want to allocate the memory for the string after it has been scanned in. Unfortunately you are not able to do this as the scanf functions needs memory addresses to put the data that it scans in. The best you will be able to do is this:
char *someInput = malloc(sizeof(char) * 80);
scanf("%s", someInput);
Edit: note the 80 is an arbitrary amount, this represents how many characters we are allocating for our string to hold - 80 was chosen as it the usual length of a line in a command prompt.
Related
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main(){
char *s1;
char *s2;
printf("Enter the string : ");
scanf("%s",s1);
printf("Enter the string : ");
scanf("%s",s2);
return 0;
}
I'm facing problems in taking inputs in char pointer. Here I'm just taking 1 word as input but Scanf isn't taking any inputs at all when using char pointer, but works well with char arrays. Is it a code blocks bug?
A pointer is a variable that holds a memory address.
An uninitialized variable contains (generally) some random garbage number.
When you pass some random garbage number to scanf and tell it to store a string at that address, it's no surprise that (usually) the program crashes.
It makes no sense to tell scanf to store a string at an address where you don't know what the address is. It's like telling your friend to come over to your house and when they ask which house is yours, you click somewhere random on Google Maps. It's probably going to be in the middle of the ocean or something and they'll drown.
What you need to do is make a space to put the string (such as by declaring an array) and then tell scanf to put the string in that space that you specifically made to hold the string.
A pointer to a string does not hold the string. A pointer to a string is just a signpost saying "the string is over there --->", and you can change it if you want it to point to a different place, maybe holding a different string, but it's never going to hold a string itself.
This is a beginner-C-programmers' bug as old as the language itself.
There are two good solutions to your problem, either change the definitions of s1 and s2 to something like
char s1[BUFFER_LENGTH];
char s2[BUFFER_LENGTH];
...where BUFFER_LENGTH-1 is some sufficiently long string length, to tell the compiler to allocate enough memory on the stack, or manually allocate memory in the heap for them using malloc() like so:
char *s1 = malloc(BUFFER_LENGTH);
char *s2 = malloc(BUFFER_LENGTH);
But keep in mind that in both cases your code is unsafe because for any finite-length buffer, there is a string too long for it, which can cause your program to crash or overwrite something important in memory or give hackers access to stuff etc. etc.
A safe solution is to allocate memory for your strings in one of the two above ways, and only read strings that are small enough to fit into them. If you require the program to be able to handle a string of any length, your code will be much more complex, but there's still a safe way to do it.
#include <stdio.h>
#define BUFFER_LENGTH 20 //Arbitrary max string length + 1
int main(){
char s1[BUFFER_LENGTH]; //Can safely hold 19 chars for string and a null terminator
char s2[BUFFER_LENGTH];
printf("Enter the string : ");
scanf("%19s",s1); //%19s tells the function to only read max 19 characters
printf("Enter the string : ");
scanf("%19s",s2);
{
In the above example a string longer than 19 characters will be truncated, for instance "012345678901234567890" will be stored in s1 as "0123456789012345678" and s2 will have "90" since scanf will just use the leftover characters in the input buffer for the next call.
I'm using with a smaller piece of code to test functionality for a larger (beginner) program, but I don't understand the difference between two strings.
I found and used:
#include <stdio.h>
#include <string.h>
int main()
{
char *string, *found;
string = strdup ("1/2/3");
printf("Orig: '%s'\n",string);
while ((found = strsep(&string,"/")) != NULL )
printf ("%s\n",found);
return (0);
}
and this print the tokens one at a time.
Then when I try and move to a user entered string:
#include <stdio.h>
#include <string.h>
int main()
{
char string[13],
char *found, *cp = string;
fprintf(stderr, "\nEnter string: ");
scanf("%12s",string);
printf("Original string: '%s'\n",string);
while((found = strsep(&cp,"/,-")) != NULL )
printf("%s\n",found);
return(0);
}
I get a seg fault. I understand the basics of pointers, arrays and strings, but clearly I'm missing something, and would love for someone to tell me what it is!
Also - if I change printf("%s\n",found); to printf("%i\n",found); I get some junk integers returned, but always the correct amount, e.g. If I enter 1/2/3 I get three lines of integers, 1111/2222 I get two lines.
Thanks!
-Edit-
There was an adittional problem with strsep, detailed here. Thanks all.
In the first piece of code, string is assigned the return value of strdup, which allocates space for the string to duplicate and returns a pointer to that allocated space.
In the second piece of code, string uninitialized when it is passed to scanf, so scanf is reading the invalid value in that pointer and attempting to dereference it. This invokes undefined behavior which in this case manifests as a crash.
You need to set aside space for the user's string. A simple way to do this is to create an array of a given size:
char string[80];
Then tell scanf how many characters it can read in:
scanf("%79s",string);
Differences between the two cases:
In the first case string points to valid memory that was allocated by strdup while in the second case you are trying to read into invalid memory.
The first case is well behaved while the second case is cause for undefined behavior.
The second case can be fixed by allocating memory for it using malloc or using a fixed size array.
char *string,*found;
string = malloc(100); // Make it large enough for your need.
fprintf(stderr, "\nEnter string: ");
scanf("%99s",string);
or
char string[100], *found;
fprintf(stderr, "\nEnter string: ");
scanf("%99s",string);
Make sure you deallocate dynamically allocated memory. Otherwise, your program leaks memory.
You should allocate memory for the user input string.
First option is statically
char string[256];
and second option is dynamically using malloc() function
char *string;
string = (char*) malloc(256 * sizeof(char));
if (string == NULL)
{
//error
}
Don't forget at the end to release the allocated memory
free(string);
In user enter string case you do not have memory allocated to the pointer string.In the first case, strdup is allocating memory for string pointer while in the second case you do not have any memory associated with string pointer leading to segfault. first, allocate memory using malloc and then use scanf.
You didn't allocate the space needed !
You have to have a memory space to write to.
You can have it statically "char string[256]", or dynamically with allocation.
In your first example, you use "strdup" that does a malloc, but scanf will not allocate memory for you.
If you want all the user input, you usually wrap the scanf in a while loop in order to retrieve the user input chunk by chunk. Then you have to reallocate each time your buffer is insuffisante to add the chunk.
If you just want to retrieve a string from stdin without doing any format-checking, I strongly recommand fgets.
char string[13]
char cp=string
Here cp is a variable of type char and as 1 byte of memory allocated
It won't be able to store a char array of 13 character which would be 13 bytes, and it's because of this you are getting segmentation fault
The reason is very simple. Your string variable is a char pointer and you need to allocate memory to it to store a string.Probably in your first case strdup ("1/2/3"); returns a string and your char pointer *string points to the string return by strdup function and that is the reason why you are not getting the segmentation error in the first case. Even in your first case also you might get a segmentation error if enter a very long string.
so allocate enough memory to the string pointer like below in your second example and that will fix your problem:-
char *string = malloc(50);// here malloc will allocate 50 bytes from heap
Hi Im new to coding in C and I can't seem to find the problem which causes a segfault after the while loop starts.
int main() {
char option;
char nickname;
printf("Welcome to our chat program. Please select mode (Send,Nickname,Exit): ");
while (gets(option)) {
if(!strncmp(option, "Exit", 4)) {
break;
}
if(!strncmp(option, "Nickname", 8)){
set_nickname(nickname);
}
if(!strncmp(option, "Send", 4)){
if(!nickname){
nickname = "Anonymous";
printf("Your nickname was set to Anonymous!");
}
send_message(nickname);
}
}
There are many issues with the code. Let's discuss them one by one.
First of all, a char is not sufficient to hold a string, you need either
an array
a pointer with proper (dynamic) memory allocation.
Using the first approach, you need to change
char option;
char nickname;
to
#define SIZ 64
char option[SIZ] = {0};
char nicknamep[SIZ] = {0};
Then, instead of using gets(), you should be using fgets() to avoid the possibility of buffer overflow. Something like
fgets(option, SIZ, stdin);
will do.
That said, once option becomes an array, you cannot assign to it. You need to use strcpy() to copy the content into the array. For example,
strcpy(nickname, "Anonymous");
There is no memory allocated for the strings.
You need someting like this:
char option[50];
char nickname[50];
and use strcpy() here:
nickname = "Anonymous";
and check the string with strlen() for example.
if(!nickname){
It is also safer to use fgets() with a length parameter to prevent buffer overflow.
while (gets(option)) {
option needs to be char[???]
Not sure about nickname but it also needs memory allocated and/or initialisation. How do you set it? What value do you use?
You'll also need to check for strlen(nickname)>0 rather than !nickname which will test for a null pointer, not an empty string.
Never ever use gets; it cannot be used correctly. Instead, use fgets, with stdin as the third parameter.
You will notice that fgets takes the length of the storage you want to assign as its second parameter. The lack of this parameter in the gets function is why it cannot be used correctly. You should pass it the value 1 in your case, and pass it the address of your char variable. fgets will then read one character into your variable.
If you want to read more, you need to start by allocating more storage for the data you'll read. For instance, you could allocate space for 80 characters:
char string[80];
You can now use fgets with string as the first character, 80 as the second, and stdin as the third. fgets will then read up to 80 characters from stdin.
If you don't want to store that number in two locations in your source code, you can use the sizeof operator instead, or use a macro to predefine the size of your buffer.
I'm trying to read a file of 10 lines of varying lengths (which will not exceed 349 characters), and store them in a dynamically allocated array in order to be able to manipulate them later on. I have the below code which gives me a "warning: passing argument 1 of âstrcpyâ makes pointer from integer without a cast" message.
What did I do wrong here? My logic was that addresses should be a pointer to an array of pointers, where each pointer in the array points to a line in the string, which I would try to make happen by using strcpy of that line to that point.
char buffer[350];
char** addresses;
int i = 0;
*addresses = malloc(sizeof(char*)*10); /* Let's start off with 10 addresses */
while(fgets(buffer, sizeof(buffer), stdin) != NULL)
{
strcpy(*addresses[i],buffer);
i++;
}
You've got couple of issues:
Syntax:
Use
strcpy(addresses[i],buffer);
instead of
strcpy(*addresses[i],buffer);
Memory:
You need to allocate memory for addresses[i] before you can copy the contents of buffer to it.
Add a line to allocate memory for addresses[i] before the call to strcpy.
addresses[i] = malloc(sizeof(buffer));
You have to give like this,
strcpy(addresses[i],buffer);
If you give like this,
strcpy(*addresses[i],buffer);
First argument will consider as a single character.
And while allocating the memory you have do like this,
address=malloc(sizeof(char)*10);
You have to allocate the memory for each pointer.
address[i]=malloc(strlen(buffer)+1);
Or else, you can use strdup function which will allocate the memory for given
string length.
address[i]=strdup(buffer);
The strdup() function returns a pointer to a new string which is a duplicate of the string s. Memory
for the new string is obtained with malloc(3), and can be freed with free(3).
addresses is a pointer to pointer so you need to allocate memory for your pointers first and later allocate memory to each pointers individually as shown below.
In 2D space if addresses is a pointer to a pointer then addresses[i] is a pointer.So allocate memory for it before writing to this location.
char** addresses;
addresses = malloc(sizeof(char*)*10);// Now you 10 character pointers
int i = 0;
while(fgets(buffer, sizeof(buffer), stdin) != NULL)
{
size_t n = strlen(buffer);
if(n>0 && buffer[n-1] == '\n')
buffer[n-1] = '\0';
if(i>=10)
break;
addresses[i] = malloc(strlen(buffer)+1);//Allocate memory to the pointer before writing to it
strcpy(addresses[i],buffer);
i++;
}
PS: fgets() comes with a newline character so I have added a check to replace a newline character with a null.
To quickly address the errors I see here:
You're dereferencing addresses (eg. *addresses or addresses[0]) without ensuring that addresses points somewhere valid. You need to assign to addresses before you dereference.
The type of *addresses[i] in strcpy(*addresses[i],buffer) is char, where it is expected that it be char *. This is what your compiler is complaining about. I suspect that you meant strcpy(addresses[i], buffer).
Even if you're to run this code in an embedded environment, your requirements seem simple enough that you shouldn't need malloc. In fact, introducing malloc complicates things... I tend avoid it unless absolutely necessary. Use automatic storage duration, instead. It'll make life easier, because you won't have as many error situations to handle (though as it is you aren't handling them anyway)...
#define nelem(array) (sizeof array / sizeof *array) /* number of elements in array */
int main(void)
{
char address[10][351] = { 0 };
size_t size = 0;
while (size < nelem(address) && fgets(address + size, sizeof *address, stdin))
{
address[size][strcspn(address[size], "\n")] = '\0';
size++;
}
}
Note that 10 and 351 only appear once here... Feel free to adjust them as you feel fit, within reason. If you can multiply them into the megabytes region, you might want to consider a different data structure depending on what you intend to do with this.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Segmentation Fault - C
#include<stdio.h>
#include<string.h>
int main()
{
char *p;
printf("enter some thing:");
gets(p);
printf("you have typed:%s\n",p);
}
Why doesn't this program work?
i can't use pointer as a string.
Output is:
enter some thing:raihan
Segmentation fault (core dumped)
I get this error every time when I use a char pointer.
How can I solve this problem?
I am using code-blocks on Linux mint13 KDE.
You have not allocated memory. You just declared a pointer, p, but didn't make it point at anything. That explains the segmentation fault. You will need to allocate memory for your buffer.
What's more, gets does not allow you to specify how big the buffer is. So you are at risk of running over the end of the buffer. So use fgets instead.
int main(void)
{
char buffer[1024];//allocates a buffer to receive the input
printf("enter some thing: ");
fgets(buffer, sizeof(buffer), stdin);
printf("you have typed: %s\n", buffer);
return 0;
}
I also corrected your declaration of main and made sure that it returns a value.
You haven't allocated any memory for p. Also, use fgets instead of gets which may overflow the input buffer.
char *p;
printf("enter some thing:");
gets(p);
Wrong. Gets() tries to fill in the array pointed to by the supplied pointer - and it segfaults, because that pointer hasn't been initialized, so it might (and does) point to some garbage/invalid memory location. Use
char p[256];
or something like this instead - you still have to worry about a buffer overflow in if the user enters a string longer than 255 characters. You can solve that one using
fgets(p, sizeof(p), stdin);
Your pointer is declared but you have not initialised it and so its value will be some arbitrary memory location that you may not have access to write to. Thus anytime you read or write to this you run the risk of segfault. Allocate some heap memory for the pointer using a call to malloc then you wont get segfaults when writing to it.
You have just defined a pointer - no memory for the characters have been allocated!
Use either an array or malloc.
A pointer is just a memory address. It says "you have some data here". But it doesn't actually reserve that data.
In your case the problem was two-fold. The pointer didn't point to valid memory and you never even set it to anything (so it pointed to somewhere random).
You can fix this in different ways. The easiest is to just use an array (it's sort of implicitly a pointer):
char something[100];
printf("enter some thing:");
gets(something);
That gives you 100 chars on the stack. You can also point to it if you want, but in this case it's a bit redundant:
char *p = something;
The other way is dynamic allocation, where you ask the operating system at runtime to give you some number of bytes. This way you have to give it back when you're finished using it.
char *something = (char*)malloc( 100 * sizeof(char) ); // Ask for 100 chars
printf("enter some thing:");
gets(something);
free(something); // Do this when you don't need that memory anymore.
PS: Remember when you have strings, you always need one extra byte than the number of characters you intend to store. That byte is for the string terminator, and the value of it is 0.