char sXSongBuffer[20][30];
sXSongBuffer = {"Thriller", "Don't Stop Till You Get Enough", "Billy Jean"};
Why does this return the error expected expression before ‘{’ token? The reason I want to initialize my array like this is so that I can change its contents like this later:
sXSongBuffer = {"New Song", "More Music From Me"};
You can't assign to arrays in C. C allows initializing arrays with values that are compile-time constants. If you want to change the values later, or set values that are not compile-time constants, you must assign to a particular index of the array manually.
So, your assignment to sXSongBuffer is disallowed in C. Moreover, since sXSongBuffer[0] to sXSongBuffer[19] are arrays too, you can't even say: sXSongBuffer[0] = "New Song";
Depending upon what you want, this may work for you:
/* declare sXSongBuffer as an array of pointers */
char *sXSongBuffer[30] = {
"Thriller",
"Don't Stop Till You Get Enough",
"Billy Jean",
NULL /* set the rest of the elements to NULL */
};
size_t i;
/* and then later in your code */
sXSongBuffer[0] = "New Song";
sXSongBuffer[1] = "More Music From Me";
for (i=2; i < sizeof sXSongBuffer; ++i)
sXSongBuffer[i] = NULL;
But the above only works if you know all your strings at compile time. If not, you will have to decide if you want "big-enough" arrays, or if you need dynamic memory for the strings and/or the number of strings. In both cases, you will want to use an equivalent of strcpy() to copy your strings.
Edit: To respond to the comment:
You're declaring an array of 30 char pointers with the first three elements pointing to buffers the size of the strings, ie the buff pointed to by sXSongBuffer[0] won't hold any string larger than "Thriller" and if he does sXSongBuffer[0] = malloc(32); He'll get a minor memory leek. Also, he'll have to malloc memory for each of the rest of the slots in the array. He should either use 2d char arrays like in the OP + a designated init, or malloc each buffer at run time and copy in the values. He'll also need to remember to free any memory he mallocs.
sXSongBuffer in char *sXSongBuffer[30]; is an array of size 30, with each element being a char *, a pointer to char. When I do:
char *sXSongBuffer[30];
each of those 30 pointers is uninitialized. When I do:
char *sXSongBuffer[30] = { "Thriller", ... };
I set the pointers to different read-only locations. There is nothing preventing me to then "re-point" the pointers somewhere else. It is as if I had:
char *data = "Hello";
printf("%s\n", data);
data = "Hello, world";
printf("%s\n", data);
In the above snippet, I assign data to "Hello" first, and then change it to point to a longer string later. The code I had above in my answer did nothing more than reassign sXSongBuffer[i] to something else later, and since sXSongBuffer[i] is a pointer, the assignment is OK. In particular, sXSongBuffer[0] is a char *, and can point to any valid location that has a char in it.
As I said later in my answer, if the strings aren't known at compile-time, this scheme doesn't work, and one has to either use arrays with "big enough" sizes, or dynamically allocate memory that's big enough.
C does not have general-purpose array literals. The {} list syntax only works when initializing, i.e. when assigning the value in the same statement that declares the variable.
You cannot just write
char sXSongBuffer[20][30];
sXSongBuffer = {"Thriller", "Don't Stop Till You Get Enough", "Billy Jean"};
You must either initialize array at once (but it will containt only 3 items):
char * sXSongBuffer[]= {"Thriller", "Don't Stop Till You Get Enough", "Billy Jean"};
Or either use stnrcpy on every item:
char sXSongBuffer[20][30];
strncpy(sXSongBuffer[0],"Thriller",29);
strncpy(sXSongBuffer[1],"Don't Stop Till You Get Enough",29);
strncpy(sXSongBuffer[2],"Billy Jean",29);
Take a look at Designated Initializers.
#include <stdio.h>
int main (void) {
char a[6][6] = { [2] = "foo", [4] = "bar" };
for (int i=0; i<6; ++i)
printf("%d == %s\n", i, a[i]);
return 0;
}
This is a c99 feature. Compile with:
gcc -W -std=c99 2dInit.c -o 2dInit
This outputs:
0 ==
1 ==
2 == foo
3 ==
4 == bar
5 ==
In your case you want to do:
char sXSongBuffer[20][30] = {
[0] = "Thriller",
[1] = "Don't Stop Till You Get Enough",
[2] = "Billy Jean"
};
Related
I'm pretty new to C and starting to play with pointers. I haven't found a way to assign an array to multiple variables.
What I want ideally is:
char myArray[10] = "test";
char (*p)[10] = &myArray;
char anotherArray[10];
anotherArray = *p;
This doesn't work and I don't know why.
I have found a way to "copy" the array by using a for loop,
for (int i = 0; i < 10; i++)
{
anotherArray[i] = myArray[i];
}
I don't know if it's good practice to do it and if there is an easier way.
The array content is not supposed to change so I just want to have a simple way to do this:
firstArr[size] = "content";
secondArr = firstArr;
You can't assign arrays in C, neither by itself nor by dereferencing pointers to arrays, the syntax simply doesn't allow it.
Arrays are normally copied with memcpy. In case they are strings, you can also use strcpy, which copies up until it finds the string null terminator.
In your example, this would be strcpy(anotherArray, *p);. But to use an array pointer of type char (*)[10] is a bit weird practice, it is far more common to use a pointer to the first element of the array. I would recommend that you change your code to this:
#include <stdio.h>
#include <string.h>
int main(void)
{
char input[10] = "test";
char* p = input;
char anotherArray[10];
strcpy(anotherArray, p);
puts(anotherArray);
}
You can't assign an array to multiple variables, but you can assign multiple variables to point to an array.
Pointers are all about memory and the memory that they point to.
Statements such as this assign a fixed amount of memory (10 char sized bytes of memory) to the variable myArray and initialises the contents to contain "test1".
char myArray[10] = "test1";
By definition myArray is actually a pointer to the first memory location, which in this case holds a char of value 't', but it is fixed to that memory.
You can define another pointer to type char and assign it the same value as the pointer to the memory that holds the data "test1" - thus:
char *secondPtr = myArray;
Now secondPtr and myArray both point to the same memory, which contains "test1". There aren't two copies of the data, but it may appear so if you did
printf("myArray %s", myArray);
printf("secondPtr %s", secondPtr);
Now you can use either myArray or secondPtr to alter the same data, which is why pointers should be treated with care.
Now as secondPtr is just a pointer to a char and as such it isn't fixed in the same way that myArray is, so you can do this:
char myArray2[10] = "test2";
secondPtr = myArray;
printf("secondPtr %s", secondPtr);
secondPtr = myArray2;
printf("secondPtr %s", secondPtr);
To copy data from one array to another you can use memcpy, which will copy a specified number of bytes(octets) of memory from one location to another.
The same process is performed by a loop (this is basic code, but not really the best way of performing it as there are no checks on the size of the arrays nor on the number of loop iterations)e.g.
for(int i=0; i<10; i++)
{
myArray2[i] = myArray[i];
}
this can also be:
secondPtr = myArray2;
for(int i=0; i<10; i++)
{
myArray2[i] = secondPtr +i;
}
I've been trying for a while now and I can not seem to get this working:
char** fetch (char *lat, char*lon){
char emps[10][50];
//char** array = emps;
int cnt = -1;
while (row = mysql_fetch_row(result))
{
char emp_det[3][20];
char temp_emp[50] = "";
for (int i = 0; i < 4; i++){
strcpy(emp_det[i], row[i]);
}
if ( (strncmp(emp_det[1], lat, 7) == 0) && (strncmp(emp_det[2], lon, 8) == 0) ) {
cnt++;
for (int i = 0; i < 4; i++){
strcat(temp_emp, emp_det[i]);
if(i < 3) {
strcat(temp_emp, " ");
}
}
strcpy(emps[cnt], temp_emp);
}
}
}
mysql_free_result(result);
mysql_close(connection);
return array;
Yes, I know array = emps is commented out, but without it commented, it tells me that the pointer types are incompatible. This, in case I forgot to mention, is in a char** type function and I want it to return emps[10][50] or the next best thing. How can I go about doing that? Thank you!
An array expression of type T [N][M] does not decay to T ** - it decays to type T (*)[M] (pointer to M-element array).
Secondly, you're trying to return the address of an array that's local to the function; once the function exits, the emps array no longer exists, and any pointer to it becomes invalid.
You'd probably be better off passing the target array as a parameter to the function and have the function write to it, rather than creating a new array within the function and returning it. You could dynamically allocate the array, but then you're doing a memory management dance, and the best way to avoid problems with memory management is to avoid doing memory management.
So your function definition would look like
void fetch( char *lat, char *lon, char emps[][50], size_t rows ) { ... }
and your function call would look like
char my_emps[10][50];
...
fetch( &lat, &lon, my_emps, 10 );
What you're attempting won't work, even if you attempt to cast, because you'll be returning the address of a local variable. When the function returns, that variable goes out of scope and the memory it was using is no longer valid. Attempting to dereference that address will result in undefined behavior.
What you need is to use dynamic memory allocation to create the data structure you want to return:
char **emps;
emps = malloc(10 * sizeof(char *));
for (int i=0; i<10; i++) {
emps[i] = malloc(50);
}
....
return emps;
The calling function will need to free the memory created by this function. It also needs to know how many allocations were done so it knows how many times to call free.
If you found a way to cast char emps[10][50]; into a char * or char **
you wouldn't be able to properly map the data (dimensions, etc). multi-dimensional char arrays are not char **. They're just contiguous memory with index calculation. Better fit to a char * BTW
but the biggest problem would be that emps would go out of scope, and the auto memory would be reallocated to some other variable, destroying the data.
There's a way to do it, though, if your dimensions are really fixed:
You can create a function that takes a char[10][50] as an in/out parameter (you cannot return an array, not allowed by the compiler, you could return a struct containing an array, but that wouldn't be efficient)
Example:
void myfunc(char emp[10][50])
{
emp[4][5] = 'a'; // update emp in the function
}
int main()
{
char x[10][50];
myfunc(x);
// ...
}
The main program is responsible of the memory of x which is passed as modifiable to myfunc routine: it is safe and fast (no memory copy)
Good practice: define a type like this typedef char matrix10_50[10][50]; it makes declarations more logical.
The main drawback here is that dimensions are fixed. If you want to use myfunc for another dimension set, you have to copy/paste it or use macros to define both (like a poor man's template).
EDITa fine comment suggests that some compilers support variable array size.
So you could pass dimensions alongside your unconstrained array:
void myfunc(int rows, int cols, char emp[rows][cols])
Tested, works with gcc 4.9 (probably on earlier versions too) only on C code, not C++ and not in .cpp files containing plain C (but still beats cumbersome malloc/free calls)
In order to understand why you can't do that, you need to understand how matrices work in C.
A matrix, let's say your char emps[10][50] is a continuous block of storage capable of storing 10*50=500 chars (imagine an array of 500 elements). When you access emps[i][j], it accesses the element at index 50*i + j in that "array" (pick a piece of paper and a pen to understand why). The problem is that the 50 in that formula is the number of columns in the matrix, which is known at the compile time from the data type itself. When you have a char** the compiler has no way of knowing how to access a random element in the matrix.
A way of building the matrix such that it is a char** is to create an array of pointers to char and then allocate each of those pointers:
char **emps = malloc(10 * sizeof(char*)); // create an array of 10 pointers to char
for (int i = 0; i < 10; i++)
emps[i] = malloc(50 * sizeof(char)); // create 10 arrays of 50 chars each
The point is, you can't convert a matrix to a double pointer in a similar way you convert an array to a pointer.
Another problem: Returning a 2D matrix as 'char**' is only meaningful if the matrix is implemented using an array of pointers, each pointer pointing to an array of characters. As explained previously, a 2D matrix in C is just a flat array of characters. The most you can return is a pointer to the [0][0] entry, a 'char*'. There's a mismatch in the number of indirections.
i am kind of new in c and i am trying to figure things out.
my question is, what i need to have in the place of '/0' , in order for it to skip
the "empty" cells?
i know i could do it the easy way and just have have all the .anoxi values in the condition, but i was just curious.
i have tried putting "", which gives me all the names (doesn't skip any of them) , '' which gives me "[Error] empty character constant" and
null, which gives me "[Error] 'null' was not declared in this scope"
struct t {
char anoxi[10];
char name[10];
char gramma [2];
}
int main() {
struct t array[5][12];
int r;
strcpy(array[4][1].anoxi, "+-1%");
strcpy(array[4][2].anoxi, "+-2%");
strcpy(array[4][5].anoxi, "+-0.5%");
strcpy(array[4][6].anoxi, "+-0.25%");
strcpy(array[4][7].anoxi, "+-1%");
strcpy(array[4][8].anoxi, "+-0.05%");
strcpy(array[0][0].gramma, "M");
strcpy(array[0][1].gramma, "K");
strcpy(array[0][2].gramma, "N");
strcpy(array[0][3].gramma, "O");
strcpy(array[0][4].gramma, "I");
strcpy(array[0][5].gramma, "R");
strcpy(array[0][6].gramma, "L");
strcpy(array[0][7].gramma, "V");
strcpy(array[0][8].gramma, "G");
strcpy(array[0][9].gramma, "A");
strcpy(array[0][10].gramma, "X");
strcpy(array[0][11].gramma, "S");
strcpy(array[1][0].name, "Black");
strcpy(array[1][1].name, "Brown");
strcpy(array[1][2].name, "Red");
strcpy(array[1][3].name, "Orange");
strcpy(array[1][4].name, "Yellow");
strcpy(array[1][5].name, "Green");
strcpy(array[1][6].name, "Blue");
strcpy(array[1][7].name, "Purple");
strcpy(array[1][8].name, "Grey");
strcpy(array[1][9].name, "White");
strcpy(array[1][10].name, "Gold");
strcpy(array[1][11].name, "Silver");
for (r=0; r<12; r++) {
if (array[4][r].anoxi!= '\0') {
printf("%s = %s\n",array[0][r].gramma, array[1][r].name);
}
}
return(0);
}
C has no concept of "empty". Variables in C represent actual physical memory locations, and they contain whatever that memory contains, which is either what they were initialized to contain, or some random value if they were never initialized (note that statics are initialized by default).
This doesn't prevent you from choosing to interpret one of the possible values of a variable as "empty", but that would be your choice, and entirely up to you. You would then have to initialize your variable/array with that value and check for it. Character variables often use the value '\0' for this, which should work for you--just make sure you take care of the difference between single characters and arrays: for example, ... if...gramma[0] == '\0'' ...
There is what you might consider an exception to this: one of the values pointer variables are allowed to take is a value called NULL, which is guaranteed not to point to anything. This is often used to initialize pointer variables but you still have to do the initialization and checking yourself.
Now that you got, it you may want to read my Structs (C), which offers a compact example, that might come in handy*.
First of all, allow me to question the validity of this code. Consider this equivalent example I made:
#include <stdio.h>
struct t {
char anoxi[10];
char name[10];
char gramma [2];
};
int main(void) {
struct t my_array[5][1];
if(my_array[0][0].anoxi != '\0')
printf("%s\n", my_array[0][0].anoxi);
return 0;
}
It will print, in my machine:
gsamaras#gsamaras-A15:~$ gcc -Wall px.c
gsamaras#gsamaras-A15:~$ ./a.out
����
Why?
Because, the memory the array holds is not initialized to anything, so its value is undefined, which invokes UNDEFINED BEHAVIOR!
We could fix this, by initializing every string, like this:
struct t my_array[5][1];
my_array[0][0].anoxi[0] = '\0';
if(my_array[0][0].anoxi[0] != '\0')
printf("edw %s\n", my_array[0][0].anoxi);
Or, as Mike suggested, you could use memset(), like this:
memset (my_array, 0, sizeof (my_array);
Usually we set the value of a variable to a predefined value, which for us, humans tells that this cell/string/whatever is empty.
c does not know that, unless we tell our program to keep an eye out of empty "things". We have to inform our program what is an empty "thing", especially how to identify it!
Here, you have a string and you check array[4][r].anoxi!= '\0', which is always true because the left-hand side is an array, which decays to pointer in this expression, as M.M said.
*I am not writing it here, since the answer is already too long
First of all, initialize the array to blank:
struct t array[5][12] = { 0 };
This means that any members you have not yet assigned contents to will have value 0 (converted to the type of that member). This is so that later on you can see if the member has been assigned something else by checking to see if it is still 0 or not.
Then you can check:
if ( array[4][r].anoxi[0] ) {
// ^^^^
Note that you must check anoxi[0] which is a char object. Checking anoxi, which is an array object, merely checks that the array exists in memory (which it tautologically does), not whether the contents of the array are some particular value.
NB. The != '\0' is redundant, I think it is clearer to omit it but you could use it if you want.
I am new to C, and things are different in C than in any other language I've learned. In my homework I want to create an array of chars which point to an array of chars, but rather than make a multidimensional char array, I figure I'd have more control and create char arrays and put each individual one into the indexes of the original char array:
char keywords[10];
keywords[0] = "float";
The above example is to clarify and a simple case. But my question is due to the research I've been doing, and I am confused about something. Normally this would work in other languages, but in C it would be:
char *keyword[10];
keywords[0] = "float";
But when I want to send it through a function, why is this necessary:
void function(char **keyword); //function prototype
Wouldn't just passing the array pointer be enough?
It looks like you're confused by the double stars in
void function(char ** keyword);
The double stars just means that this function expects you to pass a pointer to a pointer to a char. This syntax doesn't include any information about the fact that you are using an array, or that the char is actually the first char of many in a string. It's up to you as the programmer to know what kind of data structure this char ** actually points to.
For example, let's suppose the beginning of your array is stored at address 0x1000. The keyword argument to the function should have a value of 0x1000. If you dereference keyword, you get the first entry in the array, which is a char * that points to the first char in the string "float". If you dereference the char *, you get the char "f".
The (contrived) code for that would look like:
void function(char **keyword)
{
char * first_string = *keyword; // *keyword is equivalent to keyword[0]
char first_char = *first_string; // *first_string is equivalent to first_string[0]
}
There were two pointers in the example above. By adding an offset to the first pointer before dereferencing it, you can access different strings in the array. By adding an offset to the second pointer before dereferencing it, you can access different chars in the string.
char *keyword[10];
keyword is an array 10 of char *. In a value context, it converted to a pointer to a char *.
This conversion is a part of what Chris Torek calls "The Rule":
"As noted elsewhere, C has a very important rule about arrays and pointers. This rule -- The Rule -- says that, in a value context, an object of type ‘array of T’ becomes a value of type ‘pointer to T’, pointing to the first element of that array"
See here for more information: http://web.torek.net/torek/c/pa.html
The C-FAQ also has an entry on this array to pointer conversion:
Question 6.3: So what is meant by the "equivalence of pointers and arrays'' in C?
http://c-faq.com/aryptr/aryptrequiv.html
In C, you can't really pass array to a function. Instead, you pass a pointer to the beginning of the array. Since you have array of char*, the function will get a pointer to char*, which is char**.
If you want, you can write (in the prototype) char *keyword[] instead of char **keyword. The compiler will automatically convert it.
Also, in C you can dereference pointers like arrays, so you loose almost nothing with that "converting to pointer".
If you want to
void function(char **keyword);
Andy, think about that an array is just a pointer(to the beginning of the array), that's why you write:
void function(char **keyword);
Because you have create an array to char pointers.
If it's easier to understand try:
void function(char *keyword[]);
But it's more C standard to use the first one, though if you use a C++ compiler won't really matter.
Here is the answer.
#include<stdio.h>
int main(void)
{
char *CharPtr[3];
char a[4]="abc";
char b[4]="def";
char c[4]="ghi";
CharPtr[0]=a;
CharPtr[1]=b;
CharPtr[2]=c;
printf("\n content of CharPtr[0] =%s",CharPtr[0]);
printf("\n content of CharPtr[1] =%s",CharPtr[1]);
printf("\n content of CharPtr[2] =%s\n",CharPtr[2]);
printf(" \n content of char a[4]=%s",a);
printf(" \n content of char b[4]=%s",b);
printf(" \n content of char c[4]=%s\n",c);
}
char *keywords[10] is an array of character pointers. So keywords[0], keywords[1].. and so on will have the addresses to different character arrays.
In printf you can use %s and keywords[0] to print the entire character array whose address(i.e. address of the first byte in the array) is stored at keywords[0].
While passing to a function, if you give *keywords, you are referring to the value at(address stored at keywords[0]) which is again an address. So, to get the value instead of address, you can add another *... Hope that clarifies a bit..
I am assuming that you are assigning your first string:
"float"
to the first index position of keyword[0]
char keyword[0] = "float";
which is the first index position of the array:
char keyword[10];
If the previous is the case, then in a sense, you are essentially creating a data structure that holds a data structure. The array of any type is the 'smallest' data structure of that type in C. Considering that in your example you are creating a character array, then you are actually utilizing the smallest data type (char=1bit) at each index position of the smallest built in data structure (the array).
With that said, if in your example, you are attempting to create an array of arrays; your character array
/* Hold ten characters total */
char keyword[10];
was designed to hold 10 characters. One at each index position (which you probably already know). So after declaring the array titled keyword, you then try to initialize the first index position of the array with another (the second) character array:
/* I believe this is what you had stated */
char keywords[0] = "float";
With the second character array having an index of 5 positions in size.
In order to achieve your desired goal, you would essentially be creating an array that basically emulates the effect of a data structure that 'holds' other data structures.
NOTE: If you had/have plans on trying to create a data structure that holds a data structure that holds a data structure. A.K.A. a triple nested data structure and in this case I think that would be a Matrix, WHICH I WOULDN'T RECOMMEND!
None the less, the matrix structure would be in the form of the first index position of keyword, being assigned the whole array of keywords, which would include all of the data stored in each index position of the keywords array. Then there would something probably like: keywords1, keywords2, ... keywords9,
which would essentially emulate the form of:
char *keyword[10] = {
char *keywords0[10] = {"float", etc, etc, etc.};
char *keywords1[10] = {"keyword1", "secondIndexOfThisArray", etc, etc, etc.};
and so
};
So basically from right to left, the keyword array, is an array of pointers that points to array of pointers that points to character arrays.
If that is what you are representing you would be better defining a custom data type of struct/record, and with in that custom structure you would want to define a subordinate or child level of structures. You could also pre-declare them then initialize them.
e.g.
typedef *nestedDataStructures {
struct keyWords[];
struct keyWords1[];
struct keyWords2[];
... and so on.
}; nestedDataStructures
Instead of adding ten structs to one custom structure I would break down into 3 or 4 (how ever many structures and use) and create a module in order to yield symmetrical layers of abstraction as you manipulate your data set.
None the less, you can not create the character array and potentially assign the other character array in the fashion that you did (or who knows maybe you can), but the way you would want to emulate the array that holds arrays, is to create a character pointer array up front, of X number index positions and then initialize then use the character arrays in the form of a strings declared with in the initialization of the original declaration.
So basically you could declare your whole array upfront, then with in your program design, either dereference each index position, use assignment, or print/write the index position.
Like for instance you could always do something like this:
/* Example of the program and declaration with out a function */
#include <stdio.h>
int main(){
/*
* A character pointer array that contains multiple
* character arrays.
*/
char *grewMe[2] = {"I want to ", "grow to be bigger"};
int w = 0;
for(; w < 2;) {
printf("%s", grewMe[w]);
++w;
}
printf(" :-)\n");
w = 0;
return 0;
}
// Output:
// I want to grow to be bigger :-)
Or something like this:
/* Example of program: function passed arguments
* of a pointer to the array of pointers
*/
#include <stdio.h>
void mygrowth(char *growMe[]);
int main(){
char *growMe[2] = {"I want to ", "grow to be bigger"};
mygrowth(growMe);
printf(" :-)\n");
return 0;
}
void mygrowth(char *growMe[])
{
int w = 0;
for (; w < 2;) {
printf("%s", growMe[w]);
++w;
}
}
The assignment of each index position as it's passed as an argument:
/*
* This program compiles, runs and outputs properly
* Example of a program with a function of
* arguments pnt2pnter
*/
#include <stdio.h>
#include <stdlib.h>
void thoughtAsAFunction(char **iThink);
int main()
{
char *iThink[10] = {"I am trying to grow, but it's a hard task to ",
"accomplish. My father is short ",
"my mother is even shorter than him, ",
"what is the probability of me getting taller? ",
"Well both my grandfather's were Six ",
"Foot Five, and both my grandmother's ",
"were over 5 foot 8 inches tall! If my ",
"grandparent's genes point to my parents, and my ",
"parent's genes point to mine I might have a chance ",
"of being 6 foot. Do you know what I mean? "};
thoughtAsAFunction(iThink);
printf(":-)\n");
return 0;
}
void thoughtAsAFunction(char **iThink) {
int andy = 0;
for (; andy < 10;) {
char * pntThroughPnt = iThink[andy];
printf("%s", pntThroughPnt);
++andy;
}
andy = 0;
}
Or pass by reference, with an increment of the loop count variable:
/*
* This program compiles, runs, and outputs all of the character
* arrays.
*
*/
#include <stdio.h>
#include <stdlib.h>
void thoughtAsAFunction(char **iThink);
int main()
{
char *iThink[10] = {"I am trying to grow, but it's a hard task to ",
"accomplish. My father is short ",
"my mother is even shorter than him, ",
"what is the probability of me getting taller? ",
"Well both my grandfather's were Six ",
"Foot Five, and both my grandmother's ",
"were over 5 foot 8 inches tall! If my ",
"grandparent's genes point to my parents, and my ",
"parent's genes point to mine, then I might have a chance ",
"of being 6 foot. Do you know what I mean? "};
int andy = 0;
for (; andy < 10;) {
// pass by reference and increment.
thoughtAsAFunction(&iThink[andy]);
++andy;
}
printf(":-)\n");
andy = 0;
return 0;
}
void thoughtAsAFunction(char **iThink) {
char * pntThroughPnt = *iThink;
printf("%s", pntThroughPnt);
}
Keep in mind that this is the case if you declare the array of pointers (char *array[10];), and each pointer points to an array of characters.
/*
* PURPOSE
* Search if a string contains a string and print it out from there
*/
#include <stdio.h>
void searchHaystack(char cHaystack[], char cNeedle[]);
void showResult(int iOffset, char cHaystack[]);
int main() {
// Declarations
char cHaystack[50], cNeedle[50];
// Input
puts("Haystack:");
gets(cHaystack);
puts("Needle:");
gets(cNeedle);
// Call searcher
searchHaystack(cHaystack, cNeedle);
return 0;
}
void searchHaystack(char cHaystack[], char cNeedle[]) {
// Declarations
int iCntr, iCntr2, iFoundOffset;
// Search the haystack for the first letter of the needle
for (iCntr == 0; iCntr < 50 && cHaystack[iCntr] != '\0'; iCntr++) {
if (cHaystack[iCntr] == cNeedle[0]) {
iFoundOffset = iCntr;
for (iCntr2 == 1; iCntr2 < 50 && (cHaystack[iCntr+iCntr2] == cNeedle[iCntr2] || cNeedle[iCntr2] == '\0'); iCntr2++) {
if (cNeedle[iCntr2] == '\0') {
showResult(iFoundOffset, cHaystack);
}
}
}
}
}
void showResult(int iOffset, char cHaystack[]) {
int iCntr;
// Print the substring char by char
for (iCntr == iOffset; iCntr < 50 && cHaystack[iCntr] != '\0'; iCntr++) {
printf("%c", cHaystack[iCntr]);
}
printf("\n");
}
Looking at my debugger I noticed that cHaystack[] and cNeedle[] aren't passed to searchHaystack properly as only the first char is conserved. How do I fix this? I haven't learned about pointers yet.
Also, I'm getting this warning on all three for loops:
statement with no effect
What's up with that?
Actually, the entire array IS being passed, the debugger only shows the first char by default because in C, the system does not know the size of an array. It is something the program has to keep track of. Since you are using strings though, which are typically null terminated, try setting the watch variable "(char*)cHaystack" (without quotes) and see what the debugger shows then.
Also, assignment statements should have one = sign, not the double == sign. So:
for (iCntr = 0; ...
Should be used, NOT:
for (iCntr == 0; ...
Same with the other for loops.
You're starting the loop with iCntr == 0
This is a comparison, so it does not set iCntr to zero.
Use iCntr = 0 (a single equals sign)
The values are passed properly, but your expectation of how your debugger should display them is incorrect. As already mentioned, there is no string type in C. Instead, C uses char* variables -- pointers to characters; your char[] are equivalent to char*.
You know that the pointed-to character is the first character in a longer string, but the debugger doesn't. It displays the character that the pointer points to -- which you know to be the first of a longer string. The debugger, however, only knows it's a char*, and there must be a char to be pointed at, so it displays that char.
These are character arrays not strings. In C string are of type char * and you have to allocate the memory for them.
Of course when you say varname[5] that is the same as saying *(varname+5)
Basically you are going to have to learn about pointers to use strings in C.
EDIT
As pointed out below (and above by me) you can use character arrays like strings in C. HOWEVER, my point is that if you don't learn a little bit about pointers you are going to be in big trouble.
For example:
Not being able to view the string in the debugger.
Not putting a null as the last character in the array and having crazy random bugs
Forgetting that you only allocated X bytes for the array and going over the end
etc.
If you don't understand how pointers work in C, it is really hard -- if not impossible to work with the language.
I expect the prof will cover it next week.
Arrays are not first-class objects in C; when you pass an array as a function parameter, the type of the array expression is implicitly converted from "N-element array of T" to "pointer to T", and its value is set to point to the first element in the array[1].
In the context of a function parameter declaration, int a[] is the same as int *a (but this is true only in the context of a function parameter declaration); your searchHaystack function receives two pointers to char, which correspond to the first elements of the respective arrays. The debugger doesn't show you the whole array, because in the context of the function they are not arrays.
Also, NEVER, NEVER, NEVER USEgets(). Ever. It will introduce a point of failure in your code. Use fgets() instead. C does no bounds checking on arrays. If you call gets() for a buffer sized to hold 10 characters, and the user types in 100 characters, gets() will happily store those extra 90 characters in the memory following your buffer, potentially clobbering something important and leading to a crash or worse (buffer overruns are a common exploit for malware; the Morris worm exploited a call to gets() in sendmail).
The warning is coming from you using == instead of = to assign your loop counters.
The exceptions to this rule are when the array expression is an operand of either the sizeof or address-of (&) operators, or when the array is a string literal being used to initialize another array in a declaration.
The warning is probably caused by
iCntr == 0,iCntr2 == 1, iCntr == iOffset
I guess you were going, in fact, for:
iCntr = 0,iCntr2 = 1, iCntr = iOffset
As for passing the arrays, you could do something like ( using pointers ):
void searchHaystack(char* cHaystack, int cHaystackSize, char* cNeedle, int cNeedleSize )
...
for (iCntr = 0; iCntr < cHaystackSize && cHaystack[iCntr] != '\0'; ++iCntr )