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);
}
Related
I am given an array of strings in the form of a pointer to a pointer of a character (that is, char **). I wish to access each element in the array,
char **strings = {"hello", "bye", "whatusp"};
printf("%s\n", *(&strings));
printf("%s\n", *(&strings + 1));
I notice that the first printf() works, as it outputs "hello" for me, but the second doesn't output anything. The +1 does increment by 8 instead of 1, since the address is in bytes. How can I access an arbitrary element in such a double pointer?
Just as simple as:
char *strings[] = {"hello", "bye", "whatusp"};
printf("%s\n", strings[0]);
printf("%s\n", strings[1]);
printf("%s\n", strings[2]);
First of all, the line
char **strings = {"hello", "bye", "whatusp"};
is wrong. If you want to declare an array of 3 pointers to string literals, then it should be the following instead:
char *strings[3] = {"hello", "bye", "whatusp"};
In the previous line, you can omit the 3, because the compiler is smart enough to count the number of elements itself, since you are initializing the array.
The lines
printf("%s\n", *(&strings));
printf("%s\n", *(&strings + 1));
are also wrong, because when using printf with the %s format specifier, you must provide a pointer to a string, i.e. a char *. However, you are providing a char** instead in both lines.
The expression *(&strings) will evaluate to a char ** for the following reason:
The expression &strings will evaluate to a pointer to strings. Since strings itself is an array of 3 pointers to char, a pointer to strings is a pointer to an array of 3 pointers to char. Afterwards, you are applying the indirection operator * on this data type, so that the result of this operation is an array of 3 pointers to char. When passing this data type to printf, the array will decay to a pointer to the first element of the array, i.e. to a pointer to a pointer to a char (which is a char**).
You should simply write the following instead:
printf( "%s\n", strings[0] );
printf( "%s\n", strings[1] );
The expression strings[1] is equivalent to *(strings+1).
char **strings is a pointer to a pointer to char, not array of pointers to char, your compiler should have given you a warning anyways, if not you should enable them.
For that assignment to work, you will need to have an array of pointers, char *strings[] or if you want to use plain pointer notation (array notation is using pointer arithmetic in the background though), you could dynamically allocate memory for the first dimension.
#include <stdio.h>
#include <stdlib.h>
#define SIZE 3
int main(void)
{
char **strs = NULL;
if ((strs = malloc(SIZE * sizeof(char *))) == NULL) /* check malloc result */
{
exit(EXIT_FAILURE);
}
*strs = "hello"; /* assignment makes sense in this case but you cant modify the string since its read-only*/
*(strs + 1) = "bye";
*(strs + 2) = "whatsup";
for (int i = 0; i < SIZE; i++)
{
puts(*(strs + i));
}
/* Alternative that will allocate space for each string if you need to store them or modify them later */
/* for (int i = 0; i < 3; i++)
{
if ((*(strs + i) = malloc(YOUR_STRINGS_LENGTH)) == NULL)
{
exit(EXIT_FAILURE);
}
snprintf(*(strs + i), YOUR_STRINGS_LENGTH, "string");
}
*/
return 0;
}
I am given an array of strings in the form of a pointer to a pointer of a character (that is, char **)
There is no such thing: a char** is just a pointer. It is not an array.
if thing is char** then
*thing is char* and **thing is, as declared, a char.
An array can be seen as a pointer, but a pointer is not an array.
note: the prototype for main is in general
int main( int argc, char** argv)
so what you need to do is the same as every C program gets from the system.
Example
To have char** as an array of pointers to char you must build it
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
char* array[] = {
"I", "wish", "to", "access", "each", "element",
"in", "the", "array"
};
int N = sizeof(array) / sizeof(char*);
printf("%d strings in total\n\n", N);
char** strings = (char**)malloc(N * sizeof(char*));
for (int i = 0; i < N; i=i+1)
*(strings+i) = *(array + i);
for (int i = 0; i < N; i=i+1)
printf("%3d %s\n", 1 + i, *(i + strings));
// pointer is not an array
char thing = '#';
char* p = &thing;
char** pp = &p;
printf("\n\nthing is '%c', *p is '%c', **pp is '%c'\n",
thing, *p, **pp);
return 0;
}
output
9 strings in total
1 I
2 wish
3 to
4 access
5 each
6 element
7 in
8 the
9 array
thing is '#', *p is '#', **pp is '#'
In particular note this lines
char** strings = (char**)malloc(N * sizeof(char*));
for (int i = 0; i < N; i=i+1)
*(strings+i) = *(array + i);
where is defined that strings is an area of the needed size and than the pointers are initialized to the strings of the input array.
In this code snippet, strncpy has the n value as a difference of two char pointers. How can two string pointers be subtracted? What is the value of n here?
The program does compile successfully but doesn't the size have to be an int value?
void replace(char *s1) {
char r[4][5] = { "get", "tell", "your", "house" };
char rep[4][10] = { "see", "us", "tall", "kite" };
char buff[500];
int i;
char *ch;
for (i < 0; i < 4; i++) {
if ((ch = strstr(s1, r[i]))) {
strncpy(buff, s1, ch - s1);
buff[ch-s1] = 0;
sprintf(buff + (ch - s1), "%s%s", rep[i], ch + strlen(r[i]));
s1[0] = 0;
strcpy(s1, buff);
return replace(s1);
}
}
}
If you have two pointers p and q that point into the same array, then p - q evaluates to the (signed) number of elements between p and q in the array. For example, consider this code:
int array[137];
int* p = &arr[10];
int* q = &arr[5];
ptrdiff_t diff = p - q;
Here, p points to the tenth element of the array, q points to the fifth element of the array, so p - q would be five. (The special type ptrdiff_t is an integer type that’s big enough to hold the difference of any two pointers.)
Another way to interpret this difference is to ask “what index does pointer p point to if we imagine the array starts where q is pointing?” In that case, the answer is five, since if we treat q as the base of the array, then p would be at index five. In your case, your pointer ch was set equal to the return value of strstr, so it points somewhere into the middle of s1. The expression ch - s1 then means “the position in the string where ch points.”
Making an analogy to points in space: if you have two points p and q, you can think of p - q as a vector representing the direction you need to go to get from q to p. You can’t meaningfully add the points p and q to get p + q, though, just as you can’t add two pointers in C.
I am trying to learn C, so I went to try out some of the coderbyte challenges in C, one of which is to reverse a string. After gettung multiple compilation errors due to syntax I tried looking for examples and encountered this one on http://www.programmingsimplified.com/c-program-reverse-string
#include<stdio.h>
int string_length(char*);
void reverse(char*);
main()
{
char string[100];
printf("Enter a string\n");
gets(string);
reverse(string);
printf("Reverse of entered string is \"%s\".\n", string);
return 0;
}
void reverse(char *string)
{
int length, c;
char *begin, *end, temp;
length = string_length(string);
begin = string;
end = string;
for (c = 0; c < length - 1; c++)
end++;
for (c = 0; c < length/2; c++)
{
temp = *end;
*end = *begin;
*begin = temp;
begin++;
end--;
}
}
int string_length(char *pointer)
{
int c = 0;
while( *(pointer + c) != '\0' )//I DON'T UNDERSTAND THIS PART!!!!!
c++;
return c;
}
c is not even a char, so why would you add it? Or is pointer some sort of index considering the context of the while loop?
The + operator here does not mean string concatenation; it means pointer arithmetic. pointer is a pointer to a char, and c is an int, so pointer + c results in a pointer to a char that is c chars further forward in memory. For example, if you have an array {'j', 'k', 'l', 'm'} and pointer pointed at the 'j', and c was 2, then pointer + c would point at the 'l'. If you advance a pointer like this then deference it, that acts the same as the array indexing syntax: pointer[c]. The loop is therefore equivalent to:
while( pointer[c] != '\0' )
c++;
The effect of adding a pointer to an integer (or vice-versa) scales according to the size of what the pointer is (supposedly) pointing to, so you don't need to account for different sizes of objects. foo + 5, if foo is a pointer, will go 5 objects further forward in memory, whatever size object foo points to (assuming that foo is pointing at the type it is declared to point to).
Here you can talk about pointer arithmetic.
There is an important concept :
Addition a integer to a pointer will move the pointer forward. The number that you are adding will be multiplied by the size of type that the pointer is pointing to.
Example :
An int is coded on 4 bytes, so when we increment the pointer by 1, we have to multiply by 4 to obtain what really happen in regular arithmetic.
int a[3] = {1, 3, 6};
printf("%d\n", *(a + 1)); // print 3, look 4 bytes ahead
printf("%d \n", *(a + 2)); //print 6, look 8 bytes ahead
In your case :
A char is coded on 1 byte so
*(pointer + c) with c == 3
will evaluate to a memory address of 3 bytes (3 chars) ahead.
So the code :
while( *(pointer + c) != '\0' )
c++;
will evaluate the value of your pointer at a specific memory address. If the character is equal to the null-character, we have reached the end of the string.
Remember that *(pointer + c) is equivalent to pointer[c].
c is being used as an index.
/* reverse: Reverses the string pointed to by `string` */
void reverse(char *string)
{
int length, c;
char *begin, *end, temp;
/* compute length of string, initialize pointers */
length = string_length(string);
begin = string; /* points to the beginning of string */
end = string; /* will later point to the end of string */
/* make end point to the end */
for (c = 0; c < length - 1; c++)
end++;
/* walk through half of the string */
for (c = 0; c < length/2; c++)
{
/* swap the begin and end pointers */
temp = *end;
*end = *begin;
*begin = temp;
/* advance pointers */
begin++;
end--;
}
}
/* computes length of pointer */
int string_length(char *pointer)
{
int c = 0;
/* while we walk `pointer` and we don't see the null terminator */
while( *(pointer + c) != '\0' )//I DON'T UNDERSTAND THIS PART!!!!!
c++; /* advance position, c */
/* return the length */
return c;
}
The string_length function can be rewritten as
size_t strlen(const char *str)
{
size_t i;
for (i = 0; *str; ++i)
;
return i;
}
From what I understand if the string is : abcd
the result would be : dcba
if the input is : HELLO-WORLD
the output would be : DLROW-OLLEH
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.
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.