How to read and write contents from char array to a file? - c

this program accepts user input and saved to a char array. Then creates a file and put those texts to the new file. Problem is, it can only copy the part before space.
Current Output : "how to read" --> "how"
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argv, char *argc[]){
int fd;
char buffer[100];
printf("Type your text : ");
scanf("%s",&buffer);
fd=open("menew.txt",O_CREAT|O_WRONLY|O_EXCL,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
if(fd<0){
printf("file already exist!\n");
}else printf("file created!\n");
fd=write(fd,buffer,20);
if(fd<0){
printf("error on writing...\n");
}else printf("successfully written!\n");
close(fd);
return 0;
}

The problem isn't with the writing, it's with the reading -- the scanf %s conversion skips any leading whitespace, then reads and converts up to (but not including) the next white space.
You probably want to use something like fgets or the %[^\n] conversion with scanf.
Edit: I should probably also mention that when/if you use the scanset conversion (%[^\n]), you should specify the length of buffer you're reading into.
As far as the &buffer in scanf("%s", &buffer); being an error, technically it does give undefined behavior, but in reality I don't know of any implementation where it makes a real difference.
In this case, buffer was defined as an array, not a pointer. The name of an array "decays" to a pointer under many circumstances, but not when used as the operand of the address-of operator (unary &). As such, buffer and &buffer yield exactly the same result, the address of the beginning of the array.
There is still a difference though. When you use just buffer, you get a value with the type pointer to char (given that buffer is an array of char). When you use &buffer, you get a pointer of the type pointer to array of MAXLEN char.
Now, when you pass a value to scanf (a variadic function), you get undefined behavior when/if the type of the value you pass does not match the type expected by the conversion you specified. In reality, with every C compiler I've ever heard of, it'll work fine though, because the same address will be passed either way. In theory (but only in theory, AFAIK) a compiler could use some sort of "fat pointer" that included type information along with the address, so scanf would be able to detect the type mismatch. In reality, I don't know of any compiler that does anything very similar, so you won't see any difference between using just buffer and using &buffer in this case.
In other circumstances, however, the difference can be detectable. Addition and subtraction on pointers is based on the type, so (for example) array+1 and &array + 1 will yield different results:
#include <stdio.h>
int main() {
char array[10];
printf("%p %p %p\n", array, array+1, &array+1);
return 0;
}
This will print three numbers. The first number will be some arbitrary number, typically in hexadecimal. The second will be one greater than the first, and the second will be 10 greater than the first (because I defined it to be an array of 10 characters...)

At least one error:
scanf("%s",&buffer);
should be:
scanf("%s", buffer);
You were taking the address of a pointer. Probably not what you had intended.
Edit:
scanf also has the limitation described by Jerry Coffin.

Finally I found the solution!!!
Use gets(buffer); instant of scanf("%s",&buffer);

Related

Why do I need "&" in printf when I want to print a pointer

So I wrote this code where I scan 2 strings. One is declared as an array and one as a pointer.
Now to my question: Why do I need for printing text2 in the printf-statment the "&" before Text2 and when I print Text1 not?
I thought if I put "&" in printf before the variable it pirnts the memory address. I this case not, it prints the string.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char Text1[45];
char *Text2;
scanf("%s" , &Text1);
printf("Text1: %s\n", Text1);
scanf("%s" , &Text2);
printf("Text2: %s\n", &Text2);
return 0;
}
char Text1[45] is an array of characters. The compiler will allocate 45 bites in a program memory for use by the program. The value of the bytes is not known at the moment. So, scanf("%s" , Text1) will put input chars into this memory, assuming that there are less than 44 of them, or it will override the program stack and possibly crash. To prevent from this issue, you should use something like %44s.
There is no need to use & in this case. It does not do much with the array declared in such a way. Therefore you do not need it in printf("%s\n", Text1). But you can use it if you wish.
char *Text2 declares a pointer variable. It means that the compiler allocates enough space to contain the pointer value. The value of the pointer is not defined at the moment, so it does not point anywhere. If you plan to use it with characters, you need to allocate space for them or assign the space in a different way. For example, Text2 = malloc(45) will allocate 45 bytes for use and set a pointer to those bytes. Or you can do Text2 = Text1, assigning address of the first byte of the Text1 array as a pointer. This way the Text1 array will be used as a byte storage.
As a result, scanf("%s", Text2) will use the pointer to access bytes, either allocated by malloc or in the Text1. Now you need to printf("%s\n", Text2).
You should not use & on Text2. It will return an address of the pointer variable and not the address of the array of bytes. You need the latter. So print with &Text2 will return trash and could cause a crash.
BTW, if you used malloc it is a good idea to free the memory which was allocated if it is not needed any longer: free(Text2).
Let's get rid of the part dealing with Text1 for the moment, and focus solely on Text2. That leaves us with something like this:
char *Text2;
scanf("%s" , &Text2);
printf("Text2: %s\n", &Text2);
You've declared Text2 as a pointer, but you haven't initialized it to point to any available space. Then you pass the address of that pointer to scanf, and match it up with a format that tells scanf to read a string, and deposit it at the specified location, so instead of using the pointer as a pointer, scanf will try to use it as if it were an array of char.
To make this work sanely, we want to use the pointer as a pointer, and have it point at some available memory--and we want to tell scanf the size of that memory, so the user can't enter more data than we've provided space to store.
#define MAXSIZE 128
char *Text2 = malloc(MAXSIZE);
scanf("%127s", Text2); // note lack of ampersand here
printf("%s\n", Text2); // Now we don't need an ampersand here either.
Your program is exhibiting undefined behavior and although it is mostly pointless to speculate about undefined behavior, it may be interesting to consider the following:
$ cat a.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(void)
{
char text1[128] = {0};
char *text2;
char text3[128] = {0};
scanf("%44s" , &text2); /* Undefined behavior */
printf("Text1: %s\n", text1);
printf("Text3: %s\n", text3);
return 0;
}
$ echo abcdefghijklmnopHelloWorld | ./a.out
bash: child setpgid (96724 to 96716): Operation not permitted
Text1:
Text3: HelloWorld
The behavior shown above indicates that on my platform, the text that is being written to &text2 is overwriting the value of text3 (this is a stack overflow). This is simply because (on my platform), the variables text2 and text3 are placed 16 bytes apart in the stack when the program executes. To reiterate, the behavior of the code is undefined and the actual performance will vary greatly depending on where it is run, but despite mythical warnings about demons flying out of your nose it is not likely to cause any harm experimenting with it.

