This problem is driving me crazy, I'm sure I'm missing something. I need to initialize an array of chars using only pointers. Below is the code I have so far:
int p2(){
/* Implements problem 2 of lab */
// Create an array
char **s = (char**)malloc( 11 *sizeof(char));
char *p = *s;
char start ='A';
while( p != s+10){
*p = start;
start++;
p++;
}
return(0);
}
The problem I'm having is I don't know how to address the characters inside of the array. I understand the base address of the array is **s, and the pointer to the first element is *s. What I don't understand is how to get to **s+10 (i.e. the end of the array).
Can anyone shine some light for me??? Please!
EDIT: Ok, looks like I misunderstood the question. I appears I need to create an array of strings (thus the char ** allocation). Then I need to loop through this array, and assign each string (i.e. char *) a value 15 chars long. Please let me know if I'm understanding this correctly:
char **strings ==> strings[0 ... n ] where each element is a pointer to a char (possibly an array). There for *string ==> strings[0], *(string+1) = strings[1], etc etc.
Am I close or way off?
char **s is 2 dimensional array of characters, or array of C strings if you want.
If you want to use array of characters you should use:
char *string = (char*)malloc( 11 *sizeof(char));
If you really want to initialize array of strings, at first step you're initializing array of pointers, that's:
char **s = (char**)malloc( 11 *sizeof(char *));
Please note that I'm using char * inside sizeof. Than when you may use strings, but at first you must initialize each string.
s[0] = (char*) malloc( 15*size(char)); // This is actually string, 14 characters long (NULL terminated)
char *p = s[0]; // p is pointer to beginning of your string now
And there's two way how to address your string:
s[0][3] // 4th character of your string
p[3]
Or if you want to use just pointers:
char *p = *(s+0);
*(p+3); // 4th character
*((*(s+0))+3) // To do it "hardcore"
EDIT: added an example
When you have **char p and use p++ or p + 1, C increases memory address. *p operator tells compiler that you now want to work with data stored in memory, not with pointer. Therefor those two syntax do the same:
p[10] = 'a';
*(p+10) = 'a';
So if you want traverse both your dimensions, you should use:
for( int i = 0; i < 11; i++){
char *p = *(s+i);
for( int j = 0; j < 10; j++){
*(p + j) = 'a'; // Say you wanna fill them with as
}
// You may also use this syntax:
while( p < (*(s+i) + 10)){ // or use != instead of <
*p = 'a';
p++;
}
}
I think you meant this:
char *s = (char*) malloc(11 *sizeof(char));
char *p = s;
In which case you'd address the characters with s[x]
First, you don't need a char ** unless you need an array of arrays.
Second, you can get to the end of the array with (*s)[10] or *((*s)+10)
Third, in C programming, don't cast the result of malloc()
The code is falling apart here.
char **s = (char**)malloc( 11 *sizeof(char));
You're allocating enough memory for 11 chars, which sounds like what you want to do.
However, you're casting the address to those 11 chars to a (char**) as if you were allocating space for pointers, not chars.
Why should you use a double pointer for creating an array of chars?
char *s = (char *) malloc(10 * sizeof(char));
char *start = s; // save starting pointer
for(; s < start+10; s++)
*s = 'a';
return 0;
If you allocate char ** essentially you're allocating an array of pointers to char(eg. array of strings). If you need char array, allocate char array. If you start working with pointers a design of stack and heap can be really helpful.
Related
I'm trying to copy 3 strings from 2D const char array into a double pointer of char.
char **E = malloc(sizeof(char));
const char *e[3] = {"aa", "bb", "cc"};
for (int k=0; k<3; k++)
{
E[k] = malloc(sizeof(char));
strcpy(E[k], e[k]); //crash occurs here
}
This solution is when you want E to point to the same constant strings
as the variable e.
Try this code:
#include <stdio.h>
#include <stdlib.h>
int
main(void)
{
char **E = malloc(3*sizeof(char *));
const char *e[3] = {"aa", "bb", "cc"};
int k;
for (k=0; k<3; k++)
{
E[k] = e[k];
}
for( k=0; k<3; k++ )
{
printf( "%s\n", E[k]);
}
return 0;
}
Here is the explanation.
The variable 'e' is an array of 3 pointers to constant characters.
Lets say "aa" is stored in memory address of 100.
Lets say "bb" is stored in memory address of 200.
Lets say "cc" is stored in memory address of 300.
The 'e' variable looks like this:
e[0] e[1] e[2]
|------|-------|------|
| 100 | 200 | 300 |
|------|-------|------|
The E[k] = e[k]; assignment would result E to look like
E[0] E[1] E[2]
|------|-------|------|
| 100 | 200 | 300 |
|------|-------|------|
char **E = malloc(sizeof(char));
A pointer to pointer to char must reserve space for a pointer to char, not for a plain char.
It seems that you want a modifiable copy of the constant array of pointers, then change to:
char **E = malloc(sizeof(char *) * 3);
const char *e[3] = {"aa", "bb", "cc"};
for (int k=0; k<3; k++)
{
E[k] = malloc(strlen(e[k]) + 1);
strcpy(E[k], e[k]);
}
char **E = malloc(sizeof(char));
should be
char **E = malloc(3 * sizeof(char*));
The former allocates just one byte but you need to allocate memory for 3 pointers to char (char*) and this is what the latter does.
Similarly,
E[k] = malloc(sizeof(char));
should be
E[k] = malloc(strlen(e[k]) + 1);
as you need memory to store each of the respective strings (+1 for the NUL-terminator '\0') in E[K] and not just 1 byte.
E is a char**, which means that it contains char* that themselves contain char.
This mean that E have to be allocated enough space to contain the char*, that mean malloc of:
sizeof(char*) * thenumberofchar*youwantittocontains
Same goes for each char* (E[k]) contained into E, they have to be allocated of
sizeof(char) * thenumberofcharyouwanittocontains + 1 (for the '/0' character that tell that the char* has ended)
Because if you don't allocate enough memory space, you won't be able to write at all memory location you're trying to access via E[k] and even E[k][i], because it's not allocated for your program, causing a Segmentation Fault.
beginner here
This is absolutely infuriating me, how do I create an array that holds strings where the length / amount of strings are unknown? I essentially want to create a dictionary where
array[0] = "word"
array[1] = "word2"
array[2] = "word3"
and so on
I tried :
array** = malloc(INIT); where init was defined as 10
memset(array, '\0', 10)
then, under a loop
array[i] = malloc(INIT)
array[i] = string from another source ( array2[i] ) (array2 is a char*)
but that just gives errors / junk text and I have no clue how to assign strings to the array
I'm having a hard time understanding pointers / jargon in general, I've looked at all the similar questions and can't understand any of the answers.
Try doing this -
int main(){
int i;
char *arr[10];
for(i=0;i<10;i++){
char str[1000];
scanf("%s", str);
arr[0] = (char*) malloc(strlen(str));
strcpy(arr[0], str);
}
return 0;
}
You can dynamically create an array of pointers to strings and in that way keep it flexible:
char** array = malloc(sizeof(char*)*n); // allocates an array of char* pointers
if you later need to extend the array use realloc
char** newarray = realloc(array,sizeof(char*)*(n+1));
if (newarray != NULL)
{
array = newarray;
...
}
You must also remember to allocate space for where the pointers point to for storing your strings
array[i] = strdup("blabla");
or
array[i] = malloc(strlen("blabla")+1);
strcpy(array[i], "blabla" );
I am trying to build a char array of words using calloc.
What I have:
char** word;
word=(char**)calloc(12,sizeof(char*));
for(i=0;i<12;i++){
word[i]=(char*)calloc(50,sizeof(char));
}
Is this correct if I want a char array that has 12 fields each capable of storing 50 characters?
Thanks!
The code is correct. Some points:
No need to cast return value of calloc() ( Do I cast the result of malloc? )
sizeof(char) is guaranteed to be 1
So code could be rewritten as:
char** word;
int i;
word = calloc(12, sizeof(char*));
for (i = 0; i < 12; i++)
word[i] = calloc(50, 1);
In C, most of the functions that operate on 'strings' require the char array to be null terminated (printf("%s\n", word[i]); for example). If it is required that the buffers holds 50 characters and be used as 'strings' then allocate an additional character for the null terminator:
word[i] = calloc(51, 1);
As commented by eq- a less error prone approach to using sizeof is:
word = calloc(12, sizeof(*word));
Trying to learn pointers better I wrote this code. The intention was to print one character of a string at a time in a for loop. Again trying to learn how to increment a pointer and then dereference the pointer.
char *string = "abcdef";
char *pointer = &string;
for (int i =0; i < 4; i++)
{
printf("the next charater is %c\n", *pointer);
pointer = (char *)pointer + sizeof(char);
}
want it to print:
the next charater is a
the next charater is b
the next charater is c
the next charater is d
char *pointer = &string;
should be
char *pointer = string;
string is a pointer variable that contains the address of your string literal. You want the address of the string literal, so you should simply copy the value in string - not take the address of the local pointer variable - your current code gives you a pointer to a pointer to a string.
Additionally, pointer = (char *)pointer + sizeof(char); doesn't require a cast, and it should not use sizeof(char). When incrementing a variable of type pointer to X, incrementing it by one will increment it by sizeof(X) bytes - increment by one to point at the next X. Use pointer += 1; or ++pointer instead.
If you want to print (or otherwise process) the whole string one char at a time, you may use the following idiom:
char *p = /* ... */;
while (p && *p) {
printf("next char: %c\n", *p++);
}
The condition first tests whether p is NULL, i.e. if it is wise to dereference p at all. If p is not NULL, *p tests whether you already reached the end of the string, denoted by the '\0' character, which happens to be 0.
If you want to use pointer to pointer to string then you can use like this:
char *string = "abcdef";
char **pointer = &string;
int i;
for (i =0; i < 4; i++)
{
printf("the next charater is %c\n", **pointer);
*pointer = *pointer + sizeof(char);
}
AFunc changes what was sent to it, and the printf() outputs the changes:
void AFunc ( char *myStr, int *myNum )
{
*myStr = 's';
*myNum = 9;
}
int main ( int argc, char *argv[] )
{
char someString = 'm';
int n = 6;
AFunc(&someString, &n);
printf("%c" "%d", someString, n);
}
But what if the string was more than one char? How would the code look differently? Thanks for any help.
If it were a "string" instead of a char, you would do something like this:
#include <stdio.h>
void AFunc (char *myStr, int *myNum) {
myStr[0] = 'p'; // or replace the lot with strcpy(myStr, "pax");
myStr[1] = 'a';
myStr[2] = 'x';
myStr[3] = '\0';
*myNum = 9;
}
int main (void) {
char someString[4];
int n = 6;
AFunc(someString, &n);
printf("%s %d", someString, n);
return 0;
}
which outputs:
pax 9
A "string" in C is really an array of characters terminated by the \0 (NUL) character.
What the above code does is to pass in the address of the first character in that array and the function populates the four characters starting from there.
In C, a pointer to char isn't necessarily a string. In other words, just because you have char *x;, it doesn't mean that x is a string.
To be a string, x must point to a suitably allocated region which has a 0 in it somewhere. The data from the first character that x points to and up to the 0 is a string. Here are some examples of strings in C:
char x[5] = {0}; /* string of length 0 */
char x[] = "hello"; /* string of length 5, the array length being 6 */
char *x = "hello"; /* string of length 5. x is a pointer to a read-only buffer of 6 chars */
char *x = malloc(10);
if (x != NULL) {
strcpy(x, "hello"); /* x is now a string of length 5. x points
to 10 chars of useful memory */
}
The following are not strings:
char x[5] = "hello"; /* no terminating 0 */
char y = 1;
char *x = &y; /* no terminating 0 */
So now in your code, AFunc's first parameter, even though is a char * isn't necessarily a string. In fact, in your example, it isn't, since it only points to a memory that has one useful element, and that's not zero.
Depending upon how you want to change the string, and how the string was created, there are several options.
For example, if the myStr points to a writable memory, you could do something like this:
/* modify the data pointed to by 'data' of length 'len' */
void modify_in_place(char *data, size_t len)
{
size_t i;
for (i=0; i < len; ++i)
data[i] = 42 + i;
}
Another slightly different way would be for the function to modify data until it sees the terminating 0:
void modify_in_place2(char *data)
{
size_t i;
for (i=0; data[i]; ++i)
data[i] = 42 + i;
}
You are only dealing with chars and char pointers. None of the char pointers are valid strings as they are not null terminated.
Try defining a string and see what it looks like.
But what if the string was more than one char? How would the code look
differently? Thanks for any help
Ofcourse, you would modify the other characters as well, but in the exact same way you did the first time.
Declare a char array and pass its address
Modify values at those address
A char array would be a more clear term for a string.