Size of char pointer - c

int main()
{
int i;
char *names[5] = {"Miri", "Tali", "Ronit", "Avigail", "Shlomit"};
//Printing all the names:
for (i=0; i<5; i++)
printf("%s\n" , names[i]);
return 0;
}
How come its print the whole name? does names[0] (for example) shouldn't print only M?

names is array of character pointers. So names[0] is char * pointing to "Miri".
And similarly for other subsequent items.

In your program names is an array of pointers to char as already was mentioned in Rohan's answer, so to print the first character you should first access the array element and then the the 0th character
printf("%c\n", names[i][0]);
also note that the appropriate specifier is "%c" for one character, since "%s" expects a pointer to char, which should point to a null terminated sequence of bytes, i.e. a string.
Aditionally you should declare the array like
const char *names[5] = {"Miri", "Tali", "Ronit", "Avigail", "Shlomit"};
because the elements are string literals, and should not be modified. So using the const specifier you prevent acidentally doing that.

Related

How to pass a 1D array of 500 pointers to a function in C

The programm is compiling ok but once the user inputs something to the array it crashes. Any help will be appreciated :)
#include <stdio.h>
#include <stdlib.h>
void Register(char *arr[],char arr2[]);
int main() {
char *Username[500];
char table1[20];
Register(Username,table1);
return 0;
}
void Register(char *Username[],char table1[]){
int i;
for(i = 0; i < 500; i++){
scanf("%s",&table1);
Username[i] = table1;
printf("for i = %d username[%d] is %s\n\n",i,i,Username[i]);
}
}
The problem is that when you pass your arrays they decay to pointers to their first element. For "array" arguments something like e.g. char table1[] is actually char *table1. And this is a problem when you try to use the address-of operator & in scanf.
When you use &table1 in the scanf call you get a pointer to the pointer, which has the type char **, not the expected char *. This mismatch between the format %s and the expected type leads to undefined behavior and probably your crash.
The solution to this crash is to never use the address-of operator for reading strings (with e.g. the %s format), as it's even wrong when you have an actual array:
scanf("%s",table1);
As for the problem of making all elements of Username point to the single string in table1, I recommend that you use arrays of arrays for Username instead:
char Username[500][20];
This array decays to a pointer to an array, with the type of char (*)[20], which needs to be part of the Register function declaration:
void Register(char (*Username)[20]);
Then you can use this directly in the call to scanf:
scanf("%19s", Username[i]);
Also note how I limited the length of the input string, so you can't read more than the arrays can handle (and it's 19 because the array need to fit the string null-terminator as well).
In this statement
scanf("%s",&table1);
instead of reading a string into the array pointed to by the pointer table1 the string is read into the pointer itself.
You have to write
scanf("%s",table1);
Also the function Register does not make great sense because all elements of the array Username will point to the first character of the array table1. That is all elements of the array will point to the first character of the last string that was read.
You need to allocate memory dynamically. Also the second parameter of the function is redundant.
The function cam look the following way
size_t Register( char *Username[], size_t n )
{
char record[20];
int i = 0;
for ( ; i < n && scanf( "%19s", record ) == 1; i++ )
{
Username[i] = malloc( strlen( record ) + 1 );
strcpy( Username[i], record );
printf( "for i = %zu username[%zu] is %s\n\n", i, i, Username[i] );
}
return i;
}
And in main the function can be called like
size_t n = Register( Username, 500 );
\Of course you will need to free all allocated memory.

Weird beahaviour of string pointers

