This question already has answers here:
why scanf scans a null value
(2 answers)
Closed 8 years ago.
I'm sure there just a silly mistake here, however, I can't figure it out.
This is part of my code:
char *moving;
scanf("%s", moving);
When I compile it with gcc, it says the following:
newmatrix.c:38:7: warning: ‘moving’ is used uninitialized in this function [-Wuninitialized]
Line 38 is the scanf
How do I fix this?
Thanks
You can allocate memory before you call scanf(). For example:
char moving[256];
if (scanf("%255s", moving) != 1)
…oops — presumably EOF…
You could use malloc() instead of a simple array, but then you have to remember to free the allocated memory. OTOH, if you want to return the data from the function where it is read, it may well be more convenient to use malloc(), but consider passing a pointer to the space (and its size?) to the function.
Or you can have scanf() do the memory allocation for you (check the manual page for scanf() carefully — read it weekly until you've memorized (enough of) it):
char *moving;
if (scanf("%255ms", &moving) != 1)
…oops — probably EOF, but perhaps OOM (out of memory)…
…use moving…
free(moving);
Yes, this is one of the lesser-known options in POSIX-standard scanf(); it is not a part of Standard C.
Allocate memory for moving before using it. Use malloc().
moving is pointer of char type. Before storing the string in moving, you need to allocate memory for it.
char *moving;
moving = malloc(100);
scanf("%s", moving);
OR
Simply change char *moving to char moving[256].
Also instead of scanf() use fgets().
allocate memory to the pointer before using it
char *moving;
moving = malloc(100*sizeof(char));
scanf("%s", moving);
Related
#include <stdio.h>
int main ()
{
char str[40];
printf("Enter a string : \n");
gets(str);
printf("You entered: %s\n", str);
return 0;
};
in above code, if replace str to a pointer, char *str. Then NULL is out. Suppose gets defined by char *gets(char *str), it should use a pointer instead of array. All examples I saw are array not pointers. Thanks.
function gets() is depracted your libc/compiler might ignore it. try use fgets() instead.
#include <stdio.h>
int main ()
{
char str[40];
printf("Enter a string : \n");
if (fgets(str, sizeof(str), stdin) != NULL)
{
printf("You entered: %s\n", str);
}
return 0;
};
also if you want to don't use stack you need to give pointer that points allocated space. in code str also can be char *str = malloc(40); then change sizeof(str) to 40 since str is no longer stack.
Really interesting question, I have been asked this question a lot!
you should have a bit background of pointers and memory to understand what is happening.
first let's have a brief review about pointers and memory:
our computer have some memory and we can use it in programming, anything that we store (in runtime) for example an int, array of doubles, some complex struct and strings(that they are array of characters) should be somewhere in memory.
pointers contain address of somewhere in memory, some of them know about that memory (how to read/write value) some of them don't.
there is a special value for pointers (NULL) that means nowhere, if pointer is pointing to NULL, that pointer is pointing not nowhere (obviously nowhere is not a valid address in memory)
array is specific type of pointer, a const pointer that is pointing to already allocated memory in stack.
and about gets function: let's think we want to re-implement such function (namely my_gets) , how we suppose to do that? how to return a string (array of characters)?
these are options (as far as i know):
creating a local array in our function and fill it. then we should return it? no we cant! because that array is in stack of our function and after ending the function, our function data including this array will be popped automatically (handled by compiler).
although nobody forbid us from returning that array, but that would cause dangling pointer problem.
allocating some space rather than stack (heap) and fill that. this is perfectly fine and there is methods and do this! for example readline (not in ansi c, you can find it here) will do this. the drawback of this method is that you should take care of that memory and free it later, it also may be not to optimum way and you may should copy that string to your already allocated memory
the last way (and way that gets use) is getting a pointer that is already pointing to a valid memory and fill that memory. you already know that gets want a pointer as input, I add that, that pointer should point to a valid and accessible memory that gets can fill it. if pointer is pointing to NULL (or maybe uninitialized and pointing to some where random) gets will fail writing and cause undefined behavior (segmentation fault for example)
some final points:
array solution work because array name is pointer that pointing to valid memory (array in stack) so it's OK and easy to understand.
If we don't want to use array, we can point our pointer to a valid memory, we need to use malloc/calloc to allocate a block of memory. see this:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int size = 40 * sizeof(char);
char* p = malloc(size);
printf("Enter a string : \n");
if (fgets(p, size, stdin) != NULL) {
printf("You entered: %s\n", p);
}
free(p);
return 0;
}
gets is not secure because it doesn't care how much memory we have, it writes until and string ends and it may cause buffer overflow, better option (as people said) is fgets because it care memory size and will not exceed that. but my answer doesn't care it's fgets or gets.
This question already has answers here:
segmentation fault using scanf [duplicate]
(2 answers)
Closed 7 years ago.
I'm trying to input a word in the form of a char * in C
Such as :
char *inputText;
scanf("%s",inputText);
printf("This is your string %s",inputText);
I have tried with using
scanf("%s",&inputText);
As well
Each time I either get a compile error or Segmentation fault when I run it
"format '%s' expects type 'char *' but argument 2 has type 'char **'
I'm not sure if I'm missing something really simple but It's quite confusing.
My code depends on using char *
If theres a way to convert an easier input method into char * then can you show me that method?
You haven't initialized inputText so it's pointing to some random memory which you probably don't even own. Asking scanf write to that memory location results in undefined behavior.
You need to allocate memory for the pointer to point to:
char *inputText = malloc(amount_of_bytes_to_allocate);
Now inputText points to the allocated memory, and scanf can happily write to that memory location without a segfault. Remember that you must free(inputText) when you're done using the allocated memory.
But preferably, you wouldn't use dynamic memory (malloc) in this case since you can do just fine with automatic memory: just declare inputText as an array instead of a pointer:
char inputText[size_of_array];
Remember that your size_of_array (or amount_of_bytes_to_allocate) must be large enough to hold the entire string that scanf is going to write into the array, including the terminating null character. Otherwise you'll have undefined behavior again.
First, as a general precaution, it's a good idea to initialize new pointers to NULL so as to ensure they aren't pointing to memory that your program isn't allowed to access.
I would use getline() as an alternative to scanf() especially if the size of your input can vary. It allocates a properly-sized buffer for you, so you don't need to worry about entering too many characters.
char *inputText = NULL;
int inputSize;
if (getline(&inputText, &inputSize, stdin) >= 0)
printf("This is your string: %s\n", inputText);
else
printf("Error\n");
You still need to free the memory allocated to inputText yourself, so don't forget to do that and set it to NULL once you're done with it.
If I am correct, doing something like:
char *line;
Then I must allocate some memory and assign it to line, is that right? If I am right, the question is the following:
In a line like
while (fscanf(fp,"%[^\n]", line) == 1) { ... }
without assigning any memory to line I am still getting the correct lines and the correct strlen counts on such lines.
So, does fscanf assign that memory for me and it also places the '\0'?
I saw no mention about these 2 things on the spec for fscanf.
The POSIX scanf() family of functions will allocate memory if you use the m (a on some older pre-POSIX versions) format modifier. Note: when fscanf allocates, it expects a char ** pointer. (see man scanf) E.g.:
while(fscanf(fp,"%m[^\n]", &line) == 1) { ... }
I would also suggest consuming the newline with "%m[^\n]%*c". I agree with the other answers that suggest using line-oriented input instead of fscanf. (e.g. getline -- see: Basile's answer)
See the C FAQ:
Q: I just tried the code
char *p;
strcpy(p, "abc");
and it worked. How? Why didn't it crash?
A: You got lucky, I guess. The memory randomly pointed to by the uninitialized pointer p happened to be writable by you, and apparently was not already in use for anything vital. See also question 11.35.
And, here is a longer explanation, and another longer explanation.
To read entire lines with a recent C library on POSIX systems, you should use getline(3). It allocates (and reallocates) the buffer holding the line as needed. See the example on the man page.
If you have a non-POSIX system without getline you might use fgets(3) but then you have to take the pain to allocate the line itself, test that you did not read a full newline terminated line, and repeat. Then you need to pre-allocate some line buffer (using e.g. malloc) before calling fgets (and you might realloc it if a line does not fit and call fgets again). Something like:
//// UNTESTED CODE
size_t linsiz=64;
char* linbuf= malloc(linsiz);
if (!linbuf) { perror("malloc"); exit(EXIT_FAILURE); };
memset(linbuf, 0, sizeof(linbuf));
bool gotentireline= false;
char* linptr= linbuf;
do {
if (!fgets(linptr, linbuf+linsiz-linptr-1, stdin))
break;
if (strchr(linptr, '\n'))
gotentireline= true;
else {
size_t newlinsiz= 3*linsiz/2+16;
char* newlinbuf= malloc(newlinsiz);
int oldlen= strlen(linbuf);
if (!newlinbuf) { perror("malloc"); exit(EXIT_FAILURE); };
memset (newlinbuf, 0, newlinsiz); // might be not needed
strncpy(newlinbuf, linbuf, linsiz);
free (linbuf);
linbuf= newlinbuf;
linsiz= newlinsiz;
linptr= newlinbuf+oldlen;
);
} while(!gotentireline);
/// here, use the linbuf, and free it later
A general rule would be to always initialize pointers (e.g. declare char *line=NULL; in your case), and always test for failure of malloc, calloc, realloc). Also, compile with all warnings and debug info (gcc -Wall -Wextra -g). It could have give a useful warning to you.
BTW, I love to clear every dynamically allocated memory, even when it is not very useful (because the behavior is then more deterministic, making programs easier to debug).
Some systems also have valgrind to help detecting memory leaks, buffer overflows, etc..
line is uninitialized and doen't point to any valid memory location so what you see is undefined behavior.
You need to allocate memory for your pointer before writing something to it.
PS: If you are trying to read the whole line then fgets() is a better option.Note that fgets() comes with a newline character .
Nope. You're just getting lucky undefined behavior. It's completely possible that an hour from now, the program will segfault instead of run as expected or that a different compiler or even the same compiler on a different machine will produce a program that behaves differently. You can't expect things that aren't specified to happen, and if you do, you can't expect it to be any form of reliable.
I've got an interface function in my application:
void addShopToList(Tshp **shpHead){
char* name;
Tshp *newshp = NULL;
system("cls");
printf("Name: ");
scanf("%s[^\n]", &name);
fflush(stdin);
newshp = addShp(shpHead,name,NULL);
if(prompt("Do you want to add some products?")){
addProductMenu(&newshp);
}
}
and I get:
Run-Time Check Failure #2 - Stack around the variable 'name' was corrupted.
When I trigger those functions separately (I mean like addShp() -> it's just adding a new shop to the list), it works properly.
I have no idea how to fix it :/.
name is uninitialized, so then when you try to take the address of the uninitialized pointer:
scanf("%s[^\n]", &name);
it pukes on you. So two points:
1) char *name = malloc(100); // now it's initialized to something, don't forget to free it later
2) scanf("%s[^\n]", name); // shouldn't use the & for a string in scanf
and a third bonus point:
3) fflush(stdin); don't do that. Flushing stdin is undefined behavior according to the C11 standard §7.21.5.2 part 2:
Ifstream points to an output stream ... the fflush function causes any unwritten data for that stream ... to be written to the file; otherwise, the behavior is undefined.
On some systems, Linux being one as you can see in the man page for fflush(), there's a defined behavior but it's system dependent so your code may not be portable.
You have two problems:
The first is that you are passing the address of the pointer to the string to scanf - not the address of the string. The scanf call doesn't know that, so it starts reading data in to the address you passed it, overwriting the memory location where name is stored, and the memory after it (newshp) and so on... by the time the scanf is done, who knows what's left? You can fix that easily by removing the & before name in the scanf call.
But then you stumble onto the other, important, issue: currently name is a pointer that points to who-knows-where - it's uninitialized. Wherever it points, it's not your memory. The fixed call to scanf will overwrite that memory - which you don't own. And then what happens?
The solution to that is to initialize name to point to memory that you allocate. You can do that using something like malloc to allocate a chunk of memory, or, alternatively, you can allocate the space on the stack thusly:
// allocate space for 99 characters (plus 1 space for the null-terminator
// and initialize the memory to all null characters.
char name[100] = { 0 };
Sidenote: you should really try to understand the subtle difference between what happens when you pass &name instead of name to scanf. It will be a very important pedagogical exercise and help you gain a much better understanding of pointers and how your code is translated into something the machine understands.
Finally, you shouldn't call fflush(stdin) as that results in undefined behavior. And that's a bad thing. What do you believe that function call would achieve anyways?
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.