Convert double to char* in C

How can I convert double to char*.
#include <stdio.h>
int main() {
char * buf;
double number = 3.123;
sprintf(buf,"%f",number);
printf("%s",buf);
return 0;
}
This method is does not want to work and I cannot know why.
char* buf declares buf as a character pointer, but does not actually allocate any memory for it. You should declare buf as an array to allocate memory:
char buf[128];
double number = 3.123;
sprintf(buf, "%f", number);
What you probably want is a floating-point to string conversion. What you need is not a char*, but rather an array. The difference is that an array allocates some space for the string, while a pointer is supposed to point to an already existing string, but there is no such string in your code.
Because of this, your code is producing Undefined Behavior (or UB for short), because sprintf() is attempting to write at the address that the buf pointer references. The pointer was not assigned to point to anything, so it is an uninitialized (wild) pointer. This pointer probably contains a random non-sense value and sprintf() is trying to write to it - it won't work, or even worse, will appear to work until you find a problem in a totally different part of the code.
Here is how you should do it:
#include <stdio.h>
int main(void)
{
char buf[100];
double number = 3.123;
sprintf(buf, "%f", number);
printf("%s", buf);
}
First we declare a character array. It can be any length, but for simplicity I chose 100. We can then use this array in a similar way, by writing to it using sprintf().
Now, there may be another problem. It won't show up in this small piece of code, but if you use sprintf() a lot you will notice a lot of bugs if you don't pay attention to the length of the array. The array has only 100 characters, but sprintf() doesn't know that! The function will simply attempt to write past the end of the array, a bug which is called a buffer overflow, yet another case of UB, and also a very common exploit for malicious attacks.
To ease the programmer's life, C has another function that is safer, snprintf(), which works pretty much the same but takes an extra parameter, the maximum length of the array. Here is how it works:
#include <stdio.h>
int main(void)
{
char buf[100];
double number = 3.123;
snprintf(buf, 100, "%f", number);
printf("%s", buf);
}
Even if we tried to write more than 100 characters to the buffer, the function would only write 100 (actually, 99 and a null terminator), and will discard the rest of the contents. This means that, if you pass the correct value for the length of the array, a buffer overflow won't occur.

