I have an array of 10 strings of length at most 20 that I'm building up
char buffer[10][20] = {0};
//populate the buffer with 10 strings
//after this point, no more changes to the buffer allowed
//make a new pointer to indicate that I want the buffer finalized
const char **finalized = buffer;
But the previous fails with the warning
warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
Doing something similar with a single string works
char buffer[20] = {0};
//populate the buffer
const char *finalized = buffer;
What is the proper way to cast in the first case?
It is impossible to "cast" a regular 2D array to a pointer-to-pointer type. These types are completely incompatible and have completely different semantics. You can force the cast, but the result will be useless anyway.
Formally, the proper pointer type in this case is char (*)[20]
char (*finalized)[20] = buffer;
except that const-correctness rules of C language won't allow you to add a const there. You can force it though
const char (*finalized)[20] = (const char (*)[20]) buffer;
You can also do
char (*finalized)[10][20] = &buffer;
Whether this is of any use to you - I don't know since you do not provide any details about what's that for.
If you have a 2D array, you cannot simply convert it to a pointer to pointer. pointers and arrays are not the same.
If you want strings of at more length 19, then you need to make the number of strings flexible in this case, using char (*)[20], as pointed out by #AnT.
Note: using 20 as a dimension means that you can have at most 19 characters, because one space must occupy the null terminating character \0.
Here is an example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STRLEN 20
#define NUMSTR 10
int main(void) {
char buffer[NUMSTR][STRLEN];
strcpy(buffer[0], "Hello");
strcpy(buffer[1], "World");
char (*finalized)[STRLEN] = buffer;
printf("%s %s!\n", finalized[0], finalized[1]);
return 0;
}
So basically strcpy assigns the address of the 2nd argument to the 1st, but how does it do it with an array as the first argument? like in my program, i tried changing the address of the array but unfortunately it wont compile. So I had to resort to making a character pointer variable to assign the return value of capitalize. Is there something I'm misunderstanding?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char string[20];
char *Capitalize(char *str)
{
int i;
char *temp;
temp = malloc(sizeof(char)*(int)(strlen(str)+1));
for(i = 0;i < strlen(str);i++)
{
if(*(str+i) >= 'a' && *(str+i)<= 'z')
*(temp+i) = *(str+i) - 32;
else
*(temp+i) = *(str+i);
}
*(temp+i) = '\0';
return temp;
}
int main(void)
{
string word;
printf("Enter word to capitalize: ");
scanf("%19s",word);
word = Capitalize(word);
printf("%s",word);
return 0;
}
strcpy() makes a copy, just like the name implies. it's perfectly legal to copy a string in to an array.
When you make an initialization of an array such as:
char myarr[] = "hello";
You're actually copying the characters into the array.
You seem to be confusing arrays with pointers (see here for some reason you can't treat them the same)
In C, qualifying an array by name without an indexer, is equivalent to specifying a pointer to the memory address of the first element in the array, that is why you can pass as a parameter an array to functions like strcpy.
char * strcpy ( char * destination, const char * source );
strcpy will copy whatever series of characters are found, starting at memory address specified by source, to the memory address specified by destination, until a null character (0) is found (this null character is also copied to the destination buffer).
The address values specified in the parameters are not modified, they just specify from where in memory to copy and where to. It is important that destination is pointing to a memory buffer (can be a char array or a block of memory requested via malloc) with enough capacity for the copied string to fit, otherwise a buffer underrun will occur (you will write characters past the end of your buffer) and your program might crash or behave in a weird way.
Hope I have been clear and not confused you more with my explanation ;)
The thing you seem to be missing is that in c/c++ strings ARE arrays, in most practical respects declaring
char c[] = "hello";
and
char* c = "hello";
is the same thing, all strcpy does is copy the characters into the destination memory, whether that memory is allocated as an array (presumably on the stack) or pointer (presumably on the heap);it does not make a difference.
how to implement the string handling functions. is it necessary to include any libraries. give example on string concatenation
main()
{
char a,b
a='A';
b='B';
strcat(b,a);
printf("a:%s b:%s",a,b);
}
The char type only holds a single character. To hold a string, you need an array of characters. In C, arrays are fixed in size, so the programmer must ensure that a character array has enough space to hold the string you want to put in it.
#include <stdio.h> //for printf
#include <string.h> //for strncat
#define A_SIZE 10
int main(void)
{
char a[A_SIZE] = "A";
char b[] = "B";
strncat(a, b, A_SIZE - strlen(a) - 1);
printf("a:%s b:%s\n", a, b);
}
You can start by learning basic C (especially pointers, arrays, and managing memory with malloc).
http://en.wikipedia.org/wiki/Strcat
This is my first time posting here, hopefully I will not make a fool of myself.
I am trying to use a function to allocate memory to a pointer, copy text to the buffer, and then change a character. I keep getting a segfault and have tried looking up the answer, my syntax is probably wrong, I could use some enlightenment.
/* My objective is to pass a buffer to my Copy function, allocate room, and copy text to it. Then I want to modify the text and print it.*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int Copy(char **Buffer, char *Text);
int main()
{
char *Text = malloc(sizeof(char) * 100);
char *Buffer;
strncpy(Text, "1234567890\n", 100);
Copy(&Buffer, Text);
}
int Copy(char **Buffer, char *Text)
{
int count;
count = strlen(Text)+1;
*Buffer = malloc(sizeof(char) * count);
strncpy(*Buffer, Text, 5);
*Buffer[2] = 'A'; /* This results in a segfault. "*Buffer[1] = 'A';" results in no differece in the output. */
printf("%s\n", *Buffer);
}
Your problem is simply one of precedence. The [] operator has higher precendence that unary-*, so the line is parsed as if it was:
*(Buffer[2]) = 'A';
...which is not what you want. You actually want the * to happen first, so you need to use parantheses:
(*Buffer)[2] = 'A';
Additionally, your strncpy() call is wrong. strncpy() does not nul-terminate the result if the number of characters copied is equal to the length; and since your memory comes straight from malloc(), there may not be a nul-terminator there already. strncpy() is actually the wrong tool in 99.99% of the cases that you will encounter - search on this site for numerous other answers explaining why.
A call to strncat() can be used instead:
(*Buffer)[0] = '\0'; /* Truncate to an empty string */
strncat(*Buffer, Text, 5);
*Buffer[2] is getting interpreted as *(Buffer[2]). What you want is (*Buffer)[2].
The problem is that *Buffer[2] means *(Buffer[2]) - you're trying to dereference the wrong pointer. You want to use (*Buffer)[2].
I have a string:
char * someString;
If I want the first five letters of this string and want to set it to otherString, how would I do it?
#include <string.h>
...
char otherString[6]; // note 6, not 5, there's one there for the null terminator
...
strncpy(otherString, someString, 5);
otherString[5] = '\0'; // place the null terminator
Generalized:
char* subString (const char* input, int offset, int len, char* dest)
{
int input_len = strlen (input);
if (offset + len > input_len)
{
return NULL;
}
strncpy (dest, input + offset, len);
return dest;
}
char dest[80];
const char* source = "hello world";
if (subString (source, 0, 5, dest))
{
printf ("%s\n", dest);
}
char* someString = "abcdedgh";
char* otherString = 0;
otherString = (char*)malloc(5+1);
memcpy(otherString,someString,5);
otherString[5] = 0;
UPDATE:
Tip: A good way to understand definitions is called the right-left rule (some links at the end):
Start reading from identifier and say aloud => "someString is..."
Now go to right of someString (statement has ended with a semicolon, nothing to say).
Now go left of identifier (* is encountered) => so say "...a pointer to...".
Now go to left of "*" (the keyword char is found) => say "..char".
Done!
So char* someString; => "someString is a pointer to char".
Since a pointer simply points to a certain memory address, it can also be used as the "starting point" for an "array" of characters.
That works with anything .. give it a go:
char* s[2]; //=> s is an array of two pointers to char
char** someThing; //=> someThing is a pointer to a pointer to char.
//Note: We look in the brackets first, and then move outward
char (* s)[2]; //=> s is a pointer to an array of two char
Some links:
How to interpret complex C/C++ declarations and
How To Read C Declarations
You'll need to allocate memory for the new string otherString. In general for a substring of length n, something like this may work for you (don't forget to do bounds checking...)
char *subString(char *someString, int n)
{
char *new = malloc(sizeof(char)*n+1);
strncpy(new, someString, n);
new[n] = '\0';
return new;
}
This will return a substring of the first n characters of someString. Make sure you free the memory when you are done with it using free().
You can use snprintf to get a substring of a char array with precision:
#include <stdio.h>
int main()
{
const char source[] = "This is a string array";
char dest[17];
// get first 16 characters using precision
snprintf(dest, sizeof(dest), "%.16s", source);
// print substring
puts(dest);
} // end main
Output:
This is a string
Note:
For further information see printf man page.
You can treat C strings like pointers. So when you declare:
char str[10];
str can be used as a pointer. So if you want to copy just a portion of the string you can use:
char str1[24] = "This is a simple string.";
char str2[6];
strncpy(str1 + 10, str2,6);
This will copy 6 characters from the str1 array into str2 starting at the 11th element.
I had not seen this post until now, the present collection of answers form an orgy of bad advise and compiler errors, only a few recommending memcpy are correct. Basically the answer to the question is:
someString = allocated_memory; // statically or dynamically
memcpy(someString, otherString, 5);
someString[5] = '\0';
This assuming that we know that otherString is at least 5 characters long, then this is the correct answer, period. memcpy is faster and safer than strncpy and there is no confusion about whether memcpy null terminates the string or not - it doesn't, so we definitely have to append the null termination manually.
The main problem here is that strncpy is a very dangerous function that should not be used for any purpose. The function was never intended to be used for null terminated strings and it's presence in the C standard is a mistake. See Is strcpy dangerous and what should be used instead?, I will quote some relevant parts from that post for convenience:
Somewhere at the time when Microsoft flagged strcpy as obsolete and dangerous, some other misguided rumour started. This nasty rumour said that strncpy should be used as a safer version of strcpy. Since it takes the size as parameter and it's already part of the C standard lib, so it's portable. This seemed very convenient - spread the word, forget about non-standard strcpy_s, lets use strncpy! No, this is not a good idea...
Looking at the history of strncpy, it goes back to the very earliest days of Unix, where several string formats co-existed. Something called "fixed width strings" existed - they were not null terminated but came with a fixed size stored together with the string. One of the things Dennis Ritchie (the inventor of the C language) wished to avoid when creating C, was to store the size together with arrays [The Development of the C Language, Dennis M. Ritchie]. Likely in the same spirit as this, the "fixed width strings" were getting phased out over time, in favour for null terminated ones.
The function used to copy these old fixed width strings was named strncpy. This is the sole purpose that it was created for. It has no relation to strcpy. In particular it was never intended to be some more secure version - computer program security wasn't even invented when these functions were made.
Somehow strncpy still made it into the first C standard in 1989. A whole lot of highly questionable functions did - the reason was always backwards compatibility. We can also read the story about strncpy in the C99 rationale 7.21.2.4:
The strncpy function
strncpy was initially introduced into the C library to deal with fixed-length name fields in
structures such as directory entries. Such fields are not used in the same way as strings: the
trailing null is unnecessary for a maximum-length field, and setting trailing bytes for shorter
5 names to null assures efficient field-wise comparisons. strncpy is not by origin a “bounded
strcpy,” and the Committee preferred to recognize existing practice rather than alter the function
to better suit it to such use.
The Codidact link also contains some examples showing how strncpy will fail to terminate a copied string.
I think it's easy way... but I don't know how I can pass the result variable directly then I create a local char array as temp and return it.
char* substr(char *buff, uint8_t start,uint8_t len, char* substr)
{
strncpy(substr, buff+start, len);
substr[len] = 0;
return substr;
}
strncpy(otherString, someString, 5);
Don't forget to allocate memory for otherString.
#include <stdio.h>
#include <string.h>
int main ()
{
char someString[]="abcdedgh";
char otherString[]="00000";
memcpy (otherString, someString, 5);
printf ("someString: %s\notherString: %s\n", someString, otherString);
return 0;
}
You will not need stdio.h if you don't use the printf statement and putting constants in all but the smallest programs is bad form and should be avoided.
Doing it all in two fell swoops:
char *otherString = strncpy((char*)malloc(6), someString);
otherString[5] = 0;
char largeSrt[] = "123456789-123"; // original string
char * substr;
substr = strchr(largeSrt, '-'); // we save the new string "-123"
int substringLength = strlen(largeSrt) - strlen(substr); // 13-4=9 (bigger string size) - (new string size)
char *newStr = malloc(sizeof(char) * substringLength + 1);// keep memory free to new string
strncpy(newStr, largeSrt, substringLength); // copy only 9 characters
newStr[substringLength] = '\0'; // close the new string with final character
printf("newStr=%s\n", newStr);
free(newStr); // you free the memory
Try this code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char* substr(const char *src, unsigned int start, unsigned int end);
int main(void)
{
char *text = "The test string is here";
char *subtext = substr(text,9,14);
printf("The original string is: %s\n",text);
printf("Substring is: %s",subtext);
return 0;
}
char* substr(const char *src, unsigned int start, unsigned int end)
{
unsigned int subtext_len = end-start+2;
char *subtext = malloc(sizeof(char)*subtext_len);
strncpy(subtext,&src[start],subtext_len-1);
subtext[subtext_len-1] = '\0';
return subtext;
}