#include <stdio.h>
int main()
{
char*m ;
m="srm";
printf("%d",*m);
return 0;
}
The output is 115. Can someone explain why it gives 115 as output?
*m is the same as m[0], i.e. the first element of the array pointed to by m which is the character 's'.
By using the %d format specifier, you're printing the given argument as an integer. The ASCII value of 's' is 115, which is why you get that value.
If you want to print the string, use the %s format specifier (which expects a char * argument) instead and pass the pointer m.
printf("%s\n", m);
You have a few problems here,
the first one is that you're trying to add three bytes to a char, a char is one byte.
the second problem is that char *m is a pointer to an address and is not a modifiable lvalue. The only time you should use pointers is when you are trying to point to data
example:
char byte = "A"; //WRONG
char byte = 0x61; //OK
char byte = 'A'; //OK
//notice that when setting char byte = "A" you will recieve an error,
//the double quotations is for character arrays where as single quotes,
// are used to identify a char
enter code here
char str[] = "ABCDEF";
char *m = str;
printf("%02x", *m); //you are pointing to str[0]
printf("%02x", *m[1]); //you are pointing to str[1]
printf("%02x", *m[1]); //you are pointing to str[1]
printf("%02x", *(m + 1)); //you are still pointing to str[1]
//m is a pointer to the address in memory calling it like
// *m[1] or *(m + 1) is saying address + one byte
//these examples are the same as calling (more or less)
printf("%02x", str[0]); or
printf("%02x", str[1]);
Pointers and arrays act similarly .Array names are also pointers pointing to the first element of the array.
You have stored "srm" as a character array with m pointing to the first element.
"%d" will give you the ASCII value of the item being pointed by the pointer.
ASCII value of "s" is 115.
if you increment your pointer (m++) then print it's ascii value , output will be ascii value of "r" - 114.
#include <stdio.h>
int main()
{
char *m ;
m="srm";
m++; //pointing to the 2nd element of the array
printf("%d",*m); //output = 114
return 0;
}

Confused about the printing procedure of array of pointers to string

#include<stdio.h>
int main(){
char *names[2] = {"Lord", "Voldemort"};
printf("%s %s\n",names[0], names[1]);
return 0;
}
Why is the above code working? I mean, it should print the addresses of the strings it is containing in their respective indexes and we should be using *names[0] and *names[1]. But why it is working though?
If you had an array of integers like
int values[2] = { 1, 2 };
then what would you get if use used e.g. values[1]? You would get the second element in the array. Printing this values array would be done like
printf("%d %d\n", values[0], values[1]);
You are with me this far?
Now back your array. If you use names[1] what do you get then? You still get the second element in the array. And what is the second element? It is a pointer to char (i.e. char *). And what can a pointer to char be used as? A string.
And the "%s" format with printf expects a string, a char * more specifically. Which is just what you give as arguments.
If you use the dereference operator like *names[1] then thanks to operator precedence it is equal to *(names[1]) which is equal to names[1][0]. In other words it gives you the first character in the string pointed to by names[1].
names[0] and names[1] are both const char* types.
When you use %s with a const char* argument, printf outputs the characters starting at the beginning of the argument, until \0 is reached.
If you want the addresses then use
printf("%p %p\n", (const void*)names[0], (const void*)names[1]);

How to use a pointer to point only at half of an array

I'm new to C and pointers, so i have this problem. I want to tell to pointer how much memory it should point to.
char * pointer;
char arr[] = "Hello";
pointer = arr;
printf("%s \n", pointer);
This pointer will point to whole array, so i will get "Hello" on the screen. My question is how can i make pointer to only get "Hel".
You may try this:
char * pointer;
char arr[] = "Hello";
pointer = arr;
pointer[3] = '\0'; // null terminate of string
printf("%s \n", pointer);
If you always work with strings, then have a look at strlen for getting length of a string. If a string arr has length l, then you may set arr[l/2] = '\0', so that when you print arr, only its first half will be shown.
You may also want to print the last half of your string arr? You can use pointer to point to any place you want as the start. Back to your example, you may try:
char * pointer;
char arr[] = "Hello";
pointer = arr + 2; // point to arr[2]
printf("%s \n", pointer);
Have a check what you will get.
printf has the ability to print less than the full string, using the precision value in the format string. For a fixed number of characters (e.g. 3), it's as simple as
printf( "%.3s\n", pointer );
For a variable number of characters, use an asterisk for the precision, and pass the length before the pointer
int length = 3;
printf( "%.*s\n", length, pointer );
You don't know what a pointer is so I'll explain.
A pointer does not point to a string. It points to a char! Yes, a char. A string in C is really just a set of chars all one after the other in the memory.
A char* pointer points to the beginning of a string. The string ends when there is a '\0' (aka null) char. When you printf("%s",s), what printf does is a cycle like this:
int i;
for(i=0;1;i++) //infinite cycle
{
if(s[i]=='\0')
break;
printf("%c",s[i]);
}
Meaning it will not print a string but all the chars in a char array until it finds a null char or it goes into memory space that is not reserved to it (Segmentation fault).
To print just the 1st 3 characters you could do something like this:
void printString(char* s,int n) //n=number of characters you want to print
{
if(n>strlen(s))
n=strlen(s);
else if(n<0)
return;
char temp=s[n]; //save the character that is in the n'th position of s (counting since 0) so you can restore it later
s[n]='\0'; //put a '\0' where you want the printf to stop printing
printf("%s",s); //print the string until getting to the '\0' that you just put there
s[n]=temp; //restore the character that was there so you don't alter the string
}
Also, your declaration of pointer is unnecessary because it is pointing to the exact same position as arr. You can check this with printf("%p %p\n",arr,pointer);
How much of the string is printed is controlled by the NULL-character "\0", which C automatically appends to every string. If you wish to print out just a portion, either override a character in the string with a "\0", or use the fwrite function or something similar to write just a few bytes to stdout.
You could achieve the objective with a small function, say substring.
#include<stdio.h>
#include<string.h> // for accessing strlen function
void substring(char* c,int len)
{
if (len <= strlen(c)){
*(c+len)='\0';
printf("%s\n",c);
}
else{
printf("Sorry length, %d not allowed\n",len);
}
}
int main(void)
{
char c[]="teststring";
char* ptr=c;
substring(ptr,4); // 4 is where you wish to trim the string.
return 0;
}
Notes:
In C++ a built-in function called substring is already available which shouldn't be confused with this.
When a string is passed to a function like printf using a format specifier %s the function prints all the characters till it reaches a null character or \0. In essence, to trim a string c to 4 characters means you put c[4] to null. Since the count starts from 0, we are actually changing the 5th character though. Hope the example makes it more clear.

