Getting element from dynamic two dimensional array - c

Currently, I'm studying c programming language and on the test was a task - Write a function that has two strings as a parameter and need to find and print all unique characters that are present in both strings:
the 'main' function for the test is (and I suspect that all tests are generated using similar function):
int main(void)
{
char *str0 = {"example string", "excelent string"};
solution(2, str0);
return (0);
}
Function should be declared as follow void solution(int size, char **strs);
I don't see any problem to write algorithm. The question is - how to get a second string from **strs?
I tried different approaches just to print second element:
printf("%s", strs[1]);
*strs++;
printf("%s", *strs);
But nothing works.
I guess, that mistake in main function:
Should be something like this: char *str0[] = {"example string", "excelent string"};
Could somebody help - is this mistake in the test and with a provided function to solve this task is impossible or is exist any way to get second string from array?

char *str0 = {"example string", "excelent string"}; is incorrect: it declares a character array, but attempts to define it using array of size 2 containing elements of the type 'character array'. It should be declared as an array of arrays, for example using a fixed size of 2. This works:
#include <stdio.h>
void solution(int size, char **strs)
{
printf("%s\n", strs[0]);
printf("%s\n", strs[1]);
}
int main(void)
{
char *str0[2] = {"example string", "excelent string"};
solution(2, str0);
return 0;
}
I do not consider it a good practice to mix the * and [] pointer notations, but this follows the specifications of the task best, given the definition of the string literal array of size 2.

Continuing from the comment, your brace-initializer {"example string", "excelent string"} is the initializer for an array. (in this case) Specifically in your case, it is the initializer for an array of pointers to String-Literals.
You declare your array and determine the number of elements by:
char *strings[] = { "one", "two" };
size_t nelem = sizeof strings / sizeof *strings;
Once you have your array of pointers, you can pass the array as type char ** because the first level of indirection is converted to a pointer on access. See C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3)
Your function declaration can then be:
void solution (size_t size, char **strs);
and you would invoke your function like:
solution (nelem, strings);
A short example would be:
#include <stdio.h>
void solution (size_t size, char **strs)
{
for (size_t i = 0; i < size; i++)
puts (strs[i]);
}
int main (void) {
char *strings[] = { "one", "two" };
size_t nelem = sizeof strings / sizeof *strings;
solution (nelem, strings);
return 0;
}
(note: while nelem and size can be type int, it is more properly size_t -- though the compiler will allow the result of the division to be assigned to int without warning)
Example Use/Output
Which will iterate over the strings outputting each from the function:
$ ./bin/array_ptrs_init
one
two
Determining Unique Characters
Now for the rest of your task outputting unique characters from both strings, you can include string.h and iterate over the characters in one string calling strchr() to determine if the character is present in the second string. If it is, continue; and get the next char to check, or it it is unique (e.g. strchr() returns NULL), output the character as unique. (this part I leave to you)

char* is the array of chars, that is, char * is string.
And equally, for some type of T, T* is considered as the array of T.
So, you assume that char * is a new type such as
typedef char * STRING;
Then you can understand easily.
#include <stdio.h>
typedef const char * STRING;
void solution(int size, STRING * strings)
{
int i = 0;
for (i = 0; i < size; i++)
{
printf("%s\n", strings[i]);
}
}
int main()
{
STRING strings[2] = { "example string", "excelent string" };
solution(2, strings);
return 0;
}

Related

Best way to initialize an array of strings to pass it to a function