How do you assign a string in C

Printing the initials (first character) of the string held in the variable 'fn' and the variable 'ln'
#include <stdio.h>
#include <cs50.h>
int main(void)
{
string fn, ln, initials;
fn = get_string("\nFirst Name: ");
ln = get_string("Last Name: ");
initials = 'fn[0]', 'ln[0]';
printf("%s", initials)
}
Read more about C. In particular, read some good C programming book, and some C reference site and read the C11 standard n1570. Notice that cs50.h is not a standard C header (and I never encountered it).
The string type does not exist. So your example don't compile and is not valid C code.
An important (and difficult) notion in C is : undefined behavior (UB). I won't explain what is it here, but see this, read much more about UB, and be really afraid of UB.
Even if you (wrongly) add something like
typedef char* string;
(and your cs50.h might do that) you need to understand that:
not every pointer is valid, and some pointers may contain an invalid address (such as NULL, or most random addresses; in particular an uninitialized pointer variable often has an invalid pointer). Be aware that in your virtual address space most addresses are invalid. Dereferencing an invalid pointer is UB (often, but not always, giving a segmentation fault).
even when a pointer to char is valid, it could point to something which is not a string (e.g. some sequence of bytes which is not NUL terminated). Passing such a pointer (to a non-string data) to string related functions -e.g. strlen or printf with %s is UB.
A string is a sequence of bytes, with additional conventions: at the very least it should be NUL terminated and you generally want it to be a valid string for your system. For example, my Linux is using UTF-8 (in 2017 UTF-8 is used everywhere) so in practice only valid UTF-8 strings can be correctly displayed in my terminals.
Arrays are decayed into pointers (read more to understand what that means, it is tricky). So in several occasions you might declare an array variable (a buffer)
char buf[50];
then fill it, perhaps using strcpy like
strcpy(buf, "abc");
or using snprintf like
int xx = something();
snprintf(buf, sizeof(buf), "x%d", xx);
and latter you can use as a "string", e.g.
printf("buf is: %s\n", buf);
In some cases (but not always!), you might even do some array accesses like
char c=buf[4];
printf("c is %c\n", c);
or pointer arithmetic like
printf("buf+8 is %s\n", buf+8);
BTW, since stdio is buffered, I recommend ending your printf control format strings with \n or using fflush.
Beware and be very careful about buffer overflows. It is another common cause of UB.
You might want to declare
char initials[8];
and fill that memory zone to become a proper string:
initials[0] = fn[0];
initials[1] = ln[0];
initials[2] = (char)0;
the last assignment (to initials[2]) is putting the NUL terminating byte and makes that initials buffer a proper string. Then you could output it using printf or fputs
fputs(initials, stdout);
and you'll better output a newline with
putchar('\n');
(or you might just do puts(initials); ....)
Please compile with all warnings and debug info, so gcc -Wall -Wextra -g with GCC. Improve your code to get no warnings. Learn how to use your compiler and your debugger gdb. Use gdb to run your program step by step and query its state. Take time to read the documentation of every standard function that you are using (e.g. strcpy, printf, scanf, fgets) even if at first you don't understand all of it.
char initials[]={ fn[0], ln[0], '\0'};
This will form the char array and you can print it with
printf("%s", initials) //This is a string - null terminated character array.
There is no concept of string datatype in c . We simulate it using null terminated character array.
If you don't put the \0 in the end, it won't be a null terminated char array and if you want to print it you will have to use indexing in the array to determine the individual characters. (You can't use printf or other standard functions).
int s[]={'h','i'} // not null terminated
//But you can work with this, iterating over the elements.
for(size_t i=0; i< sizeof s; i++)
printf("%c",s[i]);
To explain further there is no string datatype in C. So what you can do is you simulate it using char [] and that is sufficient for that work.
For example you have to do this to get a string
char fn[MAXLEN}, ln[MAXLEN];
Reading an input can be like :
if(!fgets(fn, MAXLEN,stdin) ){
fprintf(stderr,"Error in input");
}
Do similarly for the second char array.
And then you do form the initializationg of array initials.
char initials[]={fn[0],ln[0],'\0'}
The benefit of the null terminated char array is that you can pass it to the fucntions which works over char* and get a correct result. Like strcmp() or strcpy().
Also there are lots of ways to get input from stdin and it is better always to check the return type of the standard functions that you use.
Standard don't restrict us that all the char arrays must be null terminated. But if we dont do that way then it's hardly useful in common cases. Like my example above. That array i shown earlier (without the null terminator) can't be passed to strlen() or strcpy() etc.
Also knowingly or unknowingly you have used somnething interesting The comma operator
Suppose you write a statememnt like this
char initialChar = fn[0] , ln[0]; //This is error
char initialChar = (fn[0] , ln[0]); // This is correct and the result will be `ln[0]`
, operator works that first it tries to evaluate the first expression fn[0] and then moves to the second ln[0] and that value is returned as a value of the whole expression that is assigned to initialChar.
You can check these helpful links to get you started
Beginner's Guide Away from scanf()
How to debug small programs

scanf() works despite 0-length buffer and compiler warning. What is going on?

My compiler (clang) shows this message:
11:17:warning: format specifies type 'char *' but the argument has
type 'char (*)[0]' [-Wformat]
scanf("%s", &name);
~~ ^~~~~
1 warning generated.
from the following code (greetings program):
/*
* Program: gretting2.c
* Utility: Display a greeting with your name.
* Author: Adrián Garro.
*/
#include <stdio.h>
int main () {
char name[0];
printf("-------------------\n");
printf("Write your name: \n");
printf("-------------------\n");
scanf("%s", &name);
printf("------------------------------------\n");
printf("Hello %s, nice to meet you\n",name);
printf("------------------------------------\n");
}
What is actually going on, and how can I fix it?
In order to understand this, you have to understand what scanf is doing. scanf in this case is reading a string from stdin, and placing it into a buffer that you give it. It does not allocate that space for you, or detect overflow. You need to allocate sufficient space for your string. As it stands now, you are allocating zero space for your string, so everything is an overflow. This is a major bug.
Say instead of char[0], you did char[40], as another user suggests.What if the user of your program writes more than 40 characters? This results in undefined behavior. Essentially, it will write to memory you don't want it to write to. It might cause a segfault, it might result in crucial memory getting overwritten, or it might happen to work. This is a weakness of scanf. Look into fgets. You tell it the size of your buffer, and input will be truncated to fit.
Of course, that has nothing to do with your warning. You're getting a warning because referring to the name of an array is the same as referring to a pointer to its first element, i.e. name <==> &(name[0]). Taking a pointer to this is like taking a pointer to a pointer, i.e. &name <==> &&(name[0]). Since scanf is looking for an argument of type char*, and it's getting a pointer to that, the type checker complains.
Your code exhibits "undefined behavior." This means anything could happen. Anything.
You are passing a zero-length array to scanf(). Also, you are not passing the array length in the format string. This results in a buffer overflow vulnerability (always, in the case of a zero-length target array).
You need something like this:
char name[51];
scanf("%50s", name);
Note the %50s now specifies the size of the target array (less one, to leave room for the null terminator!), which avoids buffer overflow. You still need to check the return value of scanf(), and whether the input name is actually too long (you wouldn't want to truncate the user's input without telling them).
If you're on Linux, check out the tool called valgrind. It is a runtime memory error detector (among other things), and can sometimes catch errors like this for you (and much less obvious ones, which is the main point). It's indispensable for many C programmers.
Just change this:
scanf("%s", &name);
to:
scanf("%39s", name);
and this:
char name[0];
to:
char name[40];
Also to you have to end it with a '\0' with:
name[39] = '\0';
Depending on how robust you want this to be you will want to reconsider the approach. I guess the first thing is whether you understand the type you are using when declaring char name[ 0 ]. this is a 'zero-sized' array of byte-sized characters. This is a confusing thing and it wouldn't surprise me if its behaviour differs across compilers...
The actual warning being complained by the compiler is that the type doesn't match. If you take the address of the first character in the array you can get rid of that (i.e. use &( name[ 0 ] ) in the scanf call). The address of name is its location on the stack - it just so happens that the array implementation uses that same location to store the array data, and name is treated differently by the compiler when used on its own so that the address of an array is the same as the address of its first element...
Using char name[ 0 ] leaves you open to causing memory corruption because there is nowhere for the string to be read, and implementation details may just luck out and allow this to work. One simple way to fix this is to replace 0 with a meaningful number which you take to the maximum length of the input string. Say 32 so that you have char name[ 32 ] instead... however this doesn't handle the case of an even longer string.
Since we live in a world of lots of memory and large stacks you can probably do char name[ 4096 ] and use 4KB of memory for the buffer and that will be absolutely fine for real world usage.
Now... if you want to be a little anal and handle pathological cases, like a user leaning on some keys whilst asleep for hours before pressing enter and adding some enormous 8000 character long string there are a few ways to handle that too with 'dynamic memory allocation', but that might be a bit beyond the scope of this answer.
As an aside, from what I understand char foo[ 0 ] is intentionally valid - it may have originated as a hack and has a confusing type, but is not uncommonly relied on for an old trick to create variable sized structs as described in this page from the GCC online docs
char name[0]; ---> char name[100];
/* You need to allocate some memory to store the name */
2.scanf("%s", &name);----> scanf("%s", name);
/* scanf takes char* as an argument so you need to pass string name only. */
i don't think that scanf("%(length - 1)s", name); is needed.
Because %s is used to reads a string. This will stop on the first whitespace character reached, or at the specified field width (e.g. "%39s"), whichever comes first.
except these don't tend to be used as often. You, of course, may use them as often as you wish!
/
*
* Program: gretting2.c
* Utility: Display a greeting with your name.
* Author: Adrián Garro.
*/
#include <stdio.h>
int main () {
char name[100];
printf("-------------------\n");
printf("Write your name: \n");
printf("-------------------\n");
scanf("%s", name);
printf("------------------------------------\n");
printf("Hello %s, nice to meet you\n",name);
printf("------------------------------------\n");
}
Because the correct way is
scanf("%s", name);
/* ^ no ampersand
and what is
char name[0];
you should specify a non-zero length and use it for scanf length specifier
scanf("%(length - 1)s", name);
/* ^ sunstitite with the value */
there were several problems with the OPs posted code
the following fixes most of them
I includd comments to indicate where the problems are
int main ()
{
//char name[0]; // this did not allow any room for the name
char name[100] = {'\0'}; // declare a 100 byte buffer and init to all '\0'
printf("-------------------\n");
printf("Write your name:, max 99 char \n"); // 99 allows room for nul termination byte
printf("-------------------\n");
//scanf("%s", &name); // this has no limit on length of input string so can overrun buffer
if( 1 == scanf("%99s", name) ) // 1) always check returned value from I/O functions
// 2) no '&' before 'name' because
// arrays degrade to pointer to array when variable
// name is used
// 3) placed max size limit on format conversion string
// so input buffer 'name' cannot be overflowed
{ // then scanf failed
perror( "scanf failed for name" );
return(-1); // indicate error
}
// implied else, scanf successful
printf("------------------------------------\n");
printf("Hello %s, nice to meet you\n",name);
printf("------------------------------------\n");
return(0); // indicate success
} // end function: main
You are reading a "string", thus the correct way is:
scanf("%s", name);
Why does the compiler complain? When you provide an argument in scanf, you provide the memory location of the variable. For example:
int x;
scanf("%d", &x);
&x is int *, i.e., a pointer to an integer, so x will get the correct value.
When you read a string, you're actually reading many char variables together. To store them, you need a char * array; well, name is char * on its own, so no need to write &name. The latter is char **, i.e., a 2-dimensional array of char.
By the way, you also need to allocate space for the characters to read. Thus, you have to write char name[20] (or any other number). You also need to provide a return 0; in your int main().

The compiler shows a warning from this code [duplicate]

My compiler (clang) shows this message:
11:17:warning: format specifies type 'char *' but the argument has
type 'char (*)[0]' [-Wformat]
scanf("%s", &name);
~~ ^~~~~
1 warning generated.
from the following code (greetings program):
/*
* Program: gretting2.c
* Utility: Display a greeting with your name.
* Author: Adrián Garro.
*/
#include <stdio.h>
int main () {
char name[0];
printf("-------------------\n");
printf("Write your name: \n");
printf("-------------------\n");
scanf("%s", &name);
printf("------------------------------------\n");
printf("Hello %s, nice to meet you\n",name);
printf("------------------------------------\n");
}
What is actually going on, and how can I fix it?
In order to understand this, you have to understand what scanf is doing. scanf in this case is reading a string from stdin, and placing it into a buffer that you give it. It does not allocate that space for you, or detect overflow. You need to allocate sufficient space for your string. As it stands now, you are allocating zero space for your string, so everything is an overflow. This is a major bug.
Say instead of char[0], you did char[40], as another user suggests.What if the user of your program writes more than 40 characters? This results in undefined behavior. Essentially, it will write to memory you don't want it to write to. It might cause a segfault, it might result in crucial memory getting overwritten, or it might happen to work. This is a weakness of scanf. Look into fgets. You tell it the size of your buffer, and input will be truncated to fit.
Of course, that has nothing to do with your warning. You're getting a warning because referring to the name of an array is the same as referring to a pointer to its first element, i.e. name <==> &(name[0]). Taking a pointer to this is like taking a pointer to a pointer, i.e. &name <==> &&(name[0]). Since scanf is looking for an argument of type char*, and it's getting a pointer to that, the type checker complains.
Your code exhibits "undefined behavior." This means anything could happen. Anything.
You are passing a zero-length array to scanf(). Also, you are not passing the array length in the format string. This results in a buffer overflow vulnerability (always, in the case of a zero-length target array).
You need something like this:
char name[51];
scanf("%50s", name);
Note the %50s now specifies the size of the target array (less one, to leave room for the null terminator!), which avoids buffer overflow. You still need to check the return value of scanf(), and whether the input name is actually too long (you wouldn't want to truncate the user's input without telling them).
If you're on Linux, check out the tool called valgrind. It is a runtime memory error detector (among other things), and can sometimes catch errors like this for you (and much less obvious ones, which is the main point). It's indispensable for many C programmers.
Just change this:
scanf("%s", &name);
to:
scanf("%39s", name);
and this:
char name[0];
to:
char name[40];
Also to you have to end it with a '\0' with:
name[39] = '\0';
Depending on how robust you want this to be you will want to reconsider the approach. I guess the first thing is whether you understand the type you are using when declaring char name[ 0 ]. this is a 'zero-sized' array of byte-sized characters. This is a confusing thing and it wouldn't surprise me if its behaviour differs across compilers...
The actual warning being complained by the compiler is that the type doesn't match. If you take the address of the first character in the array you can get rid of that (i.e. use &( name[ 0 ] ) in the scanf call). The address of name is its location on the stack - it just so happens that the array implementation uses that same location to store the array data, and name is treated differently by the compiler when used on its own so that the address of an array is the same as the address of its first element...
Using char name[ 0 ] leaves you open to causing memory corruption because there is nowhere for the string to be read, and implementation details may just luck out and allow this to work. One simple way to fix this is to replace 0 with a meaningful number which you take to the maximum length of the input string. Say 32 so that you have char name[ 32 ] instead... however this doesn't handle the case of an even longer string.
Since we live in a world of lots of memory and large stacks you can probably do char name[ 4096 ] and use 4KB of memory for the buffer and that will be absolutely fine for real world usage.
Now... if you want to be a little anal and handle pathological cases, like a user leaning on some keys whilst asleep for hours before pressing enter and adding some enormous 8000 character long string there are a few ways to handle that too with 'dynamic memory allocation', but that might be a bit beyond the scope of this answer.
As an aside, from what I understand char foo[ 0 ] is intentionally valid - it may have originated as a hack and has a confusing type, but is not uncommonly relied on for an old trick to create variable sized structs as described in this page from the GCC online docs
char name[0]; ---> char name[100];
/* You need to allocate some memory to store the name */
2.scanf("%s", &name);----> scanf("%s", name);
/* scanf takes char* as an argument so you need to pass string name only. */
i don't think that scanf("%(length - 1)s", name); is needed.
Because %s is used to reads a string. This will stop on the first whitespace character reached, or at the specified field width (e.g. "%39s"), whichever comes first.
except these don't tend to be used as often. You, of course, may use them as often as you wish!
/
*
* Program: gretting2.c
* Utility: Display a greeting with your name.
* Author: Adrián Garro.
*/
#include <stdio.h>
int main () {
char name[100];
printf("-------------------\n");
printf("Write your name: \n");
printf("-------------------\n");
scanf("%s", name);
printf("------------------------------------\n");
printf("Hello %s, nice to meet you\n",name);
printf("------------------------------------\n");
}
Because the correct way is
scanf("%s", name);
/* ^ no ampersand
and what is
char name[0];
you should specify a non-zero length and use it for scanf length specifier
scanf("%(length - 1)s", name);
/* ^ sunstitite with the value */
there were several problems with the OPs posted code
the following fixes most of them
I includd comments to indicate where the problems are
int main ()
{
//char name[0]; // this did not allow any room for the name
char name[100] = {'\0'}; // declare a 100 byte buffer and init to all '\0'
printf("-------------------\n");
printf("Write your name:, max 99 char \n"); // 99 allows room for nul termination byte
printf("-------------------\n");
//scanf("%s", &name); // this has no limit on length of input string so can overrun buffer
if( 1 == scanf("%99s", name) ) // 1) always check returned value from I/O functions
// 2) no '&' before 'name' because
// arrays degrade to pointer to array when variable
// name is used
// 3) placed max size limit on format conversion string
// so input buffer 'name' cannot be overflowed
{ // then scanf failed
perror( "scanf failed for name" );
return(-1); // indicate error
}
// implied else, scanf successful
printf("------------------------------------\n");
printf("Hello %s, nice to meet you\n",name);
printf("------------------------------------\n");
return(0); // indicate success
} // end function: main
You are reading a "string", thus the correct way is:
scanf("%s", name);
Why does the compiler complain? When you provide an argument in scanf, you provide the memory location of the variable. For example:
int x;
scanf("%d", &x);
&x is int *, i.e., a pointer to an integer, so x will get the correct value.
When you read a string, you're actually reading many char variables together. To store them, you need a char * array; well, name is char * on its own, so no need to write &name. The latter is char **, i.e., a 2-dimensional array of char.
By the way, you also need to allocate space for the characters to read. Thus, you have to write char name[20] (or any other number). You also need to provide a return 0; in your int main().

Resources