Printing an array of characters

I have an array of characters declared as:
char *array[size];
When I perform a
printf("%s", array);
it gives me some garbage characters, why it is so?
http://www.cplusplus.com/reference/clibrary/cstdio/printf/
This url indicates printf takes in the format of: `int printf ( const char * format, ... );
#include <stdio.h>
#include <string.h>
#define size 20
#define buff 100
char line[buff];
int main ()
{
char *array[100];
char *sep = " \t\n";
fgets(line, buff, stdin);
int i;
array[0] = strtok(line, sep);
for (i = 1; i < size; i++) {
array[i] = strtok(NULL, sep);
if (array[i] == NULL)
break;
}
return 0;
}
You declare an array of characters like so:
char foo[size];
You seem to have it mixed up with char *, which is a pointer to a character. You could say
char *bar = foo;
which would make bar point to the contents of foo. (Or, actually, to the first character of foo.)
To then print the contents of the array, you can do one of the following:
// either print directly from foo:
printf("%s", foo);
// or print through bar:
printf("%s", bar);
Note, however, that C performs no initialization of the contents of variables, so unless you specifically set the contents to something, you'll get garbage. In addition, if that garbage doesn't happen to contain a \0; that is, a char with value 0, it will keep on outputting past the end of the array.
Your array is not initialized, and also you have an array of pointers, instead of an array of char's. It should be char* array = (char*)malloc(sizeof(char)*size);, if you want an array of char's. Now you have a pointer to the first element of the array.
Why are we making such a simple thing sound so difficult?
char array[SIZE];
... /* initialize array */
puts(array); /* prints the string/char array and a new line */
/* OR */
printf("%s", array); /* prints the string as is, without a new line */
The char in array after the end of what you want to be your string (ie. if you want your string to read "Hello" that would be the next char after the 'o') must be the terminating NUL character '\0'. If you use a C function to read input that would automatically be appended to the end of your buffer. You would only need to worry about doing it manually if you were individually writing characters to your buffer or something for some reason.
EDIT: As with pmg's comment, the '\0' goes wherever you want the string to end, so if you wanted to shorten your string you could just move it up closer to the front, or to have an empty string you just have array[0] = '\0';. Doing so can also be used to tokenise smaller strings inside a single buffer, just as strtok does. ie. "Part1\0Part2\0Part3\0". But I think this is getting away from the scope of the question.
ie. you wanted to store the first 3 chars of the alphabet as a string (don't know why anyone would do it this way but it's just an example):
char array[4];
array[0] = 'a';
array[1] = 'b';
array[2] = 'c';
array[3] = '\0';
printf("%s\n", array);
If you have something like char array[] = "Hello"; the '\0' is automatically added for you.
char *array[size];
array is not a char * with that, it's more like a char ** (pointer to an array of chars, with is similar to pointer to pointer to char).
If all you need is a C string, either:
char array[size];
and make sure you 0-terminate it properly, or
char *array;
and make sure you properly allocate and free storage for it (and 0-terminate it too).

Resources