I need to intialize an empty array of strings with fixed size ( 3 by 100 for example), pass it to a function to fill it with data and perform things like strcpy(), strcmp(), memset() on it. After the function is terminated I need to be able to read the data from my main().
What I tried so far:
char arrayofstrings[3][100] = {0};
char (*pointer)[3][100] = &arrayofstrings;
function(pointer);
Initalizing an (empty?) array of strings and initializing a pointer on the first element.
int function (char (*pointer)[3][100])
{
strcpy((*pointer)[i], somepointertostring);
strcmp((*pointer)[i], somepointertostring)
memset((*pointer)[i], 0, strlen((*pointer)[i]));
}
Is this a good way to do it? Is there an easier way to do it? Whats up with the brackets around the pointer?
C string functions expect a buffer to be null-terminated. Your arrayofstrings allocation happens on the stack. Depending on your compiler it might be initialized to all zeros or might contain garbage.
The simplest way in your case to make sure string functions won't overrun your buffers is to set the first character of each to 0 (null)
arrayofstrings[0][0] = 0x00;
arrayofstrings[1][0] = 0x00;
arrayofstrings[2][0] = 0x00;
This will give you 3, 100-char buffers that contain a valid empty "string". Note that you can only store 99 "characters" because the last character must be 0x00 (null-terminator).
char (*pointer)[3][100] = &arrayofstrings;
This is unnecessary.
Something to keep in mind about arrays in C is that the [] index is really only there to make things easier for the human programmer. Any array definition is simply a pointer to memory. The values inside the [][]...[] indexes and the type are used by the compiler to allocate the right amount of memory on the stack and do some simple math to come up with the right memory address for the element you want to access.
char arrayofstrings[3][100];
This will allocate sizeof(char)*3*100 bytes on the stack and give you a char* called 'arrayofstrings'. There's nothing special about the char* itself. It would be the same pointer if you had char arrayofstrings[300] or char arrayofstrings[3][10][10] or even long arrayofstrings[75] (char is 1 byte, long is 4 bytes).
Because you declared it as a multidimensional array with [a][b], when you ask for arrayofstrings[x][y], the compiler will calculate ((x*b)+y)*sizeof(type) and add it to the arrayofstrings pointer to get the address of the value you want. But because it's just a pointer, you can treat it like any other pointer and pass it around or cast it to other types of pointer or do pointer math with it.
You don't need the extra level of indirection.
An array, when passed to a function, is converted to a pointer to its first member. So if you declare the function like this:
int function(char (*pointer)[100])
Or equivalently:
int function(char pointer[][100])
Or:
int function(char pointer[3][100])
You can pass the array directly to the function:
function(arrayofstrings);
Then the body could look something like this:
strcpy(pointer[0], "some string");
strcpy(pointer[1], "some other string");
strcpy(pointer[2], "yet another string");
Best way to initialize an array of strings ...
char arrayofstrings[3][100] = {0}; is fine to initialize an array of strings.
In C, initialization is done only at object definition, like above.
Later code like strcpy(), assigns data to the array.
Best way to ... pass it to a function
When the C compiler supports variable length arrays, use function(size_t n, size_t sz, char a[n][sz]).
Add error checks.
Use size_t for array sizing and indexing.
#define somepointertostring "Hello World"
int function(size_t n, size_t sz, char arrayofstrings[n][sz]) {
if (sz <= strlen(somepointertostring)) {
return 1;
}
for (size_t i = 0; i < n; i++) {
strcpy(arrayofstrings[i], somepointertostring);
if (strcmp(arrayofstrings[i], somepointertostring)) {
return 1;
}
// Drop this it see something interesting in `foo()`
memset(arrayofstrings[i], 0, strlen(arrayofstrings[i]));
}
return 0;
}
void foo(void) {
char arrayofstrings[3][100] = {0};
size_t n = sizeof arrayofstrings / sizeof arrayofstrings[0];
size_t sz = sizeof arrayofstrings[0];
if (function(n, sz, arrayofstrings)) {
puts("Fail");
} else {
puts("Success");
puts(arrayofstrings[0]);
}
}
Initalizing an (empty?) array of strings and initializing a pointer on the first element.
The type of &arrayofstrings is char (*)[3][100] i.e. pointer to an object which is a 2D array of char type with dimension 3 x 100. So, this initialisation
char (*pointer)[3][100] = &arrayofstrings;
is not initialisation of pointer with first element of arrayofstrings array but pointer will point to whole 2D array arrayofstrings. That why, when accessing the elements using pointer you need bracket around it -
`(*pointer)[0]` -> first string
`(*pointer)[1]` -> second string and so on..
Is this a good way to do it? Is there an easier way to do it?
If you want pointer to first element of array arrayofstrings then you can do
char (*p)[100] = &arrayofstrings[0];
Or
char (*p)[100] = arrayofstrings;
both &arrayofstrings[0] and arrayofstrings are equivalent1).
Pass it to a function and access the array:
function() function signature should be -
int function (char (*pointer)[100])
// if you want the function should be aware of number of rows, add a parameter for it -
// int function (char (*pointer)[100], int rows)
this is equivalent to
int function (char pointer[][100])
and call it in from main() function like this -
function (p);
In the function() function you can access array as p[0], p[1] ...:
Sample program for demonstration:
#include <stdio.h>
#include <string.h>
#define ROW 3
#define COL 100
void function (char (*p)[COL]) {
strcpy (p[0], "string one");
strcpy (p[1], "string two");
strcpy (p[2], "string three");
}
int main(void) {
char arrayofstrings[ROW][COL] = {0};
char (*pointer)[COL] = &arrayofstrings[0];
function (pointer);
for (size_t i = 0; i < ROW; ++i) {
printf ("%s\n", arrayofstrings[i]);
}
return 0;
}
When you access an array, it is converted to a pointer to first element (there are few exceptions to this rule).

