int readOptions(char *argv[]){
FILE * infile;
char line_buf[BUFSIZ];
int i = 0, j = 0 ;
infile = fopen("options","r");
if(!infile){
fprintf(stderr,"File Read failure\n");
exit(2);
}
while( i < 10 && fgets(line_buf,sizeof(line_buf),infile)!=0){
printf("Line buf : %s",line_buf);
argv[i] = line_buf;
i++;
}
}
int main(){
int j ;
char *options[10];
for(j = 0 ; j< 10 ; j++){
options[j] = malloc(len * sizeof (char));
}
readOptions(options);
for(j=0; j<10 ; j++)
printf("%s %d\n",options[j], j );
}
The problem is that I always see - the program print only the last line read in the file. Where is the mistake ? and am I missing any important pointer concept with this code ?
Every element of argv points to the same line_buf. Use strdup() to create new strings instead (which you will later have to free).
A char* is not a string. It is a pointer. In your loop, you set each char* in your char*[] to point at the beginning of the line_buf array. Thus, each refers to the same data (which, furthermore, is no longer available after returning from the function; you get undefined behaviour at this point and you're just "lucky" - actually very unlucky, because it makes it harder to diagnose the problem - that it seems to "work" as well as it does.)
There is no real string type in C. You must set up separate chunks of memory that will hold the characters, and point at those chunks. If you allocate them dynamically, you will also have to free them. If you want to be able to resize them, or in general handle things of unknown size, that's also on you.
You've written the code to allocate some space, but you don't copy the data into the space - instead, you repoint the pointers at the local buffer. As noted, we use strcpy to copy from one buffer to another. But there's no real point in doing that, if you're going to pass in allocated buffers and limit yourself to their sizes anyway; instead, just fgets directly into the buffers pointed at by the pointers in the argv array, instead of into a local one.
The argv[i]s are not strings in and of themselves, but pointers to areas of memory that contain text strings. That's what you're doing when you say options[j] = malloc(...) -- you're setting aside an area of memory for that pointer to point at. But that area of memory is just an area of memory, it doesn't have anything to do with the pointer, except that the pointer happens to be pointing at it.
So when you say argv[i] = line_buf, that doesn't mean copy the string itself. It means change the pointer, such that argv[i] now points to the same area of memory where line_buf[] starts. Then in the next iteration of your for loop, you overwrite that same area of memory. By the end of the loop, all ten of your pointers are pointing to line_buf, which contains the last line of your file, which is why you get ten copies of that line.
(What's also worth noting is that once readOptions() returns, that area of memory that all your pointers are pointing to is considered undefined, because line_buf[] only "exists" within the readOptions() function. It's only through luck that your program is printing the last line ten times, rather than printing garbage or crashing.)
Now, to copy a string from one place to another, you can use the strcpy() function, which can be added to your program by putting #include <string.h> at the top. You'd then write strcpy(argv[i], line_buf).
Here's what a simple version of strcpy() would look like, so you can see what it's doing:
char *strcpy(char *dest, char *source) {
int i = 0;
while (source[i] != '\0') { /* a zero (or "null") byte means end of string */
dest[i] = source[i];
i=i+1;
}
dest[i] = source[i];
return dest;
}
Notice that strcpy() doesn't have any way of knowing how much space there is to copy into! If you don't have enough space available, it will go right past the end of your space and into who knows what memory areas, which may cause your program to crash or behave strangely. This is called a buffer overrun, and it's one of the most common security errors. So make sure you have enough space before you call strcpy().
Related
How to print array of string by taking of user input? I am confused between str+i and str[i].
In my program, strings are not printed. It takes 5 strings as input, after that program terminates
#include <stdio.h>
int main()
{
char *str[5];
for (int i = 0; i < 5; i++)
{
scanf("%s", &str[i]);
}
for (int i = 0; i < 5; i++)
{
printf("%s\n", str[i]);
}
}
So firstly, go and read the answers, then come here for complete code. By span of 2 days, I arrived at two solutions to my problem with the help of below answers.
//1.
#include <stdio.h>
#include<stdlib.h>
int main()
{
char* str[5];
for (int i = 0; i < 5; i++)
{
str[i] = (char *)malloc(40 * sizeof(char));
scanf("%s", str[i]);
}
for (int i = 0; i < 5; i++)
{
printf("%s\n", str[i]);
}
}
//2
#include <stdio.h>
#include<stdlib.h>
int main()
{
char str[5][40];
for (int i = 0; i < 5; i++)
{
scanf("%s", &str[i]);
}
for (int i = 0; i < 5; i++)
{
printf("%s\n", str[i]);
}
}
Strings are a painful learning experience in c. Its quite unlike higher level languages.
First off, to answer your explicit question, str[i] is the value of the i-th element in an array. If str points to the array of characters"Hello", then str[1] is the value "e". str + i, on the other hand, is a pointer to the i-th element in an array. In the same situation, where str points to the array of characters "Hello", str + 1 is a pointer to the "e" in that array. str[i] and *(str + i) are identical in every way. In fact, the spec defines a[b] to be (*(a + b)), with all of the behaviors that come with it! (As an aside, C still supports a very ancient notation i[str] which is exactly the same as str[i] because addition of pointers and integers is commutative. You should never use the backwards form, but its worth noting that when I say they are defined to be the same, I mean it!)
Note that I have been very careful to avoid the word "string," and focused on "character arrays" instead. C doesn't technically have a string type. This is important here because you can't do easy things like std::string str[5] (which is a valid C++ notation to create an array of 5 strings) to get a variable length string. You have to make sure you have memory for it. char *str[5] creates an array of 5 char*, but doesn't create any arrays of characters to write to. This is why your code is failing. What is actually happening is each element of str is a pointer to an unspecified address (garbage memory from whatever was there before the variable was created), and scanf is trying to assign into that (nonexistent) array. Bad things happen when you write to somewhere random in memory!
There are two solutions to this. One is to use Serve Lauijssen's approach using malloc. Just please please please please please remember to use free() to deallocate that memory. In nearly any real program, you will not want to leak memory, and using free is a very important habit to get into early on. You should also make sure malloc did not return null. That's another one of those habits. It virtually never returns null on a desktop, but it can. On embedded platforms, it can easily happen. Just check it! (And, from the fact that I have to be reminded of this in the comments suggests I failed to get in the habit early!)
The other approach is to create a multidimensional array of characters. You can use the syntax char str[5][80] to create a 5x80 array of characters.
The exact behavior is a bit of a doozie, but you will find it just happens to behave the way you think it should in your case. You can just use the syntax above, and keep moving. However, you should eventually circle back to understand how this works and what is going on underneath.
C handles the access to these multidimensional arrays in a left to right manner, and it "flattens" the array. In the case of char str[5][80], this will create an array of 400 characters in memory. str[0] will be a char [80] (an 80 character array) which is the first 80 characters in that swath of memory. str[1] will be the next swath of 80 characters, and so on. C will decay an array into a pointer implicitly, so when scanf expects a char*, it will automatically convert the char [80] that is the value of str[i] into a char* that points at the first character of the array. phew
Now, all that explicit "here's what's actually going on" stuff aside, you'll find this does what you want. char str[5][80] will allocate 400 characters of memory, laid out in 5 groups of 80. str[i] will (almost) always turn into a char* pointing at the start of the i-th group of characters. Then scanf has a valid pointer to an array of characters to fill in. Because C "strings" are null-terminated, meaning they end at the first null (character 0 aka '\0') rather than at the end of the memory allocated for it, the extra unused space in the character array simply wont matter.
Again, sorry its so long. This is a source of confusion for basically every C programmer that ever graced the surface of this earth. I am yet to meet a C programmer who was not initially confused by pointers, much less how C handles arrays.
Three other details:
I recommend changing the name from str to strs. It doesn't affect how the code runs, but if you are treating an object as an array, it tends to be more readable if you use plurals. If I was reading code, strs[i] looks like the i-th string in strs, while str[i] looks like the i-th character in a string.
As Bodo points out in comments, using things like scanf("%79s", str[i]) to make sure you don't read too many characters is highly highly highly desirable. Later on, you will be plagued by memory corruptions if you don't ingrain this habit early. The vast majority of exploits you read about in major systems are "buffer overruns" which are where an attacker gets to write too many characters into a buffer, and does something malicious with the extra data as it spills over into whatever happens to be next in the memory space. I'm quite sure you aren't worried about an attacker using your code maliciously at this point in your C career, but it will be a big deal later.
Eventually you will write code where you really do need a char**, that is a pointer to a pointer to a character. The multidimensional array approach won't actually work on that day. When I come across this, I have to create two arrays. The first is char buffer[400] which is my "backing" buffer that holds the characters, and the second is char* strs[5], which holds my strings. Then I have to do strs[0] = buffer + (0 * 80); strs[1] = buffer + (1 * 80); and so on. You don't need this here, but I have needed it in more advanced code.
If you do this, you can also follow the suggestion in the comments to make a static char backing[400]. This creates a block of 400 bytes at compile time which can be used by the function. In general I'd recommend avoiding this, but I include it for completeness. There are some embedded software situations where you will want to use this due to platform limitations. However, this is terribly broken in multithreading situations, which is why many of the standard C functions that relied on static allocated memory now have a variant ending in _r which is re-entrant and threadsafe.
There is also alloca.
Since you have defined char *str[5], so str should be of type char **. So when scanf() expects char *, it is given &str[i] which is of type char **, and so it is not right. That is why your printf("%s\n", str[i]) might not work.
The (str+i) (which is of type char ** and not the same as str[i]) method might work with printf() in the above case because you are reading string values to &str[i]. This could be fine when you have input strings which are short. But then, reading values to &str[i] is not what you intend here, because str[i] is already of type char *. Try giving a very very long string as input (like aaaaaaa...) in the above code, and it will probably give you a Segmentation fault. So technically the method is broken, and you really need to allocate memory to each char * elements in your str array before reading in strings. For example, you can do
for (int i=0; i<5; ++i)
str[i] = (char *) malloc(length_you_wish);
Since each str[i] is of type char * and scanf() expects argument of type char *, use scanf( "%s", str[i] ), omitting & before str[i].
Now, you can printf() with
printf( "%s\n", str[i] ) or printf( "%s\n", *(str+i) ), where str[i] or *(str+i) is of type char *.
Lastly, you need to do
for (int i=0; i<5; ++i)
free(str[i])
Moral: str[i] is a pointer to a specific char array (it holds the address of the first char element of the array), but (str+i) points to str[i] (it refers to the address of str[i], so (str+i) and &str[i] should have same value).
I wonder if there is a way to initialize a string array to a value I decide on during memory allocation, so it won't contain any garbage and the null character will be placed at the correct place. I know that using calloc the memory allocated is initialized to all zeros, but in this case involving strings it doesn't help.
I practice using pointers and allocation memory in C.
There is an exercise in which I wrote a function for copying a string to another string - In main(), I allocate memory using malloc for both strings based on the strings lengths the user provides, and then the user enters the first string.
At this point I send the pointer of the first string and second string (uninitialized) as parameters to strCopy(char* str1, char* str2). Inside that function I also use another basic function I wrote, to calculate the length of a string. but as you may guess, since the second string is full of garbage, it's length calculation inside the function is messed up.
void strCopy(char* str1, char* str2)
{
int str1len = str_len(str1); // basic length calculating function
int str2len = str_len(str2);
int i;
for (i = 0; i < str2len; i++)
{
str2[i] = str1[i];
}
str2[i] = '\0';
if (str2len < str1len)
printf("There wasn't enought space to copy the entire string. %s was
copied.\n", str2);
else
printf("The string %s has been copied.\n", str2);
}
Right now it works fine when initializing str2 in a loop in main(), but I am interested in other possible solutions.
Thank you very much for any help!
No, there is not. You have to manually initialize it.
If you want to copy a string while allocating memory, you can use strdup. Note that this is a POSIX function, which means this will only work on POSIX-compliant operating systems, Windows, and any other OSs that implement it.
Well, for this particular situation you can use memcpy. A simple way could be like this in your code instead of the for loop:
memcpy(str2, str1, str2len);
But your code is seriously flawed. I don't know how you have implemented str_len but there is absolutely no way (if you're not using non-standard, non-portable, dirty hacks) to get the size of the block that a pointer is pointing to.
I'm trying to create a dynamic array of 1000 character long strings using calloc:
int i;
char** strarr =(char**)calloc(argc,sizeof(char)*1000);
if(strarr == NULL)
return 0;
strarr[0][0] ='a';
printf("%c\n",strarr[0][0]);
Every time i try to run this code i get segmentation fault on the printf line, i don't get why does this happen (you can assume that argc is bigger than 0)
Thanks
P.s. im sorry that the code is in text format but im using a mobile so i dont have the code feature
Try this:
const int num_of_strings = 255; //argc ?
const int num_of_chars = 1000;
int i;
char** strarr =(char**)malloc(sizeof(char*)*num_of_strings);
if(strarr == NULL)
return 0;
for (i = 0; i < num_of_strings; i++) strarr[i] = (char*)malloc(sizeof(char)*num_of_chars);
Hello and Welcome to the world of undefined behaviour, one of the darkest territories of the C language. Your code has several problems, which cause undefined behaviour in several occasions, but they all get executed, until you reach the printf line, where you are accessing memory, you have not allocated, which is finally caught by your system and, thus, a segmentation fault is produced.
But I think, it would be better to walk ourselves through your code.
The variable i, which is declared in the int i; line is not used anywhere in the code you have posted, but I guess you need it later.
The first piece of code, that is not right, is in this second line, where you declare an array of strings or a char**. That means that you have a pointer to pointers to chars. So, what you really want to do there is allocate memory for those pointers and not for the chars they will point to. Note that a char consumes a different amount of memory than a char*. This line is, thus, the one to go with.
char** strarr = (char**) calloc(argc, sizeof(char*));
This will allocate memory for argc blocks of memory, each of which is of size 4 or 8 bytes, which depends on whether your system is 32 or 64-bit.
You are doing a very good job of checking whether the calloc function returned NULL or not, which is a very good practice overall.
Next, you will want to allocate memory for the strings themselves, that are pointed to by the pointers, for which you allocated memory in the previous line. These lines will do it.
for (int i = 0; i < argc; i++) {
strarr[i] = (char*) calloc(1000, sizeof(char));
}
This will now allocate 1000-character lengthed strings for every element of our argc-sized string array.
After that, you can continue with your code as it is and I think that no errors will be produced. Please accept an additional piece of advice from me. Learn to love valgrind. It is a very helpful program, which you can run your code with, in order to analyse memory. It is my first step, whenever I get a segmentation fault.
i just started learning c. i am doing an exercise and the question is as follows.
Write a function called insertString to insert one character string into another string.The arguments to the function should consist of the source string, the string to be inserted, and the position in the source string where the string is to be inserted. So, the call insertString (text, "per", 10); with text as originally defined "the wrong son" results in the character string "per" being inserted inside text, beginning at text[10].Therefore, the character string "the wrong person" is stored inside the text array after the function returned.
#include<stdio.h>
int insertString(char[],char[],int);
int stringLength(char[]);
int main()
{
char text[]="the wrong son";
int result=insertString(text,"per",10);
if(result!=-1)
printf("string 1 is : %s \n",text);
else
printf("Not possible\n");
return 0;
}
int insertString(char a[],char b[],int pos)
{
int i=0,j=0;
int lengthA=stringLength(a);
int lengthB=stringLength(b);
if(pos>lengthA)
return -1;
for(i=lengthA;i>=pos;i--)
a[i+lengthB]=a[i];
for ( i = 0; i < lengthB; ++i )
a[i + pos] = b[i];
return 1;
}
int stringLength(char x[])
{
int length=0;
while(x[length]!='\0')
length++;
return length;
}
i have done this and it's working too. but i am receiving a message abort trap : 6. when i looked upon it, i learned it's an error because i am writing to the memory that i don't own. since i have used variable length character arrays, wherever the null character is, indicates the end of array and i am trying to extending it by inserting a string, that's my understanding. am i right so far?
i am also moving the null character. i don't know whether it's right or wrong.
so is there a way to get around this error? Also, i don't know pointers yet and they're in the next chapter of the textbook .
Any help in this would be appreciated very much.
A variable-length array is a very specific C construct that has nothing to do with what your textbook calls "variable length arrays". If I were you I would not trust this textbook if it said that 1+1=2. So much for it.
A character array that ends with a null character is called string by pretty much everyone, everywhere.
char text[]="the wrong son";
Your textbook led you to believe that text will hold as many characters as you need. Alas, there is no such thing in C. In fact text will hold exactly as many characters as there are in its initializer, plus 1 for the null terminator, so you cannot insert anything in it.
In order for your program to work, you need to explicitly allocate as many characters for text as the resulting string will contain.
So as there are 14 characters in "the wrong son" (including the terminator) and three characters in "per" (not including the terminator), you need 17 characters in total:
char text[17]="the wrong son";
You can also check your calculations:
int result=insertString(text, "per", 10, sizeof(text));
...
int insertString(char a[], char b[], int pos, int capacity)
{
...
if (lengthA + lengthB + 1 < capacity)
return -1;
...
First you must understand what the difference between C-programming and other programming languages are manual memory management and pointers.
In C you have to do everything yourself but you have total control of everything, in other languages like Java a lot is made automatically for you but you can't open the hood.
Memory handling in C is the essence of C and is very different from for instance Java that looks very alike C. Java and C syntax are very much alike, but in two completely different worlds.
C++ is an extension of C that allow similar features like in Java, but still memory wise is C.
There are two types of memory in C:
Automatic string array (declared as char xx[]) with the exact length of its initialization number or defined string length (the number between the []) + 1 (for null termination), can't be changed.
Dynamic memory (declared as char*) is allocated with calloc() or alloc() and can be changed in length with realloc() and must be manually freed or else the program will leak memory (still allocate memory after the program is ended (some OS has automatic clean-up of that but it is bad style C programming not freeing memory)).
Dynamic memory is delivered to a pointer (char*) that points to the memory allocated. Pointers can point at any type of memory also string arrays and even integers.
A pointer is an integer, a number pointing at the available memory address in the OS, the OS keep track of the memory of each pointer, but do not clean it up like in Java.
Also note that after the realloc the old memory of the old pointer is freed by the command, new is allocated that you must manually free, later after use.
It is possible to send a pointer (it is just a number) into a function and the function changes the pointer (it is just another number pointing at memory (that might not be the same)).
Because of this it is essential to return the new pointer from functions that might have changed its content.
In practice the core of C-programming is pointer programming and the programmer must have a firm track of the memory or the program goes berserk, you have to learn the routines.
With pointer programming it is possible to have absolute control over all the memory and the functions becomes normally very efficient, fast and memory lean.
This is used also when we are talking about huge data like in high resolution pictures or video content, and often the only way to get performance.
Extended level - pointer to pointers
When getting more advanced it is possible to send the pointer of a pointer (char**) to a function allowing the function to amend the content of a pointer like reallocation of a string and the updated pointer will be readable by the calling function. This way multiple pointers can be amended (there is only one return value).
A pointer to a pointer, points to the memory where the pointer address (the number that points to the memory) is stored, so sending it into the function the function can change the pointers number (what memory it points at) and the calling function can read it (the same pointer have a new value).
Pointers to pointers are normally used for instance in database programming with linked lists being able to control a huge number of memory chunks in a long chain, and being able to handle them smoothly.
Most other programming languages basic system is programmed in C, so normally it is possible to integrate chunks of C--code to improve performance.
ANSI C is the same in all computers so it is also a way of making code real portable from system to system and work the same in them all.
Lets check out your case, here is a sample code to show.
#include<stdlib.h>
#include<string.h>
#include <stdio.h>
char* insertString(
char* pTarget,
char* pInput);
void main(void)
{
char Target[9] = { "Hello" };
char Target2[9] = { "Hi" };
char Input[] = { " World" };
Target and Target2 are automatic string arrays with the exact length of its initialization number, the number between the[] and Input is defined by the string length(+1 for null termination), can't be changed.
So, the length of Input is defined as 7 bytes, six letters +1, as Target and Target2 are defined as 9 bytes (can contain 8 letters), can't be changed, they are string arrays.
This below will not work, because Target is too short, only 9 chars space (enough for 8 letters) and Target + Input is 11 letters, the program will crash.
strcat(Target, Input);
But this will work because Target2 is 9 chars (space for 8 letters) and Target2 + Input is 8 letters, so it fits.
strcat(Target2, Input);
printf("%s\n", Target2);
This below will not work because Target is an automatic char array with the exact length of its initialization number or string length +1 (for null termination), its length can't be changed.
They are fixed in length and not possible to extend or shrink in length, can't realloc them, and they will be freed automatically at the end of the function.
In fact, it is created normally in another set of memory than the dynamic memory and is protected from change.
pTarget = insertString(Target, Input);
{
This below will work because it is dynamically allocated memory(by a calloc or alloc command) that can be reallocated to any size.
Dynamic memory(volatile) in C is not automatic like in other programming languages, must be taken care of manually.
Usually in C a p is put ahead for pointers to differentiate them from automatic string arrays.
Dynamically allocated memory must be manually freed after use or the program will leak memory, it is not Java with auto clean - up.
char* pTarget = calloc(strlen(Target) + 1, sizeof(char));
if (pTarget) {
strcpy(pTarget, Target);
pTarget = insertString(pTarget, Input);
Also notice you as a programmer must check that you got the memory you asked for by the memory allocation command calloc.
If not (very unlikely memory is unavailable in 2022) you can't perform the action and, you fail, or the program will crash.
printf("%s\n", pTarget);
free(pTarget);
}
else
printf("%s\n", "Failure!");
}
}
char* insertString(
char* pTarget,
char* pInput)
{
We are here reallocating the memory to get it enlarged to fit our use
pTarget = realloc(pTarget, (strlen(pTarget) + strlen(pInput) + 1) * sizeof(char));
The old memory is freed by realloc and a new larger is allocated for us.
Now the pointer (the number that points to memory) might not be the same as before realloc.
A pointer is a storage of the number and the same storage pTarget contains the new number to the new data, OK.
if (pTarget)
strcat(pTarget, pInput);
return pTarget;
}
int replace_substring (char *str, char *substr, char *new_substr) {
int pos = delete_substring (str, substr); /* first delete the existing substring */
if (pos == -1) return pos; /* substring not found, return */
insert_substring (str, pos, new_substr); /* add the new substring at the deleted position */
}
int replace_substring (char *str, char *substr, char *new_substr) {
int pos = delete_substring (str, substr); /first delete the existing substring/
if (pos == -1) return pos; /substring not found, return/
insert_substring (str, pos, new_substr); /add the new substring at the deleted position/
}
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.