Passing params to function and casting

I am new to C language and I have some misunderstanding in the following exercise:
void printAllStrings(const char** arr[])
{
while(*arr!=NULL)
{
char** ptr=(char**)*arr;
while(*ptr!=NULL)
{
printf("%s\n",*ptr);
ptr++;
}
arr++;
}
}
int main()
{
char* arrP1[]={"father","mother",NULL};
char* arrP2[]={"sister","brother","grandfather",NULL};
char* arrP3[]={"grandmother",NULL};
char* arrP4[]={"uncle","aunt",NULL};
char** arrPP[]={arrP1,arrP2,arrP3,arrP4,NULL};
printf("Before sort :\n");
printAllStrings(arrPP);
sort(arrPP);
printf("\nAfter sort :\n");
printAllStrings(arrPP);
printf("\nMaximum length string : %s \n",maxLengthString(arrPP));
return 0;
}
The code above prints all strings.
My questions is:
In printAllStrings function the the passed parameter(char** arr[]) array of strings, could we pass pointer on pointer - char** arr.
What the meaning of this row char** ptr=(char**)*arr; I undersatnd that this casting of pointers to char type.
But why the pointer have to be casted is already points to char type?
In printAllStrings function the the passed parameter(char** arr[]) array of strings, could we pass pointer on pointer - char** arr[].
In your examples above, you have char** arr[] and char** arr[] (the two are the same) so your "could we pass?" question is unclear. If you are asking if you could change the parameter to (char ***arr), then yes, you could because the first level of indirection (e.g. [ ]) is converted to a pointer.
What the meaning of this row char** ptr=(char**)*arr; I undersatnd that this casting of pointers to char type. But why the pointer have
to be casted is already points to char type?
The reason is your parameter is const char** arr[] and then you declare char** ptr which discards the const qualifier on arr. const char ** and char ** are not the same. So when you attempt to initialize ptr with the dereferenced arr, e.g. (char** ptr=arr;) the compiler complains about the discard of the const qualifier.
Rather than fixing the problem correctly, e.g.
const char **ptr = *arr;
you "fudge" the initialization to force the discard of the const qualifier -- resulting in ptr not retaining the const type which can prevent the compiler from warning when you attempt to use ptr in a non-constant way (really bad things happen when you just cast away const qualifiers)
I may be wrong -- but it looks like the point of the assignment is to have you preserve the const nature of the string literals you use to initialize your array of pointers. So rather than declaring the arrays as:
char* arrP1[]={"father","mother",NULL};
You should declare them as arrays of const pointers to char, e.g.
const char *arrP1[]={"father","mother",NULL};
Your parameter for printAllStrings then makes sense, and the compiler with warn if you try and do something you are not allowed to do like changing the string literals, e.g. if you try:
arrP1[0][0] = 'l';
(the compiler will throw error: assignment of read-only location ‘*arrP1[0])
If you carry the types consistently through your code, you will not have to "fudge" with any casts anywhere, and the compiler can help protect you from yourself. For example, a simple rework of your types to make sure your string literals are const qualified (while still allowing you to sort your arrays) could be done with something like:
#include <stdio.h>
#include <string.h>
void printAllStrings (const char **arr[])
{
while (*arr != NULL) {
const char **ptr = *arr;
while (*ptr != NULL) {
printf ("%s\n", *ptr);
ptr++;
}
arr++;
}
}
const char *maxLengthString (const char **arr[])
{
size_t max = 0;
const char *longest = NULL;
while (*arr != NULL) {
const char **ptr = *arr;
while (*ptr != NULL) {
size_t len = strlen (*ptr);
if (len > max) {
max = len;
longest = *ptr;
}
ptr++;
}
arr++;
}
return longest;
}
int main (void) {
const char *arrP1[] = {"father", "mother", NULL};
const char *arrP2[] = {"sister", "brother", "grandfather", NULL};
const char *arrP3[] = {"grandmother", NULL};
const char *arrP4[] = {"uncle", "aunt", NULL};
const char **arrPP[] = {arrP1, arrP2, arrP3, arrP4, NULL};
printf ("Before sort :\n");
printAllStrings (arrPP);
// sort (arrPP); /* you didn't post sort, so the following swaps */
const char **tmp = arrPP[0]; /* simple swap example */
arrPP[0] = arrPP[1];
arrPP[1] = tmp;
printf ("\nAfter sort :\n");
printAllStrings (arrPP);
printf ("\nMaximum length string : %s \n", maxLengthString (arrPP));
return 0;
}
(You didn't post sort(), so above the elements a simply swapped to show your arrPP retains the ability to be sorted, and a quick implementation of the maxLengthString () was added to make your last statement work -- but note, it just finds the first of any longest strings if more than one are the same length)
Example Use/Output
$ ./bin/array_ptp_const_char
Before sort :
father
mother
sister
brother
grandfather
grandmother
uncle
aunt
After sort :
sister
brother
grandfather
father
mother
grandmother
uncle
aunt
Maximum length string : grandfather
Look things over and let me know if you have further questions. I'm not sure if this is what you were looking for, but based on your code and questions, it seemed the most logical choice.
I can only answer the 2nd question as I can not understand the 1st the way it is now.
char** ptr=(char**)*arr;
// this is the same but maybe confusing because arr is a pointer now and it gets iterated in the loop.
char** ptr=(char**)arr[0];
arrhas the type pointer (decayed from an array) to pointer to pointer to char.
ptrhas the type pointer to pointer to char.
As you can see ptr has one level of reference less than arr. arrholds all the pointers to your declared arrays of type pointer to char. (arrP1, arrP2, arrP3, arrP4).
By dereferencing arr you get the pointer to one of these arrays.(arrP1 in the first iteration)
Then you print where the pointer stored in ptr[0] points to and iterate to ptr[1], to print this. After the loop arrgets iterated and yields the pointer to arrP2 and you start again with the ptr-loop.
You have to keep in mind that arrays and pointers are quite similar(but not exactly the same) in their usage and passing an array to function lets it decay to a pointer.
Edit: David's answer is great, I misread the focus of the 2nd question, so this answer is a bit offtopic. I will leave it here, because I think it still helps understanding what happens with all the pointer magic. For a relevant answer especially about const correctness David's answer is the one.

How to copy a char array in C?

In C, I have two char arrays:
char array1[18] = "abcdefg";
char array2[18];
How to copy the value of array1 to array2 ? Can I just do this: array2 = array1?
You can't directly do array2 = array1, because in this case you manipulate the addresses of the arrays (char *) and not of their inner values (char).
What you, conceptually, want is to do is iterate through all the chars of your source (array1) and copy them to the destination (array2). There are several ways to do this. For example you could write a simple for loop, or use memcpy.
That being said, the recommended way for strings is to use strncpy. It prevents common errors resulting in, for example, buffer overflows (which is especially dangerous if array1 is filled from user input: keyboard, network, etc). Like so:
// Will copy 18 characters from array1 to array2
strncpy(array2, array1, 18);
As #Prof. Falken mentioned in a comment, strncpy can be evil. Make sure your target buffer is big enough to contain the source buffer (including the \0 at the end of the string).
If your arrays are not string arrays, use:
memcpy(array2, array1, sizeof(array2));
If you want to guard against non-terminated strings, which can cause all sorts of problems, copy your string like this:
char array1[18] = {"abcdefg"};
char array2[18];
size_t destination_size = sizeof (array2);
strncpy(array2, array1, destination_size);
array2[destination_size - 1] = '\0';
That last line is actually important, because strncpy() does not always null terminate strings. (If the destination buffer is too small to contain the whole source string, sntrcpy() will not null terminate the destination string.)
The manpage for strncpy() even states "Warning: If there is no null byte among the first n bytes of src, the string placed in dest will not be null-terminated."
The reason strncpy() behaves this somewhat odd way, is because it was not actually originally intended as a safe way to copy strings.
Another way is to use snprintf() as a safe replacement for strcpy():
snprintf(array2, destination_size, "%s", array1);
(Thanks jxh for the tip.)
As others have noted, strings are copied with strcpy() or its variants. In certain cases, you could use snprintf() as well.
You can only assign arrays the way you want as part of a structure assignment:
typedef struct { char a[18]; } array;
array array1 = { "abcdefg" };
array array2;
array2 = array1;
If your arrays are passed to a function, it will appear that you are allowed to assign them, but this is just an accident of the semantics. In C, an array will decay to a pointer type with the value of the address of the first member of the array, and this pointer is what gets passed. So, your array parameter in your function is really just a pointer. The assignment is just a pointer assignment:
void foo (char x[10], char y[10]) {
x = y; /* pointer assignment! */
puts(x);
}
The array itself remains unchanged after returning from the function.
This "decay to pointer value" semantic for arrays is the reason that the assignment doesn't work. The l-value has the array type, but the r-value is the decayed pointer type, so the assignment is between incompatible types.
char array1[18] = "abcdefg";
char array2[18];
array2 = array1; /* fails because array1 becomes a pointer type,
but array2 is still an array type */
As to why the "decay to pointer value" semantic was introduced, this was to achieve a source code compatibility with the predecessor of C. You can read The Development of the C Language for details.
You cannot assign arrays, the names are constants that cannot be changed.
You can copy the contents, with:
strcpy(array2, array1);
assuming the source is a valid string and that the destination is large enough, as in your example.
it should look like this:
void cstringcpy(char *src, char * dest)
{
while (*src) {
*(dest++) = *(src++);
}
*dest = '\0';
}
.....
char src[6] = "Hello";
char dest[6];
cstringcpy(src, dest);
I recommend to use memcpy() for copying data.
Also if we assign a buffer to another as array2 = array1 , both array have same memory and any change in the arrary1 deflects in array2 too. But we use memcpy, both buffer have different array. I recommend memcpy() because strcpy and related function do not copy NULL character.
array2 = array1;
is not supported in c. You have to use functions like strcpy() to do it.
c functions below only ... c++ you have to do char array then use a string copy then user the string tokenizor functions... c++ made it a-lot harder to do anythng
#include <iostream>
#include <fstream>
#include <cstring>
#define TRUE 1
#define FALSE 0
typedef int Bool;
using namespace std;
Bool PalTrueFalse(char str[]);
int main(void)
{
char string[1000], ch;
int i = 0;
cout<<"Enter a message: ";
while((ch = getchar()) != '\n') //grab users input string untill
{ //Enter is pressed
if (!isspace(ch) && !ispunct(ch)) //Cstring functions checking for
{ //spaces and punctuations of all kinds
string[i] = tolower(ch);
i++;
}
}
string[i] = '\0'; //hitting null deliminator once users input
cout<<"Your string: "<<string<<endl;
if(PalTrueFalse(string)) //the string[i] user input is passed after
//being cleaned into the null function.
cout<<"is a "<<"Palindrome\n"<<endl;
else
cout<<"Not a palindrome\n"<<endl;
return 0;
}
Bool PalTrueFalse(char str[])
{
int left = 0;
int right = strlen(str)-1;
while (left<right)
{
if(str[left] != str[right]) //comparing most outer values of string
return FALSE; //to inner values.
left++;
right--;
}
return TRUE;
}
Well, techincally you can…
typedef struct { char xx[18]; } arr_wrap;
char array1[18] = "abcdefg";
char array2[18];
*((arr_wrap *) array2) = *((arr_wrap *) array1);
printf("%s\n", array2); /* "abcdefg" */
but it will not look very beautiful.
…Unless you use the C preprocessor…
#define CC_MEMCPY(DESTARR, SRCARR, ARRSIZE) \
{ struct _tmparrwrap_ { char xx[ARRSIZE]; }; *((struct _tmparrwrap_ *) DESTARR) = *((struct _tmparrwrap_ *) SRCARR); }
You can then do:
char array1[18] = "abcdefg";
char array2[18];
CC_MEMCPY(array2, array1, sizeof(array1));
printf("%s\n", array2); /* "abcdefg" */
And it will work with any data type, not just char:
int numbers1[3] = { 1, 2, 3 };
int numbers2[3];
CC_MEMCPY(numbers2, numbers1, sizeof(numbers1));
printf("%d - %d - %d\n", numbers2[0], numbers2[1], numbers2[2]); /* "abcdefg" */
(Yes, the code above is granted to work always and it's portable)
for integer types
#include <string.h>
int array1[10] = {0,1,2,3,4,5,6,7,8,9};
int array2[10];
memcpy(array2,array1,sizeof(array1)); // memcpy("destination","source","size")
You cannot assign arrays to copy them. How you can copy the contents of one into another depends on multiple factors:
For char arrays, if you know the source array is null terminated and destination array is large enough for the string in the source array, including the null terminator, use strcpy():
#include <string.h>
char array1[18] = "abcdefg";
char array2[18];
...
strcpy(array2, array1);
If you do not know if the destination array is large enough, but the source is a C string, and you want the destination to be a proper C string, use snprinf():
#include <stdio.h>
char array1[] = "a longer string that might not fit";
char array2[18];
...
snprintf(array2, sizeof array2, "%s", array1);
If the source array is not necessarily null terminated, but you know both arrays have the same size, you can use memcpy:
#include <string.h>
char array1[28] = "a non null terminated string";
char array2[28];
...
memcpy(array2, array1, sizeof array2);
None of the above was working for me..
this works perfectly
name here is char *name which is passed via the function
get length of char *name using strlen(name)
storing it in a const variable is important
create same length size char array
copy name 's content to temp using strcpy(temp, name);
use however you want, if you want original content back. strcpy(name, temp); copy temp back to name and voila works perfectly
const int size = strlen(name);
char temp[size];
cout << size << endl;
strcpy(temp, name);
You can't copy directly by writing array2 = array1.
If you want to copy it manually, iterate over array1 and copy item by item as follows -
int i;
for(i=0;array1[i]!='\0';i++){
array2[i] = array1[i];
}
array2[i]='\0'; //put the string terminator too
If you are ok to use string library, you can do it as follows -
strncpy ( array2, array1, sizeof(array2) );

Problem with processing individual strings stored in an array of pointers to multiple strings in C

An array of pointers to strings is provided as the input. The task is to reverse each string stored in the input array of pointers. I've made a function called reverseString() which reverses the string passed to it. This functions works correctly as far as i know.
The strings stored/referenced in the input array of pointers are sent one by one to the reverseString() function. But the code hangs at some point in the reverseString() function when the values of the passed string are swapped using a temp variable. I can't figure out why the code is hanging while swapping values. Please help me with this.
The code is as follows:
#include <stdio.h>
void reverseString(char*);
int main()
{ char *s[] = {"abcde", "12345", "65gb"};
int i=0;
for(i=0; i< (sizeof(s)/sizeof(s[0]) ); i++ )
{ reverseString(s[i]);
printf("\n%s\n", s[i]);
}
getch();
return 0;
}//end main
void reverseString(char *x)
{ int len = strlen(x)-1;
int i=0;
char temp;
while(i <= len-i)
{ temp = x[i];
x[i] = x[len-i];
x[len-i] = temp;
i++;
}
}//end reverseString
You are trying to change string literals.
String literals are usually not modifiable, and really should be declared as const.
const char *s[] = {"abcde", "12345", "65gb"};
/* pointers to string literals */
If you want to make an array of modifiable strings, try this:
char s[][24] = {"abcde", "12345", "65gb"};
/* non-readonly array initialized from string literals */
The compiler will automatically determine you need 3 strings, but it can't determine how long each needs to be. I've made them 24 bytes long.
The strings ("abcde" etc) could be stored in readonly memory. Anything is possible when you try to modify those strings, therefore. The pointers to the strings are modifiable; it is just the strings themselves that are not.
You should include <string.h> to obtain the declaration of strlen(3), and another header to obtain the function getch() - it is not in <stdio.h> on my MacOS X system (so I deleted the call; it is probably declared in either <stdio.h> or <conio.h> on Windows).
Hope this helps you! what i am doing here is that i am going to the address of the last character in the string then printing them all by decreasing the pointer by 1 unit (for character its 2 bytes(please check)).
//program to reverse the strings in an array of pointers
#include<stdio.h>
#include<string.h>
int main()
{
char *str[] = {
"to err is human....",
"But to really mess things up...",
"One needs to know C!!"
};
int i=0; //for different strings
char *p; //declaring a pointer whose value i will be setting to the last character in
//the respective string
while(i<3)
{
p=str[i]+strlen(str[i])-1;
while(*p!='\0')
{
printf("%c",*p);
p--;
}
printf("\n");
i++;
}
}

How do I create an array of strings in C?

I am trying to create an array of strings in C. If I use this code:
char (*a[2])[14];
a[0]="blah";
a[1]="hmm";
gcc gives me "warning: assignment from incompatible pointer type". What is the correct way to do this?
edit: I am curious why this should give a compiler warning since if I do printf(a[1]);, it correctly prints "hmm".
If you don't want to change the strings, then you could simply do
const char *a[2];
a[0] = "blah";
a[1] = "hmm";
When you do it like this you will allocate an array of two pointers to const char. These pointers will then be set to the addresses of the static strings "blah" and "hmm".
If you do want to be able to change the actual string content, the you have to do something like
char a[2][14];
strcpy(a[0], "blah");
strcpy(a[1], "hmm");
This will allocate two consecutive arrays of 14 chars each, after which the content of the static strings will be copied into them.
There are several ways to create an array of strings in C. If all the strings are going to be the same length (or at least have the same maximum length), you simply declare a 2-d array of char and assign as necessary:
char strs[NUMBER_OF_STRINGS][STRING_LENGTH+1];
...
strcpy(strs[0], aString); // where aString is either an array or pointer to char
strcpy(strs[1], "foo");
You can add a list of initializers as well:
char strs[NUMBER_OF_STRINGS][STRING_LENGTH+1] = {"foo", "bar", "bletch", ...};
This assumes the size and number of strings in the initializer match up with your array dimensions. In this case, the contents of each string literal (which is itself a zero-terminated array of char) are copied to the memory allocated to strs. The problem with this approach is the possibility of internal fragmentation; if you have 99 strings that are 5 characters or less, but 1 string that's 20 characters long, 99 strings are going to have at least 15 unused characters; that's a waste of space.
Instead of using a 2-d array of char, you can store a 1-d array of pointers to char:
char *strs[NUMBER_OF_STRINGS];
Note that in this case, you've only allocated memory to hold the pointers to the strings; the memory for the strings themselves must be allocated elsewhere (either as static arrays or by using malloc() or calloc()). You can use the initializer list like the earlier example:
char *strs[NUMBER_OF_STRINGS] = {"foo", "bar", "bletch", ...};
Instead of copying the contents of the string constants, you're simply storing the pointers to them. Note that string constants may not be writable; you can reassign the pointer, like so:
strs[i] = "bar";
strs[i] = "foo";
But you may not be able to change the string's contents; i.e.,
strs[i] = "bar";
strcpy(strs[i], "foo");
may not be allowed.
You can use malloc() to dynamically allocate the buffer for each string and copy to that buffer:
strs[i] = malloc(strlen("foo") + 1);
strcpy(strs[i], "foo");
BTW,
char (*a[2])[14];
Declares a as a 2-element array of pointers to 14-element arrays of char.
Ack! Constant strings:
const char *strings[] = {"one","two","three"};
If I remember correctly.
Oh, and you want to use strcpy for assignment, not the = operator. strcpy_s is safer, but it's neither in C89 nor in C99 standards.
char arr[MAX_NUMBER_STRINGS][MAX_STRING_SIZE];
strcpy(arr[0], "blah");
Update: Thomas says strlcpy is the way to go.
Here are some of your options:
char a1[][14] = { "blah", "hmm" };
char* a2[] = { "blah", "hmm" };
char (*a3[])[] = { &"blah", &"hmm" }; // only since you brought up the syntax -
printf(a1[0]); // prints blah
printf(a2[0]); // prints blah
printf(*a3[0]); // prints blah
The advantage of a2 is that you can then do the following with string literals
a2[0] = "hmm";
a2[1] = "blah";
And for a3 you may do the following:
a3[0] = &"hmm";
a3[1] = &"blah";
For a1 you will have to use strcpy() (better yet strncpy()) even when assigning string literals. The reason is that a2, and a3 are arrays of pointers and you can make their elements (i.e. pointers) point to any storage, whereas a1 is an array of 'array of chars' and so each element is an array that "owns" its own storage (which means it gets destroyed when it goes out of scope) - you can only copy stuff into its storage.
This also brings us to the disadvantage of using a2 and a3 - since they point to static storage (where string literals are stored) the contents of which cannot be reliably changed (viz. undefined behavior), if you want to assign non-string literals to the elements of a2 or a3 - you will first have to dynamically allocate enough memory and then have their elements point to this memory, and then copy the characters into it - and then you have to be sure to deallocate the memory when done.
Bah - I miss C++ already ;)
p.s. Let me know if you need examples.
If you don't want to keep track of number of strings in array and want to iterate over them, just add NULL string in the end:
char *strings[]={ "one", "two", "three", NULL };
int i=0;
while(strings[i]) {
printf("%s\n", strings[i]);
//do something
i++;
};
Or you can declare a struct type, that contains a character arry(1 string), them create an array of the structs and thus a multi-element array
typedef struct name
{
char name[100]; // 100 character array
}name;
main()
{
name yourString[10]; // 10 strings
printf("Enter something\n:);
scanf("%s",yourString[0].name);
scanf("%s",yourString[1].name);
// maybe put a for loop and a few print ststements to simplify code
// this is just for example
}
One of the advantages of this over any other method is that this allows you to scan directly into the string without having to use strcpy;
If the strings are static, you're best off with:
const char *my_array[] = {"eenie","meenie","miney"};
While not part of basic ANSI C, chances are your environment supports the syntax. These strings are immutable (read-only), and thus in many environments use less overhead than dynamically building a string array.
For example in small micro-controller projects, this syntax uses program memory rather than (usually) more precious ram memory. AVR-C is an example environment supporting this syntax, but so do most of the other ones.
In ANSI C:
char* strings[3];
strings[0] = "foo";
strings[1] = "bar";
strings[2] = "baz";
The string literals are const char *s.
And your use of parenthesis is odd. You probably mean
const char *a[2] = {"blah", "hmm"};
which declares an array of two pointers to constant characters, and initializes them to point at two hardcoded string constants.
Your code is creating an array of function pointers. Try
char* a[size];
or
char a[size1][size2];
instead.
See wikibooks to arrays and pointers
hello you can try this bellow :
char arr[nb_of_string][max_string_length];
strcpy(arr[0], "word");
a nice example of using, array of strings in c if you want it
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]){
int i, j, k;
// to set you array
//const arr[nb_of_string][max_string_length]
char array[3][100];
char temp[100];
char word[100];
for (i = 0; i < 3; i++){
printf("type word %d : ",i+1);
scanf("%s", word);
strcpy(array[i], word);
}
for (k=0; k<3-1; k++){
for (i=0; i<3-1; i++)
{
for (j=0; j<strlen(array[i]); j++)
{
// if a letter ascii code is bigger we swap values
if (array[i][j] > array[i+1][j])
{
strcpy(temp, array[i+1]);
strcpy(array[i+1], array[i]);
strcpy(array[i], temp);
j = 999;
}
// if a letter ascii code is smaller we stop
if (array[i][j] < array[i+1][j])
{
j = 999;
}
}
}
}
for (i=0; i<3; i++)
{
printf("%s\n",array[i]);
}
return 0;
}
char name[10][10]
int i,j,n;//here "n" is number of enteries
printf("\nEnter size of array = ");
scanf("%d",&n);
for(i=0;i<n;i++)
{
for(j=0;j<1;j++)
{
printf("\nEnter name = ");
scanf("%s",&name[i]);
}
}
//printing the data
for(i=0;i<n;i++)
{
for(j=0;j<1;j++)
{
printf("%d\t|\t%s\t|\t%s",rollno[i][j],name[i],sex[i]);
}
printf("\n");
}
Here try this!!!
I was missing somehow more dynamic array of strings, where amount of strings could be varied depending on run-time selection, but otherwise strings should be fixed.
I've ended up of coding code snippet like this:
#define INIT_STRING_ARRAY(...) \
{ \
char* args[] = __VA_ARGS__; \
ev = args; \
count = _countof(args); \
}
void InitEnumIfAny(String& key, CMFCPropertyGridProperty* item)
{
USES_CONVERSION;
char** ev = nullptr;
int count = 0;
if( key.Compare("horizontal_alignment") )
INIT_STRING_ARRAY( { "top", "bottom" } )
if (key.Compare("boolean"))
INIT_STRING_ARRAY( { "yes", "no" } )
if( ev == nullptr )
return;
for( int i = 0; i < count; i++)
item->AddOption(A2T(ev[i]));
item->AllowEdit(FALSE);
}
char** ev picks up pointer to array strings, and count picks up amount of strings using _countof function. (Similar to sizeof(arr) / sizeof(arr[0])).
And there is extra Ansi to unicode conversion using A2T macro, but that might be optional for your case.
Each element is a pointer to its first character
const char *a[2] = {"blah", "hmm"};
A good way is to define a string your self.
#include <stdio.h>
typedef char string[]
int main() {
string test = "string";
return 0;
}
It's really that simple.

Resources